diff --git a/chord/topology.go b/chord/topology.go index 128a3e0..29995b3 100644 --- a/chord/topology.go +++ b/chord/topology.go @@ -3,11 +3,16 @@ package chord import ( "errors" "net/netip" + "sync" ) // Node represents a node's topological relations within a Chord network. +// It is safe to use the methods of Node concurrently. type Node struct { + // mu guards the mutable fields of the node. + mu sync.Mutex // self is the node's own address. + // It is fully immutable; the mutex does not protect it. self Peer // pred is the node's predecessor. // If not valid, the predecessor is not currently known. @@ -27,11 +32,15 @@ func (n *Node) Self() Peer { } func (n *Node) Successor() Peer { + n.mu.Lock() + defer n.mu.Unlock() return n.succ[0] } // Neighbors returns the node's predecessor and appends its successor list to s. func (n *Node) Neighbors(s []Peer) (Peer, []Peer) { + n.mu.Lock() + defer n.mu.Unlock() return n.pred, append(s, n.succ...) } @@ -43,6 +52,8 @@ func (n *Node) IsLocal(id ID) bool { // Closest finds the locally known peer which is the closest predecessor of key. func (n *Node) Closest(id ID) Peer { self := n.self.id + n.mu.Lock() + defer n.mu.Unlock() l := n.fingers for i := len(l) - 1; i >= 0; i-- { f := l[i]