Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions src/routing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub struct Routing<T> {
finger_table: Vec<IdentifierValue<T>>,
}

impl<T: Identify + Copy + Clone> Routing<T> {
impl<T: Identify + Clone> Routing<T> {
/// Creates a new `Routing` instance for the given initial values.
pub fn new(current: T, predecessor: T, successor: T, finger_table: Vec<T>) -> Self {
Self {
Expand All @@ -56,13 +56,6 @@ impl<T: Identify + Copy + Clone> Routing<T> {
/// Sets the current successor.
pub fn set_successor(&mut self, new_succ: T) {
self.successor = IdentifierValue::new(new_succ);

// update finger table so that all fingers closer than successor point to successor
let diff = self.successor.identifier() - self.current.identifier();

for i in diff.leading_zeros() as usize..self.finger_table.len() {
self.finger_table[i] = self.successor;
}
}

/// Sets the finger for the given index.
Expand All @@ -80,15 +73,77 @@ impl<T: Identify + Copy + Clone> Routing<T> {
identifier.is_between(&self.predecessor.identifier(), &self.current.identifier())
}

/// Checks whether this peer's successor is responsible for the given identifier.
pub fn successor_responsible_for(&self, identifier: Identifier) -> bool {
identifier.is_between(&self.current.identifier(), &self.successor.identifier())
}

/// Returns the peer closest to the given identifier.
pub fn closest_peer(&self, identifier: Identifier) -> &IdentifierValue<T> {
if self.responsible_for(identifier) {
return &self.current;
}

if self.successor_responsible_for(identifier) {
return &self.successor;
}

let diff = identifier - self.current.identifier();
let zeros = diff.leading_zeros() as usize;

self.finger_table.get(zeros).unwrap_or(&self.successor)
}
}

#[cfg(test)]
mod tests {
use super::*;
use routing::identifier::Identifier;
use std::net::SocketAddr;

#[test]
fn new_routing() {
let current: SocketAddr = "192.168.0.1:123".parse().unwrap();
let predecessor: SocketAddr = "192.168.0.3:456".parse().unwrap();
let successor: SocketAddr = "192.168.0.2:789".parse().unwrap();

let finger_table = vec![
"192.168.0.4:8080".parse().unwrap(),
"192.168.0.5:8080".parse().unwrap(),
"192.168.0.6:8080".parse().unwrap(),
"192.168.0.7:8080".parse().unwrap(),
];

let routing = Routing::new(current, predecessor, successor, finger_table.clone());

assert_eq!(current, *routing.current);
assert_eq!(predecessor, *routing.predecessor);
assert_eq!(successor, *routing.successor);

for (expected, finger) in finger_table.iter().zip(routing.finger_table) {
assert_eq!(*expected, *finger);
}
}

#[test]
fn set_predecessor() {
let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
let mut routing = Routing::new(addr, addr, addr, Vec::new());

let predecessor: SocketAddr = "192.168.0.1:1234".parse().unwrap();
routing.set_predecessor(predecessor);

assert_eq!(predecessor, *routing.predecessor);
}

#[test]
fn set_successor() {
let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
let mut routing = Routing::new(addr, addr, addr, Vec::new());

let succecessor: SocketAddr = "192.168.0.1:1234".parse().unwrap();
routing.set_succecessor(succecessor);

assert_eq!(succecessor, *routing.succecessor);
}
}