Skip to content

Commit

Permalink
Implemented skeleton code for master election
Browse files Browse the repository at this point in the history
  • Loading branch information
tailhook committed Oct 5, 2015
1 parent 4bd996a commit b3a4b9b
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/elect/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use std::net::SocketAddr;
use std::collections::HashSet;

use time::SteadyTime;

mod node;
mod settings;
#[cfg(test)] mod test_mesh;
#[cfg(test)] mod test_util;
#[cfg(test)] mod test_split_brain;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct Id(String);


enum Machine {
Starting { leader_deadline: SteadyTime },
Electing { votes_for_me: HashSet<Id>, election_deadline: SteadyTime },
Voted { peer: Id, election_deadline: SteadyTime },
Leader { ping_time: SteadyTime },
Follower { leader_deadline: SteadyTime },
}

struct Node {
id: String,
machine: Machine,
}
17 changes: 17 additions & 0 deletions src/elect/node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use rand::{thread_rng, Rng};
use time::{SteadyTime, Duration};

use super::{Node, Machine};
use super::settings::start_timeout;


impl Node {
pub fn new<S:AsRef<str>>(id: S, now: SteadyTime) -> Node {
Node {
id: id.as_ref().to_string(),
machine: Machine::Starting {
leader_deadline: now + start_timeout(),
}
}
}
}
39 changes: 39 additions & 0 deletions src/elect/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use time::Duration;
use rand::{thread_rng, Rng};

/// The number of seconds just started worker waits it to be reached by
/// leader. We usually don't care joining the cluster on start too much.
/// Probably we want it to be bigger than:
///
/// * TCP retransmision timeout (so that in flaky network we don't start too
/// much elections, because they have big chance to fail)
/// * Cantal's discovery time and time to propagate changes to the leader
///
/// The random MESSAGE_TIMEOUT (constained by constants below) is added to
/// this timeout.
pub const START_TIMEOUT: i64 = 5000;

/// On each leader's ping we start election timer of a random value in this
/// range. If there is no heartbeat from leader during this timeout, we start
/// election. Note that mio currently has only 200 ms precision timers.
pub const MIN_MESSAGE_TIMEOUT: i64 = 1200;
pub const MAX_MESSAGE_TIMEOUT: i64 = 3000;

/// Leader ping interval
///
/// Raft have it slightly less than MIN_MESSAGE_TIMEOUT. My intuition says that
/// it's nicer to have 2x smaller, just like in almost every other heartbeating
/// system. There is no good reason to wait so long for original Raft. I.e.
/// it wants to reestablish consistency as fast as possible. But it may be
/// nicer to keep lower elections for us.
pub const HEARTBEAT_INTERVAL: u64 = 600;


pub fn start_timeout() -> Duration {
Duration::milliseconds(START_TIMEOUT) + election_ivl()
}

pub fn election_ivl() -> Duration {
Duration::milliseconds(
thread_rng().gen_range(MIN_MESSAGE_TIMEOUT, MAX_MESSAGE_TIMEOUT))
}
1 change: 1 addition & 0 deletions src/elect/test_mesh.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//! Tests for the case network is full mesh
1 change: 1 addition & 0 deletions src/elect/test_mesh.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// Tests of
4 changes: 4 additions & 0 deletions src/elect/test_split_brain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Tests for partitioned network (split-brain)
//!
//! Note that unlike in most other leader election systems, we still elect a
//! leader even in minority partition. Becase we don't care strong consistency.
13 changes: 13 additions & 0 deletions src/elect/test_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use time::{SteadyTime, Duration};



struct TimeScale {
now: SteadyTime,
}

impl TimeScale {
fn advance_ms(&mut self, ms: u64) {
self.now += Duration::milliseconds(ms);
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod config;
mod render;
mod apply;
mod scheduler;
mod elect;

use argparse::{ArgumentParser, Parse, StoreTrue};

Expand Down

0 comments on commit b3a4b9b

Please sign in to comment.