diff --git a/chord/client.go b/chord/client.go index d1460fc..ac1ce65 100644 --- a/chord/client.go +++ b/chord/client.go @@ -22,6 +22,15 @@ type Client interface { // considering we can sort by increasing distance from the origin and then do // the query in linear time. +// Find finds the first node in the network preceding id. +func Find(ctx context.Context, cl Client, n *Node, id ID) (Peer, error) { + if n.IsLocal(id) { + return n.self, nil + } + p, err := cl.FindSuccessor(ctx, n.Closest(id), id) + return p, err +} + // Join creates a new node joining an existing Chord network by communicating // with any peer already in the network. func Join(ctx context.Context, cl Client, addr netip.AddrPort, np Peer) (*Node, error) { diff --git a/chord/id.go b/chord/id.go index def63c5..85d5c81 100644 --- a/chord/id.go +++ b/chord/id.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha1" "encoding/hex" + "errors" "net/netip" ) @@ -49,3 +50,12 @@ func (id ID) String() string { b = hex.AppendEncode(b, id[:]) return string(b) } + +func ParseID(s string) (ID, error) { + if len(s) != len(ID{})*2 { + return ID{}, errors.New("invalid ID") + } + var id ID + _, err := hex.AppendDecode(id[:], []byte(s)) + return id, err +} diff --git a/chord/topology.go b/chord/topology.go index 89157ae..bde8557 100644 --- a/chord/topology.go +++ b/chord/topology.go @@ -26,16 +26,19 @@ func (n *Node) Successor() Peer { 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) { + return n.pred, append(s, n.succ...) +} + // IsLocal reports whether this node owns the given key. -func (n *Node) IsLocal(key string) bool { - id := keyID(key) +func (n *Node) IsLocal(id ID) 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 { +func (n *Node) Closest(id ID) Peer { self := n.self.id - id := keyID(key) l := n.fingers for i := len(l) - 1; i >= 0; i-- { f := l[i]