Commit b9b6d10b authored by Luker's avatar Luker

Connect Service_Info to handler

Signed-off-by: Luker's avatarLuca Fulchir <luker@fenrirproject.org>
parent 9123d5a6
......@@ -27,6 +27,7 @@
#include "Fenrir/v1/net/Handshake.hpp"
#include "Fenrir/v1/plugin/Loader.hpp"
#include "Fenrir/v1/service/Service_ID.hpp"
#include "Fenrir/v1/service/Service_Info.hpp"
#include "Fenrir/v1/util/Shared_Lock.hpp"
#include <map>
#include <memory>
......@@ -76,6 +77,39 @@ public:
void connect (const std::vector<uint8_t> &dest, const Service_ID &service);
std::unique_ptr<Report::Base> get_report();
private:
struct FENRIR_LOCAL Vhost_Service :
type_safe::strong_typedef<Vhost_Service,
std::pair<Service_ID, std::vector<uint8_t>>>,
type_safe::strong_typedef_op::equality_comparison<Vhost_Service>
{
using strong_typedef::strong_typedef;
bool operator< (const Vhost_Service &rhs) const
{
// see issue #1
// try to make this parse the whole pair instead of returning early
// TODO: this is clumsy. better ides to avoid branching?
const auto *a = reinterpret_cast<const std::pair<
Service_ID, std::vector<uint8_t>>*> (this);
const auto *b = reinterpret_cast<const std::pair<
Service_ID, std::vector<uint8_t>>*> (&rhs);
int32_t x = 0;
if (a->first < b->first) {
x -= 10;
} else {
x += 10;
}
// FIXME: issue #1: not constant time, and try to avoid branching
// we don't reall car wht the ordering is, as long as there
// actually is one
if (a->second < b->second) {
x -= 5;
} else {
x += 5;
}
return x < 0;
}
};
Shared_Lock _conn_lock, _sock_lock, _srv_lock, _res_lock;
std::mutex _rep_lock;
Event::Loop _loop;
......@@ -85,7 +119,8 @@ private:
std::shared_ptr<Rate::Rate> _rate;
std::vector<std::shared_ptr<Resolve::Resolver>> _resolvers;
std::map<Conn_ID, std::shared_ptr<Connection>> _connections;
std::vector<std::pair<Service_ID, std::shared_ptr<Connection>>> _services;
std::vector<std::pair<Vhost_Service, Service_Info>> _service_info;
std::vector<std::pair<Vhost_Service, std::shared_ptr<Connection>>>_services;
std::vector<std::pair<Link_ID, std::shared_ptr<Socket>>> _sockets;
std::deque<std::unique_ptr<Report::Base>> _user_reports;
Handshake _handshakes;
......
......@@ -40,8 +40,9 @@ struct FENRIR_LOCAL Stream_ID : type_safe::strong_typedef<Stream_ID, uint16_t>,
type_safe::strong_typedef_op::relational_comparison<Stream_ID>
{ using strong_typedef::strong_typedef; };
struct FENRIR_LOCAL Stream_PRIO : type_safe::strong_typedef<Stream_ID, uint8_t>,
type_safe::strong_typedef_op::equality_comparison<Stream_ID>
struct FENRIR_LOCAL Stream_PRIO :
type_safe::strong_typedef<Stream_PRIO, uint8_t>,
type_safe::strong_typedef_op::equality_comparison<Stream_PRIO>
{ using strong_typedef::strong_typedef; };
struct FENRIR_LOCAL Counter : type_safe::strong_typedef<Counter, uint32_t>,
......
......@@ -28,6 +28,7 @@
#include <algorithm>
#include <atomic>
#include <memory>
#include <mutex>
#include <type_safe/strong_typedef.hpp>
#include <vector>
#include <tuple>
......@@ -39,7 +40,7 @@ namespace Impl {
class FENRIR_LOCAL Service_Info
{
public:
using stream_info = std::vector<Storage_t, Stream_PRIO>;
using stream_info = std::vector<std::tuple<Storage_t, Stream_PRIO>>;
Service_Info()
: _info (nullptr)
......@@ -50,32 +51,36 @@ public:
Service_Info& operator= (Service_Info &&) = default;
~Service_Info() = default;
stream_info get_streams (const Service_ID &service) const
stream_info get_streams (const Service_ID &service)
{
auto p = _info.load();
std::lock_guard<std::mutex> lock (_mtx);
FENRIR_UNUSED (lock);
auto p = _info;
if (p == nullptr)
return stream_info{};
auto res = std::lower_bound (p->begin(), p->end(), service,
[] (const auto it, const Service_ID &id)
{
return std::get<Service_ID> (it) < id;
}
if (std::get<Service_ID> (*res) == service))
});
if (std::get<Service_ID> (*res) == service)
return std::get<stream_info> (*res);
return stream_info{};
}
Lattice get_lattice (const Service_ID &service) const
Lattice get_lattice (const Service_ID &service)
{
auto p = _info.load();
std::lock_guard<std::mutex> lock (_mtx);
FENRIR_UNUSED (lock);
auto p = _info;
if (p == nullptr)
return Lattice{};
auto res = std::lower_bound (p->begin(), p->end(), service,
[] (const auto it, const Service_ID &id)
{
return std::get<Service_ID> (it) < id;
}
if (std::get<Service_ID> (*res) == service))
});
if (std::get<Service_ID> (*res) == service)
return std::get<Lattice> (*res);
return Lattice{};
}
......@@ -83,28 +88,34 @@ public:
bool add_service (const Service_ID id, stream_info &streams,
Lattice &lattice)
{
std::shared_ptr<std::vector<std::tuple<Service_ID, stream_info>>>
current, copy;
do {
current = _info.load();
while (true) {
std::shared_ptr<std::vector<std::tuple<
Service_ID, stream_info, Lattice>>> current, copy;
current = _info;
size_t cur_size = 0;
if (current != nullptr)
cur_size = current->size();
copy = std::make_shared<std::vector<
std::tuple<Service_ID, stream_info>>> (
std::tuple<Service_ID, stream_info, Lattice>>> (
cur_size + 1);
for (size_t idx = 0; idx < cur_size; ++idx) {
copy->push_back ((*current)[idx]);
}
copy->emplace_back (id, streams, lattice);
} while (!_info.compare_exchange_strong (current, copy));
std::lock_guard<std::mutex> lock (_mtx);
FENRIR_UNUSED (lock);
if (_info.get() == copy.get()) {
_info = current;
break;
}
}
return true;
}
private:
// TODO: test thread safety
std::atomic<std::shared_ptr<std::vector<
std::tuple<Service_ID, stream_info, Lattice>>>> _info;
std::mutex _mtx;
std::shared_ptr<std::vector<
std::tuple<Service_ID, stream_info, Lattice>>> _info;
};
} // namespace Impl
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment