-#include "config.h"
+#include "include/config.h"
using std::vector;
-
-// The config module maintains views. As a node joins or leaves a
-// view, the next view will be the same as previous view, except with
-// the new node added or removed. The first view contains only node
-// 1. If node 2 joins after the first node (it will download the views
-// from node 1), it will learn about view 1 with the first node as the
-// only member. It will then invoke Paxos to create the next view.
-// It will tell Paxos to ask the nodes in view 1 to agree on the value
-// {1, 2}. If Paxos returns success, then it moves to view 2 with
-// {1,2} as the members. When node 3 joins, the config module runs
-// Paxos with the nodes in view 2 and the proposed value to be
-// {1,2,3}. And so on. When a node discovers that some node of the
-// current view is not responding, it kicks off Paxos to propose a new
-// value (the current view minus the node that isn't responding). The
-// config module uses Paxos to create a total order of views, and it
-// is ensured that the majority of the previous view agrees to the
-// next view. The Paxos log contains all the values (i.e., views)
-// agreed on.
+using namespace std::chrono;
+
+// The config module maintains views. As a node joins or leaves a view, the
+// next view will be the same as previous view, except with the new node added
+// or removed. The first view contains only node 1. If node 2 joins after the
+// first node (it will download the views from node 1), it will learn about
+// view 1 with the first node as the only member. It will then invoke Paxos to
+// create the next view. It will tell Paxos to ask the nodes in view 1 to
+// agree on the value {1, 2}. If Paxos returns success, then it moves to view
+// 2 with {1,2} as the members. When node 3 joins, the config module runs Paxos
+// with the nodes in view 2 and the proposed value to be {1,2,3}. And so on.
+// When a node discovers that some node of the current view is not responding,
+// it kicks off Paxos to propose a new value (the current view minus the node
+// that isn't responding). The config module uses Paxos to create a total order
+// of views, and it is ensured that the majority of the previous view agrees to
+// the next view. The Paxos log contains all the values (i.e., views) agreed
+// on.
//
-// The RSM module informs config to add nodes. The config module
-// runs a heartbeater thread that checks in with nodes. If a node
-// doesn't respond, the config module will invoke Paxos's proposer to
-// remove the node. Higher layers will learn about this change when a
-// Paxos acceptor accepts the new proposed value through
-// paxos_commit().
+// The RSM module informs config to add nodes. The config module runs a
+// heartbeater thread that checks in with nodes. If a node doesn't respond,
+// the config module will invoke Paxos's proposer to remove the node. Higher
+// layers will learn about this change when a Paxos acceptor accepts the new
+// proposed value through paxos_commit().
//
-// To be able to bring other nodes up to date to the latest formed
-// view, each node will have a complete history of all view numbers
-// and their values that it knows about. At any time a node can reboot
-// and when it re-joins, it may be many views behind; by remembering
-// all views, the other nodes can bring this re-joined node up to
-// date.
+// To be able to bring other nodes up to date to the latest formed view, each
+// node will have a complete history of all view numbers and their values that
+// it knows about. At any time a node can reboot and when it re-joins, it may
+// be many views behind; by remembering all views, the other nodes can bring
+// this re-joined node up to date.
config_view_change::~config_view_change() {}
reconstruct(cfg_mutex_lock);
}
-void config::get_view(unsigned instance, vector<string> & m) {
+vector<string> config::get_view(unsigned instance) {
lock cfg_mutex_lock(cfg_mutex);
- get_view(instance, m, cfg_mutex_lock);
+ return get_view(instance, cfg_mutex_lock);
}
-void config::get_view(unsigned instance, vector<string> & m, lock & cfg_mutex_lock) {
+vector<string> config::get_view(unsigned instance, lock & cfg_mutex_lock) {
VERIFY(cfg_mutex_lock);
string value = paxos.value(instance);
LOG << "get_view(" << instance << "): returns " << value;
- m = explode(value);
+ return explode(value);
}
void config::reconstruct(lock & cfg_mutex_lock) {
VERIFY(cfg_mutex_lock);
my_view_id = paxos.instance();
if (my_view_id > 0) {
- get_view(my_view_id, mems, cfg_mutex_lock);
+ mems = get_view(my_view_id, cfg_mutex_lock);
LOG << "view " << my_view_id << " " << mems;
}
}
bool config::ismember(const string & m, unsigned vid) {
lock cfg_mutex_lock(cfg_mutex);
- vector<string> v;
- get_view(vid, v, cfg_mutex_lock);
- return isamember(m, v);
+ return isamember(m, get_view(vid, cfg_mutex_lock));
}
bool config::add(const string & new_m, unsigned vid) {
lock cfg_mutex_lock(cfg_mutex);
while (1) {
- auto next_timeout = steady_clock::now() + milliseconds(300);
+ auto next_timeout = steady_clock::now() + 300ms;
LOG << "go to sleep";
config_cond.wait_until(cfg_mutex_lock, next_timeout);
unsigned vid = my_view_id;
- vector<string> cmems;
- get_view(vid, cmems, cfg_mutex_lock);
+ vector<string> cmems = get_view(vid, cfg_mutex_lock);
LOG << "current membership " << cmems;
if (!isamember(me, cmems)) {
}
}
-paxos_protocol::status config::heartbeat(int & r, string m, unsigned vid) {
+paxos_protocol::status config::heartbeat(paxos_protocol::view_t & r, string m, paxos_protocol::view_t vid) {
lock cfg_mutex_lock(cfg_mutex);
- r = (int) my_view_id;
- LOG<< "heartbeat from " << m << "(" << vid << ") my_view_id " << my_view_id;
+ r = my_view_id;
+ LOG << "heartbeat from " << m << "(" << vid << ") my_view_id " << my_view_id;
if (vid == my_view_id)
return paxos_protocol::OK;
else if (paxos.isrunning()) {
config::heartbeat_t config::doheartbeat(const string & m, lock & cfg_mutex_lock) {
VERIFY(cfg_mutex_lock);
- unsigned vid = my_view_id;
+ paxos_protocol::view_t vid = my_view_id, r;
LOG << "heartbeat to " << m << " (" << vid << ")";
cfg_mutex_lock.unlock();
- int r = 0, ret = rpc_protocol::bind_failure;
+ int ret = rpc_protocol::bind_failure;
if (auto cl = rpcc::bind_cached(m))
- ret = cl->call_timeout(paxos_protocol::heartbeat, milliseconds(100), r, me, vid);
+ ret = cl->call_timeout(paxos_protocol::heartbeat, 100ms, r, me, vid);
cfg_mutex_lock.lock();
heartbeat_t res = OK;