diff --git a/Makefile.am b/Makefile.am index 43066c5..fecc8d3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -74,7 +74,8 @@ EVENTS = \ LEGISLATOR = \ src/legislator/legislator.cc \ - src/legislator/legislator-factory.cc + src/legislator/legislator-factory.cc \ + src/legislator/ledger.cc SOCKET = \ src/socket/default-socket.cc \ diff --git a/config-files/one-legislator.json b/config-files/one-legislator.json index 85ac252..aec63f4 100644 --- a/config-files/one-legislator.json +++ b/config-files/one-legislator.json @@ -3,7 +3,7 @@ { "ip" : "127.0.0.1", "port" : 8000, - "name" : "test", + "name" : "legislator1", "self" : true } ] diff --git a/src/law/ballot.cc b/src/law/ballot.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/law/ballot.hh b/src/law/ballot.hh new file mode 100644 index 0000000..e1e1b95 --- /dev/null +++ b/src/law/ballot.hh @@ -0,0 +1,15 @@ +#pragma once +#include + +#include "decree.hh" + +namespace paxos +{ + struct Ballot + { + int id; + Decree decree; + std::unordered_set quorum; + std::unordered_set voters; + } +} diff --git a/src/law/decree.cc b/src/law/decree.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/law/decree.hh b/src/law/decree.hh new file mode 100644 index 0000000..3016dcc --- /dev/null +++ b/src/law/decree.hh @@ -0,0 +1,9 @@ +#pragma once + +namespace paxos +{ + struct Decree + { + int decree; + }; +} diff --git a/src/legislator/ledger.cc b/src/legislator/ledger.cc new file mode 100644 index 0000000..9059a21 --- /dev/null +++ b/src/legislator/ledger.cc @@ -0,0 +1,65 @@ +#include "ledger.hh" +#include +#include + +namespace paxos +{ + Ledger::Ledger(std::string path) + : base_path_(path) + { + std::filesystem::create_directory(path); + base_path_ += "/"; + } + + std::vector Ledger::get_decrees() + { + return std::vector(); + } + + int Ledger::last_tried() + { + return read_file(base_path_ + "last-tried.txt"); + } + + void Ledger::set_last_tried(int b) + { + write_file(base_path_ + "last-tried.txt", b); + } + + + int Ledger::prev_vote() + { + return read_file(base_path_ + "prev-vote.txt"); + } + + void Ledger::set_prev_vote(int v) + { + write_file(base_path_ + "prev-vote.txt", v); + } + + int Ledger::next_bal() + { + return read_file(base_path_ + "next-bal.txt"); + } + + void Ledger::set_next_bal(int b) + { + write_file(base_path_ + "next-bal.txt", b); + } + + int Ledger::read_file(std::string path) + { + std::ifstream stream(path); + if (!stream.good()) + return -1; + int res; + stream >> res; + return res; + } + + void Ledger::write_file(std::string path, int n) + { + std::ofstream stream(path); + stream << n; + } +} diff --git a/src/legislator/ledger.hh b/src/legislator/ledger.hh new file mode 100644 index 0000000..68eacd2 --- /dev/null +++ b/src/legislator/ledger.hh @@ -0,0 +1,31 @@ +#pragma once +#include +#include + +#include "law/decree.hh" + +namespace paxos +{ + class Ledger + { + public: + Ledger(std::string path); + + std::vector get_decrees(); + + int last_tried(); + void set_last_tried(int b); + + int prev_vote(); + void set_prev_vote(int v); + + int next_bal(); + void set_next_bal(int b); + + private: + std::string base_path_; + + int read_file(std::string path); + void write_file(std::string path, int n); + }; +} diff --git a/src/legislator/legislator.cc b/src/legislator/legislator.cc index c81dc0e..fbe517e 100644 --- a/src/legislator/legislator.cc +++ b/src/legislator/legislator.cc @@ -1,9 +1,63 @@ #include "legislator.hh" +#include "misc/logger.hh" +#include namespace paxos { Legislator::Legislator(const LegislatorConfig& config) - : config_(config) + : config_(config), ledger(config.name) { + log("created legislator " + config.name, blue); + } + + void Legislator::initiate_ballot() + { + int new_ballot_number = ledger.last_tried() + 1; + ledger.set_last_tried(new_ballot_number); + log(config_.name + " is initiating ballot " + std::to_string(new_ballot_number), cyan); + send_next_ballot(new_ballot_number); + } + + void Legislator::send_next_ballot(int ballot) + { + ballot = ballot; + return; + } + + void Legislator::receive_next_ballot(int ballot, std::string sender) + { + log(config_.name + " has received a NextBallot(" + + std::to_string(ballot) + + ") from " + sender, cyan); + int next_ballot = ledger.next_bal(); + if (ballot <= next_ballot) + { + log("but it was discarded because ballot " + std::to_string(ballot) + + " is inferior or equal to nextBallot " + + std::to_string(next_ballot), red); + return; + } + ledger.set_next_bal(ballot); + int previous_vote = ledger.prev_vote(); + previous_vote = previous_vote; + //XXX send a LastVote to sender + } + + void Legislator::receive_enough_last_vote + (std::unordered_map quorum_last_votes) + { + quorum_last_votes = quorum_last_votes; + //find d to satisfy B3 + //send BeginBallot to the quorum + } + + void Legislator::receive_begin_ballot(int ballot, int decree) + { + if (ballot != ledger.next_bal()) + return; + ledger.set_prev_vote(ballot); + + decree = decree; + //XXX send Voted } } diff --git a/src/legislator/legislator.hh b/src/legislator/legislator.hh index b011d84..cbefdf8 100644 --- a/src/legislator/legislator.hh +++ b/src/legislator/legislator.hh @@ -1,5 +1,7 @@ #pragma once #include "config/config.hh" +#include "ledger.hh" +#include namespace paxos { @@ -9,6 +11,21 @@ namespace paxos Legislator(const LegislatorConfig& config); LegislatorConfig config_; + void initiate_ballot(); + + void send_next_ballot(int ballot); + + void receive_next_ballot(int ballot, std::string sender); + + void receive_enough_last_vote + (std::unordered_map quorum_last_votes); + + void receive_begin_ballot(int ballot, int decree); + + Ledger ledger; }; using shared_legislator = std::shared_ptr; + + extern shared_legislator self; + extern std::vector legislators; } diff --git a/src/legislator/vote.cc b/src/legislator/vote.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/legislator/vote.hh b/src/legislator/vote.hh new file mode 100644 index 0000000..e78ef26 --- /dev/null +++ b/src/legislator/vote.hh @@ -0,0 +1,13 @@ +#pragma once +#include "legislator.hh" +#include "law/decree.hh" + +namespace paxos +{ + struct Vote + { + Legislator legislator; + int ballot_id; + Decree decree; + }; +} diff --git a/src/main.cc b/src/main.cc index 0aee9f8..a23a65e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,10 +1,14 @@ #include +#include #include "config/config.hh" #include "legislator/legislator-factory.hh" #include "events/register.hh" +#include "misc/logger.hh" paxos::EventWatcherRegistry paxos::event_register; +std::vector paxos::legislators; +paxos::shared_legislator paxos::self; ev_signal sigint_watcher; static void sigint_cb(struct ev_loop* loop, ev_signal*, int) @@ -12,6 +16,13 @@ static void sigint_cb(struct ev_loop* loop, ev_signal*, int) ev_break(loop, EVBREAK_ALL); } +ev_signal sigstop_watcher; +static void sigstop_cb(struct ev_loop*, ev_signal*, int) +{ + log("SIGSTOP detected trying to initiate ballot", paxos::red); + paxos::self->initiate_ballot(); +} + int main(int, char **argv) { @@ -20,11 +31,14 @@ int main(int, char **argv) ev_signal_init(&sigint_watcher, sigint_cb, SIGINT); paxos::event_register.get_event_loop().register_sigint_watcher(&sigint_watcher); - paxos::LegislatorFactory::Create(server_config.self_); + ev_signal_init(&sigstop_watcher, sigstop_cb, SIGTSTP); + paxos::event_register.get_event_loop().register_sigint_watcher(&sigstop_watcher); + + paxos::self = paxos::LegislatorFactory::Create(server_config.self_); for (auto config : server_config.legislators_) { - paxos::LegislatorFactory::Create(config); + paxos::legislators.push_back(paxos::LegislatorFactory::Create(config)); } paxos::event_register.get_event_loop()(); diff --git a/src/misc/logger.cc b/src/misc/logger.cc index b2b0f77..4e8d780 100644 --- a/src/misc/logger.cc +++ b/src/misc/logger.cc @@ -2,7 +2,7 @@ #include -namespace http +namespace paxos { void log(std::string str, Color color) { diff --git a/src/misc/logger.hh b/src/misc/logger.hh index f9f2b04..716d301 100644 --- a/src/misc/logger.hh +++ b/src/misc/logger.hh @@ -2,7 +2,7 @@ #include -namespace http +namespace paxos { enum Color {