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:
Goran Zuzic 2017-08-22 17:13:12 +02:00
parent 8f33269b03
commit abedfb29b1
6 changed files with 75 additions and 72 deletions

View File

@ -21,12 +21,12 @@ uint16_t SenderMessage::Port() const { return port_; }
std::string SenderMessage::ReactorName() const { return reactor_; }
std::string SenderMessage::ChannelName() const { return channel_; }
std::shared_ptr<Channel> SenderMessage::GetChannelToSender(
Distributed *distributed) const {
std::shared_ptr<Channel> SenderMessage::GetChannelToSender() const {
if (address_ == FLAGS_address && port_ == FLAGS_port) {
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);
}

View File

@ -225,8 +225,6 @@ class Network {
std::unique_ptr<NetworkServer> server_{nullptr};
};
class Distributed;
/**
* Message that includes the sender channel used to respond.
*/
@ -240,7 +238,7 @@ class SenderMessage : public Message {
std::string ReactorName() const;
std::string ChannelName() const;
std::shared_ptr<Channel> GetChannelToSender(Distributed *distributed = nullptr) const;
std::shared_ptr<Channel> GetChannelToSender() const;
template <class Archive>
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.
* Alive through the entire process lifetime.
* Singleton class. Created automatically on first use.
*/
class Distributed {
public:
Distributed() {}
Distributed(const Distributed &) = delete;
Distributed(Distributed &&) = delete;
Distributed &operator=(const Distributed &) = delete;
Distributed &operator=(Distributed &&) = delete;
/**
* Get the (singleton) instance of Distributed.
*
* More info: https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
*/
static Distributed &GetInstance() {
static Distributed distributed; // guaranteed to be destroyed, initialized on first use
return distributed;
}
void StartServices() {
network_.StartClient(4);
@ -321,15 +325,13 @@ class Distributed {
Network &network() { return network_; }
protected:
Distributed() {}
Network network_;
};
class DistributedReactor : public Reactor {
public:
DistributedReactor(std::string name, Distributed &distributed)
: Reactor(name), distributed_(distributed) {}
protected:
Distributed &distributed_;
private:
Distributed(const Distributed &) = delete;
Distributed(Distributed &&) = delete;
Distributed &operator=(const Distributed &) = delete;
Distributed &operator=(Distributed &&) = delete;
};

View File

@ -465,7 +465,7 @@ class Reactor {
*
* E.g. holds set of reactors, channels for all reactors.
* Alive through the entire process lifetime.
* Singleton class. Created automatically.
* Singleton class. Created automatically on first use.
*/
class System {
public:

View File

@ -13,7 +13,15 @@ class MemgraphDistributed : public Distributed {
using Location = std::pair<std::string, uint16_t>;
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. */
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);
}
protected:
MemgraphDistributed() {}
private:
std::recursive_mutex mutex_;
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).
*/
std::pair<int64_t, std::vector<int64_t>>
ParseConfigAndRegister(const std::string &filename,
MemgraphDistributed &distributed) {
ParseConfigAndRegister(const std::string &filename) {
std::ifstream file(filename, std::ifstream::in);
assert(file.good());
int64_t master_mnid;
@ -59,6 +74,7 @@ std::pair<int64_t, std::vector<int64_t>>
std::string address;
uint16_t port;
file >> master_mnid >> address >> port;
MemgraphDistributed &distributed = MemgraphDistributed::GetInstance();
distributed.RegisterMemgraphNode(master_mnid, address, port);
while (file.good()) {
file >> mnid >> address >> port;
@ -71,21 +87,6 @@ std::pair<int64_t, std::vector<int64_t>>
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.
*/
@ -108,16 +109,16 @@ protected:
CEREAL_REGISTER_TYPE(TextMessage);
class Master : public MemgraphReactor {
class Master : public Reactor {
public:
Master(std::string name, MemgraphDistributed &distributed,
int64_t mnid, std::vector<int64_t> &&worker_mnids)
: MemgraphReactor(name, distributed), mnid_(mnid),
Master(std::string name, int64_t mnid, std::vector<int64_t> &&worker_mnids)
: Reactor(name), mnid_(mnid),
worker_mnids_(std::move(worker_mnids)) {}
virtual void Run() {
std::cout << "Master (" << mnid_ << ") @ " << distributed_.network().Address()
<< ":" << distributed_.network().Port() << std::endl;
MemgraphDistributed &distributed = MemgraphDistributed::GetInstance();
std::cout << "Master (" << mnid_ << ") @ " << distributed.network().Address()
<< ":" << distributed.network().Port() << std::endl;
auto stream = main_.first;
@ -138,7 +139,7 @@ class Master : public MemgraphReactor {
// send a TextMessage to each worker
for (auto wmnid : worker_mnids_) {
auto stream = distributed_.FindChannel(wmnid, "worker", "main");
auto stream = distributed.FindChannel(wmnid, "worker", "main");
stream->OnEventOnce()
.ChainOnce<ChannelResolvedMessage>([this, stream](const ChannelResolvedMessage &msg){
msg.channel()->Send<TextMessage>("master", "main", "hi from master");
@ -153,16 +154,16 @@ class Master : public MemgraphReactor {
std::vector<int64_t> worker_mnids_;
};
class Worker : public MemgraphReactor {
class Worker : public Reactor {
public:
Worker(std::string name, MemgraphDistributed &distributed,
int64_t mnid, int64_t master_mnid)
: MemgraphReactor(name, distributed), mnid_(mnid),
Worker(std::string name, int64_t mnid, int64_t master_mnid)
: Reactor(name), mnid_(mnid),
master_mnid_(master_mnid) {}
virtual void Run() {
std::cout << "Worker (" << mnid_ << ") @ " << distributed_.network().Address()
<< ":" << distributed_.network().Port() << std::endl;
MemgraphDistributed &distributed = MemgraphDistributed::GetInstance();
std::cout << "Worker (" << mnid_ << ") @ " << distributed.network().Address()
<< ":" << distributed.network().Port() << std::endl;
auto stream = main_.first;
// 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) {
std::cout << "Message from " << msg.Address() << ":" << msg.Port() << " .. " << msg.text << "\n";
msg.GetChannelToSender(&distributed_)
msg.GetChannelToSender()
->Send<TextMessage>("worker", "main", "hi from worker");
// 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);
System &system = System::GetInstance();
MemgraphDistributed distributed(system);
auto mnids = ParseConfigAndRegister(FLAGS_config_filename, distributed);
MemgraphDistributed& distributed = MemgraphDistributed::GetInstance();
auto mnids = ParseConfigAndRegister(FLAGS_config_filename);
distributed.StartServices();
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
system.Spawn<Worker>("worker", distributed, FLAGS_my_mnid, mnids.first);
system.Spawn<Worker>("worker", FLAGS_my_mnid, mnids.first);
system.AwaitShutdown();
distributed.StopServices();

View File

@ -36,10 +36,10 @@ class ChatACK : public ChatMessage {
};
CEREAL_REGISTER_TYPE(ChatACK);
class ChatServer : public DistributedReactor {
class ChatServer : public Reactor {
public:
ChatServer(std::string name, Distributed &distributed)
: DistributedReactor(name, distributed) {}
ChatServer(std::string name)
: Reactor(name) {}
virtual void Run() {
std::cout << "ChatServer is active" << std::endl;
@ -64,10 +64,10 @@ class ChatServer : public DistributedReactor {
}
};
class ChatClient : public DistributedReactor {
class ChatClient : public Reactor {
public:
ChatClient(std::string name, Distributed &distributed)
: DistributedReactor(name, distributed) {}
ChatClient(std::string name)
: Reactor(name) {}
virtual void Run() {
std::cout << "ChatClient is active" << std::endl;
@ -79,7 +79,7 @@ class ChatClient : public DistributedReactor {
std::cin >> address >> port >> message;
auto channel =
distributed_.network().Resolve(address, port, "server", "chat");
Distributed::GetInstance().network().Resolve(address, port, "server", "chat");
if (channel != nullptr) {
channel->Send<ChatMessage>("server", "chat", message);
} else {
@ -92,10 +92,10 @@ class ChatClient : public DistributedReactor {
int main(int argc, char *argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
System& system = System::GetInstance();
Distributed distributed;
Distributed &distributed = Distributed::GetInstance();
distributed.StartServices();
system.Spawn<ChatServer>("server", distributed);
system.Spawn<ChatClient>("client", distributed);
system.Spawn<ChatServer>("server");
system.Spawn<ChatClient>("client");
system.AwaitShutdown();
distributed.StopServices();
return 0;

View File

@ -2,7 +2,7 @@
int main(int argc, char *argv[]) {
google::InitGoogleLogging(argv[0]);
Distributed distributed;
Distributed &distributed = Distributed::GetInstance();
distributed.network().StartClient(1);
auto channel = distributed.network().Resolve("127.0.0.1", 10000, "master", "main");
std::cout << channel << std::endl;