Make Distributed Singleton (and remove unused code)
Reviewers: sasa.stanko, buda Reviewed By: sasa.stanko Differential Revision: https://phabricator.memgraph.io/D694
This commit is contained in:
parent
8f33269b03
commit
abedfb29b1
experimental/distributed
@ -21,12 +21,12 @@ uint16_t SenderMessage::Port() const { return port_; }
|
|||||||
std::string SenderMessage::ReactorName() const { return reactor_; }
|
std::string SenderMessage::ReactorName() const { return reactor_; }
|
||||||
std::string SenderMessage::ChannelName() const { return channel_; }
|
std::string SenderMessage::ChannelName() const { return channel_; }
|
||||||
|
|
||||||
std::shared_ptr<Channel> SenderMessage::GetChannelToSender(
|
std::shared_ptr<Channel> SenderMessage::GetChannelToSender() const {
|
||||||
Distributed *distributed) const {
|
|
||||||
if (address_ == FLAGS_address && port_ == FLAGS_port) {
|
if (address_ == FLAGS_address && port_ == FLAGS_port) {
|
||||||
return System::GetInstance().FindChannel(reactor_, channel_);
|
return System::GetInstance().FindChannel(reactor_, channel_);
|
||||||
|
} else {
|
||||||
|
// TODO(zuza): we should probably assert here if services have been already started.
|
||||||
|
return Distributed::GetInstance().network().Resolve(address_, port_, reactor_, channel_);
|
||||||
}
|
}
|
||||||
if (distributed)
|
|
||||||
return distributed->network().Resolve(address_, port_, reactor_, channel_);
|
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
@ -225,8 +225,6 @@ class Network {
|
|||||||
std::unique_ptr<NetworkServer> server_{nullptr};
|
std::unique_ptr<NetworkServer> server_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
class Distributed;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message that includes the sender channel used to respond.
|
* Message that includes the sender channel used to respond.
|
||||||
*/
|
*/
|
||||||
@ -240,7 +238,7 @@ class SenderMessage : public Message {
|
|||||||
std::string ReactorName() const;
|
std::string ReactorName() const;
|
||||||
std::string ChannelName() const;
|
std::string ChannelName() const;
|
||||||
|
|
||||||
std::shared_ptr<Channel> GetChannelToSender(Distributed *distributed = nullptr) const;
|
std::shared_ptr<Channel> GetChannelToSender() const;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive &ar) {
|
void serialize(Archive &ar) {
|
||||||
@ -274,17 +272,23 @@ class ChannelResolvedMessage : public Message {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Placeholder for all functionality related to non-local communication
|
* Placeholder for all functionality related to non-local communication.
|
||||||
|
*
|
||||||
* E.g. resolve remote channels by memgraph node id, etc.
|
* E.g. resolve remote channels by memgraph node id, etc.
|
||||||
|
* Alive through the entire process lifetime.
|
||||||
|
* Singleton class. Created automatically on first use.
|
||||||
*/
|
*/
|
||||||
class Distributed {
|
class Distributed {
|
||||||
public:
|
public:
|
||||||
Distributed() {}
|
/**
|
||||||
|
* Get the (singleton) instance of Distributed.
|
||||||
Distributed(const Distributed &) = delete;
|
*
|
||||||
Distributed(Distributed &&) = delete;
|
* More info: https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
|
||||||
Distributed &operator=(const Distributed &) = delete;
|
*/
|
||||||
Distributed &operator=(Distributed &&) = delete;
|
static Distributed &GetInstance() {
|
||||||
|
static Distributed distributed; // guaranteed to be destroyed, initialized on first use
|
||||||
|
return distributed;
|
||||||
|
}
|
||||||
|
|
||||||
void StartServices() {
|
void StartServices() {
|
||||||
network_.StartClient(4);
|
network_.StartClient(4);
|
||||||
@ -321,15 +325,13 @@ class Distributed {
|
|||||||
Network &network() { return network_; }
|
Network &network() { return network_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Distributed() {}
|
||||||
|
|
||||||
Network network_;
|
Network network_;
|
||||||
};
|
|
||||||
|
private:
|
||||||
|
Distributed(const Distributed &) = delete;
|
||||||
class DistributedReactor : public Reactor {
|
Distributed(Distributed &&) = delete;
|
||||||
public:
|
Distributed &operator=(const Distributed &) = delete;
|
||||||
DistributedReactor(std::string name, Distributed &distributed)
|
Distributed &operator=(Distributed &&) = delete;
|
||||||
: Reactor(name), distributed_(distributed) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Distributed &distributed_;
|
|
||||||
};
|
};
|
||||||
|
@ -465,7 +465,7 @@ class Reactor {
|
|||||||
*
|
*
|
||||||
* E.g. holds set of reactors, channels for all reactors.
|
* E.g. holds set of reactors, channels for all reactors.
|
||||||
* Alive through the entire process lifetime.
|
* Alive through the entire process lifetime.
|
||||||
* Singleton class. Created automatically.
|
* Singleton class. Created automatically on first use.
|
||||||
*/
|
*/
|
||||||
class System {
|
class System {
|
||||||
public:
|
public:
|
||||||
|
@ -13,7 +13,15 @@ class MemgraphDistributed : public Distributed {
|
|||||||
using Location = std::pair<std::string, uint16_t>;
|
using Location = std::pair<std::string, uint16_t>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemgraphDistributed(System &system) : Distributed() {}
|
/**
|
||||||
|
* Get the (singleton) instance of MemgraphDistributed.
|
||||||
|
*
|
||||||
|
* More info: https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
|
||||||
|
*/
|
||||||
|
static MemgraphDistributed &GetInstance() {
|
||||||
|
static MemgraphDistributed distributed; // guaranteed to be destroyed, initialized on first use
|
||||||
|
return distributed;
|
||||||
|
}
|
||||||
|
|
||||||
/** Register memgraph node id to the given location. */
|
/** Register memgraph node id to the given location. */
|
||||||
void RegisterMemgraphNode(int64_t mnid, const std::string &address, uint16_t port) {
|
void RegisterMemgraphNode(int64_t mnid, const std::string &address, uint16_t port) {
|
||||||
@ -29,9 +37,17 @@ class MemgraphDistributed : public Distributed {
|
|||||||
return Distributed::FindChannel(location.first, location.second, reactor, channel);
|
return Distributed::FindChannel(location.first, location.second, reactor, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MemgraphDistributed() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::recursive_mutex mutex_;
|
std::recursive_mutex mutex_;
|
||||||
std::unordered_map<int64_t, Location> mnodes_;
|
std::unordered_map<int64_t, Location> mnodes_;
|
||||||
|
|
||||||
|
MemgraphDistributed(const MemgraphDistributed &) = delete;
|
||||||
|
MemgraphDistributed(MemgraphDistributed &&) = delete;
|
||||||
|
MemgraphDistributed &operator=(const MemgraphDistributed &) = delete;
|
||||||
|
MemgraphDistributed &operator=(MemgraphDistributed &&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,8 +65,7 @@ class MemgraphDistributed : public Distributed {
|
|||||||
* @return Pair (master mnid, list of worker's id).
|
* @return Pair (master mnid, list of worker's id).
|
||||||
*/
|
*/
|
||||||
std::pair<int64_t, std::vector<int64_t>>
|
std::pair<int64_t, std::vector<int64_t>>
|
||||||
ParseConfigAndRegister(const std::string &filename,
|
ParseConfigAndRegister(const std::string &filename) {
|
||||||
MemgraphDistributed &distributed) {
|
|
||||||
std::ifstream file(filename, std::ifstream::in);
|
std::ifstream file(filename, std::ifstream::in);
|
||||||
assert(file.good());
|
assert(file.good());
|
||||||
int64_t master_mnid;
|
int64_t master_mnid;
|
||||||
@ -59,6 +74,7 @@ std::pair<int64_t, std::vector<int64_t>>
|
|||||||
std::string address;
|
std::string address;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
file >> master_mnid >> address >> port;
|
file >> master_mnid >> address >> port;
|
||||||
|
MemgraphDistributed &distributed = MemgraphDistributed::GetInstance();
|
||||||
distributed.RegisterMemgraphNode(master_mnid, address, port);
|
distributed.RegisterMemgraphNode(master_mnid, address, port);
|
||||||
while (file.good()) {
|
while (file.good()) {
|
||||||
file >> mnid >> address >> port;
|
file >> mnid >> address >> port;
|
||||||
@ -71,21 +87,6 @@ std::pair<int64_t, std::vector<int64_t>>
|
|||||||
return std::make_pair(master_mnid, worker_mnids);
|
return std::make_pair(master_mnid, worker_mnids);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to the Memgraph distributed system.
|
|
||||||
*
|
|
||||||
* E.g. get channel to other Memgraph nodes.
|
|
||||||
*/
|
|
||||||
class MemgraphReactor : public Reactor {
|
|
||||||
public:
|
|
||||||
MemgraphReactor(std::string name,
|
|
||||||
MemgraphDistributed &distributed)
|
|
||||||
: Reactor(name), distributed_(distributed) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
MemgraphDistributed &distributed_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a text message and has a return address.
|
* Sends a text message and has a return address.
|
||||||
*/
|
*/
|
||||||
@ -108,16 +109,16 @@ protected:
|
|||||||
CEREAL_REGISTER_TYPE(TextMessage);
|
CEREAL_REGISTER_TYPE(TextMessage);
|
||||||
|
|
||||||
|
|
||||||
class Master : public MemgraphReactor {
|
class Master : public Reactor {
|
||||||
public:
|
public:
|
||||||
Master(std::string name, MemgraphDistributed &distributed,
|
Master(std::string name, int64_t mnid, std::vector<int64_t> &&worker_mnids)
|
||||||
int64_t mnid, std::vector<int64_t> &&worker_mnids)
|
: Reactor(name), mnid_(mnid),
|
||||||
: MemgraphReactor(name, distributed), mnid_(mnid),
|
|
||||||
worker_mnids_(std::move(worker_mnids)) {}
|
worker_mnids_(std::move(worker_mnids)) {}
|
||||||
|
|
||||||
virtual void Run() {
|
virtual void Run() {
|
||||||
std::cout << "Master (" << mnid_ << ") @ " << distributed_.network().Address()
|
MemgraphDistributed &distributed = MemgraphDistributed::GetInstance();
|
||||||
<< ":" << distributed_.network().Port() << std::endl;
|
std::cout << "Master (" << mnid_ << ") @ " << distributed.network().Address()
|
||||||
|
<< ":" << distributed.network().Port() << std::endl;
|
||||||
|
|
||||||
auto stream = main_.first;
|
auto stream = main_.first;
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ class Master : public MemgraphReactor {
|
|||||||
|
|
||||||
// send a TextMessage to each worker
|
// send a TextMessage to each worker
|
||||||
for (auto wmnid : worker_mnids_) {
|
for (auto wmnid : worker_mnids_) {
|
||||||
auto stream = distributed_.FindChannel(wmnid, "worker", "main");
|
auto stream = distributed.FindChannel(wmnid, "worker", "main");
|
||||||
stream->OnEventOnce()
|
stream->OnEventOnce()
|
||||||
.ChainOnce<ChannelResolvedMessage>([this, stream](const ChannelResolvedMessage &msg){
|
.ChainOnce<ChannelResolvedMessage>([this, stream](const ChannelResolvedMessage &msg){
|
||||||
msg.channel()->Send<TextMessage>("master", "main", "hi from master");
|
msg.channel()->Send<TextMessage>("master", "main", "hi from master");
|
||||||
@ -153,16 +154,16 @@ class Master : public MemgraphReactor {
|
|||||||
std::vector<int64_t> worker_mnids_;
|
std::vector<int64_t> worker_mnids_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Worker : public MemgraphReactor {
|
class Worker : public Reactor {
|
||||||
public:
|
public:
|
||||||
Worker(std::string name, MemgraphDistributed &distributed,
|
Worker(std::string name, int64_t mnid, int64_t master_mnid)
|
||||||
int64_t mnid, int64_t master_mnid)
|
: Reactor(name), mnid_(mnid),
|
||||||
: MemgraphReactor(name, distributed), mnid_(mnid),
|
|
||||||
master_mnid_(master_mnid) {}
|
master_mnid_(master_mnid) {}
|
||||||
|
|
||||||
virtual void Run() {
|
virtual void Run() {
|
||||||
std::cout << "Worker (" << mnid_ << ") @ " << distributed_.network().Address()
|
MemgraphDistributed &distributed = MemgraphDistributed::GetInstance();
|
||||||
<< ":" << distributed_.network().Port() << std::endl;
|
std::cout << "Worker (" << mnid_ << ") @ " << distributed.network().Address()
|
||||||
|
<< ":" << distributed.network().Port() << std::endl;
|
||||||
|
|
||||||
auto stream = main_.first;
|
auto stream = main_.first;
|
||||||
// wait until master sends us a TextMessage, then reply back and close
|
// wait until master sends us a TextMessage, then reply back and close
|
||||||
@ -170,7 +171,7 @@ class Worker : public MemgraphReactor {
|
|||||||
.ChainOnce<TextMessage>([this](const TextMessage &msg) {
|
.ChainOnce<TextMessage>([this](const TextMessage &msg) {
|
||||||
std::cout << "Message from " << msg.Address() << ":" << msg.Port() << " .. " << msg.text << "\n";
|
std::cout << "Message from " << msg.Address() << ":" << msg.Port() << " .. " << msg.text << "\n";
|
||||||
|
|
||||||
msg.GetChannelToSender(&distributed_)
|
msg.GetChannelToSender()
|
||||||
->Send<TextMessage>("worker", "main", "hi from worker");
|
->Send<TextMessage>("worker", "main", "hi from worker");
|
||||||
|
|
||||||
// Sleep for a while so we can read output in the terminal.
|
// Sleep for a while so we can read output in the terminal.
|
||||||
@ -190,13 +191,13 @@ int main(int argc, char *argv[]) {
|
|||||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||||
|
|
||||||
System &system = System::GetInstance();
|
System &system = System::GetInstance();
|
||||||
MemgraphDistributed distributed(system);
|
MemgraphDistributed& distributed = MemgraphDistributed::GetInstance();
|
||||||
auto mnids = ParseConfigAndRegister(FLAGS_config_filename, distributed);
|
auto mnids = ParseConfigAndRegister(FLAGS_config_filename);
|
||||||
distributed.StartServices();
|
distributed.StartServices();
|
||||||
if (FLAGS_my_mnid == mnids.first)
|
if (FLAGS_my_mnid == mnids.first)
|
||||||
system.Spawn<Master>("master", distributed, FLAGS_my_mnid, std::move(mnids.second));
|
system.Spawn<Master>("master", FLAGS_my_mnid, std::move(mnids.second));
|
||||||
else
|
else
|
||||||
system.Spawn<Worker>("worker", distributed, FLAGS_my_mnid, mnids.first);
|
system.Spawn<Worker>("worker", FLAGS_my_mnid, mnids.first);
|
||||||
system.AwaitShutdown();
|
system.AwaitShutdown();
|
||||||
distributed.StopServices();
|
distributed.StopServices();
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ class ChatACK : public ChatMessage {
|
|||||||
};
|
};
|
||||||
CEREAL_REGISTER_TYPE(ChatACK);
|
CEREAL_REGISTER_TYPE(ChatACK);
|
||||||
|
|
||||||
class ChatServer : public DistributedReactor {
|
class ChatServer : public Reactor {
|
||||||
public:
|
public:
|
||||||
ChatServer(std::string name, Distributed &distributed)
|
ChatServer(std::string name)
|
||||||
: DistributedReactor(name, distributed) {}
|
: Reactor(name) {}
|
||||||
|
|
||||||
virtual void Run() {
|
virtual void Run() {
|
||||||
std::cout << "ChatServer is active" << std::endl;
|
std::cout << "ChatServer is active" << std::endl;
|
||||||
@ -64,10 +64,10 @@ class ChatServer : public DistributedReactor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChatClient : public DistributedReactor {
|
class ChatClient : public Reactor {
|
||||||
public:
|
public:
|
||||||
ChatClient(std::string name, Distributed &distributed)
|
ChatClient(std::string name)
|
||||||
: DistributedReactor(name, distributed) {}
|
: Reactor(name) {}
|
||||||
|
|
||||||
virtual void Run() {
|
virtual void Run() {
|
||||||
std::cout << "ChatClient is active" << std::endl;
|
std::cout << "ChatClient is active" << std::endl;
|
||||||
@ -79,7 +79,7 @@ class ChatClient : public DistributedReactor {
|
|||||||
std::cin >> address >> port >> message;
|
std::cin >> address >> port >> message;
|
||||||
|
|
||||||
auto channel =
|
auto channel =
|
||||||
distributed_.network().Resolve(address, port, "server", "chat");
|
Distributed::GetInstance().network().Resolve(address, port, "server", "chat");
|
||||||
if (channel != nullptr) {
|
if (channel != nullptr) {
|
||||||
channel->Send<ChatMessage>("server", "chat", message);
|
channel->Send<ChatMessage>("server", "chat", message);
|
||||||
} else {
|
} else {
|
||||||
@ -92,10 +92,10 @@ class ChatClient : public DistributedReactor {
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||||
System& system = System::GetInstance();
|
System& system = System::GetInstance();
|
||||||
Distributed distributed;
|
Distributed &distributed = Distributed::GetInstance();
|
||||||
distributed.StartServices();
|
distributed.StartServices();
|
||||||
system.Spawn<ChatServer>("server", distributed);
|
system.Spawn<ChatServer>("server");
|
||||||
system.Spawn<ChatClient>("client", distributed);
|
system.Spawn<ChatClient>("client");
|
||||||
system.AwaitShutdown();
|
system.AwaitShutdown();
|
||||||
distributed.StopServices();
|
distributed.StopServices();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
Distributed distributed;
|
Distributed &distributed = Distributed::GetInstance();
|
||||||
distributed.network().StartClient(1);
|
distributed.network().StartClient(1);
|
||||||
auto channel = distributed.network().Resolve("127.0.0.1", 10000, "master", "main");
|
auto channel = distributed.network().Resolve("127.0.0.1", 10000, "master", "main");
|
||||||
std::cout << channel << std::endl;
|
std::cout << channel << std::endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user