From 7dd2de50550b391fa271e03a28b716970813cfee Mon Sep 17 00:00:00 2001 From: Branden J Brown Date: Sat, 8 Mar 2025 13:20:23 -0500 Subject: [PATCH] add closest-preceding-node operation --- chord/topology.go | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/chord/topology.go b/chord/topology.go index 41684c7..268ab9a 100644 --- a/chord/topology.go +++ b/chord/topology.go @@ -32,6 +32,38 @@ func (n *Node) IsLocal(key string) bool { return contains(n.self.id, n.Successor().id, id) } +// Closest finds the locally known peer which is the closest predecessor of key. +func (n *Node) Closest(key string) Peer { + self := n.self.id + id := keyID(key) + l := n.fingers + for i := len(l) - 1; i >= 0; i-- { + f := l[i] + if contains(self, id, f.id) { + // contains reports true if id == f.id, which is + // technically incorrect for this operation. + // We could reasonably skip double-checking and rely on the hash, + // but we can also not skip it and just be correct. + if id == f.id { + continue + } + return f + } + } + // Also try successors. + l = n.succ + for i := len(l) - 1; i >= 0; i-- { + f := l[i] + if contains(self, id, f.id) { + if id == f.id { + continue + } + return f + } + } + return n.self +} + // Peer is the ID and address of a node. type Peer struct { id ID @@ -56,7 +88,7 @@ func Create(addr netip.AddrPort) (*Node, error) { n := &Node{ self: self, succ: []Peer{self}[:1:1], // extra cautious about capacity - fingers: make([]Peer, len(ID{})*8), + fingers: make([]Peer, 0, len(ID{})*8), } return n, nil }