diff --git a/src/cluster/cut.rs b/src/cluster/cut.rs index a9f6d98..1dadd9c 100644 --- a/src/cluster/cut.rs +++ b/src/cluster/cut.rs @@ -12,6 +12,7 @@ use std::{ collections::HashMap, convert::TryInto, net::SocketAddr, + ops::Index, result, sync::{Arc, Weak}, }; @@ -89,6 +90,21 @@ pub struct MultiNodeCut { pub(crate) kicked: Arc<[Member]>, } +impl Index for MultiNodeCut { + type Output = Member; + + /// Binary search for the provided `addr`. + /// + /// O(log n) + /// + /// # Panics + /// Panics if a member with `addr` doesn't exist in the configuration. + #[inline] + fn index(&self, addr: SocketAddr) -> &Self::Output { + self.lookup(addr).unwrap() + } +} + impl MultiNodeCut { /// Returns the number of cuts that were skipped between this and the last received /// cut. @@ -139,6 +155,18 @@ impl MultiNodeCut { pub fn kicked(&self) -> &Arc<[Member]> { &self.kicked } + + /// Lookup a specific member in the configuration by socket address. + /// + /// Executes in O(log n) time. + pub fn lookup(&self, addr: SocketAddr) -> Option<&Member> { + let key = |s: SocketAddr| (s.ip(), s.port()); + + self.members + .binary_search_by_key(&key(addr), |m| key(m.addr())) + .ok() + .map(|i| &self.members[i]) + } } /// A cluster member. diff --git a/src/cluster/mod.rs b/src/cluster/mod.rs index a1dae1f..693f1cd 100644 --- a/src/cluster/mod.rs +++ b/src/cluster/mod.rs @@ -633,14 +633,21 @@ impl Cluster { let local_node = self.local_node(); + joined.sort_by_key(|m| (m.addr().ip(), m.addr().port())); + kicked.sort_by_key(|m| (m.addr().ip(), m.addr().port())); + + let mut members: Vec<_> = (state.nodes.iter()) + .map(|node| self.resolve_member(state, node).unwrap()) + .collect(); + + members.sort_by_key(|m| (m.addr().ip(), m.addr().port())); + let cut = MultiNodeCut { skipped: 0, local_addr: self.addr, degraded: !state.nodes.contains(&local_node), conf_id: state.refresh_config(), - members: (state.nodes.iter()) - .map(|node| self.resolve_member(state, node).unwrap()) - .collect(), + members: members.into(), joined: joined.into(), kicked: kicked.into(), }; diff --git a/src/cluster/partition.rs b/src/cluster/partition.rs index 6c01a36..763b2d3 100644 --- a/src/cluster/partition.rs +++ b/src/cluster/partition.rs @@ -186,14 +186,20 @@ impl Cluster { assert!(state.uuids.insert(uuid)); } + joined.sort_by_key(|m| (m.addr().ip(), m.addr().port())); + + let mut members: Vec<_> = (state.nodes.iter()) + .map(|node| self.resolve_member(&state, node).unwrap()) + .collect(); + + members.sort_by_key(|m| (m.addr().ip(), m.addr().port())); + let cut = MultiNodeCut { skipped: 0, local_addr: self.addr, degraded: !state.nodes.contains(&self.local_node()), conf_id: state.refresh_config(), - members: (state.nodes.iter()) - .map(|node| self.resolve_member(&state, node).unwrap()) - .collect(), + members: members.into(), joined: joined.into(), kicked: vec![].into(), };