transmit value for key in find

This commit is contained in:
Branden J Brown 2025-03-12 16:17:25 -04:00
parent d5f26bb2bf
commit f4a8b104ab
4 changed files with 28 additions and 21 deletions

View File

@ -9,8 +9,10 @@ import (
// Client represents the communications a Chord node performs.
type Client interface {
// FindSuccessor asks s to find the first peer in the network preceding id.
FindSuccessor(ctx context.Context, s Peer, id ID) (Peer, error)
// Find asks s to find a value and the peer that owns it.
// If the ID is not associated with a key, the result must be the empty
// string with a nil error.
Find(ctx context.Context, s Peer, id ID) (Peer, string, error)
// Notify tells s we believe n to be its predecessor.
Notify(ctx context.Context, n *Node, s Peer) error
// Neighbors requests a peer's beliefs about its own neighbors.
@ -22,13 +24,13 @@ 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) {
// Find gets a value and the peer that owns it.
func Find(ctx context.Context, cl Client, n *Node, id ID) (Peer, string, error) {
if n.IsLocal(id) {
return n.self, nil
return n.self, "", nil
}
p, err := cl.FindSuccessor(ctx, n.Closest(id), id)
return p, err
p, s, err := cl.Find(ctx, n.Closest(id), id)
return p, s, err
}
// Join creates a new node joining an existing Chord network by communicating
@ -41,7 +43,7 @@ func Join(ctx context.Context, cl Client, addr netip.AddrPort, np Peer) (*Node,
return nil, errors.New("chord: invalid peer")
}
self := Address(addr)
p, err := cl.FindSuccessor(ctx, np, self.id)
p, _, err := cl.Find(ctx, np, self.id)
if err != nil {
return nil, fmt.Errorf("couldn't query own successor: %w", err)
}

View File

@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"net/http"
"net/netip"
"net/url"
"path"
@ -19,11 +18,11 @@ type Client struct {
APIBase string
}
// FindSuccessor asks s to find the first peer in the network preceding id.
func (cl *Client) FindSuccessor(ctx context.Context, s chord.Peer, id chord.ID) (chord.Peer, error) {
// Find asks s to find a value and the peer that owns it.
func (cl *Client) Find(ctx context.Context, s chord.Peer, id chord.ID) (chord.Peer, string, error) {
_, addr := s.Values()
if !addr.IsValid() {
return chord.Peer{}, errors.New("FindSuccessor with invalid peer")
return chord.Peer{}, "", errors.New("Find with invalid peer")
}
url := url.URL{
Scheme: "http",
@ -33,17 +32,17 @@ func (cl *Client) FindSuccessor(ctx context.Context, s chord.Peer, id chord.ID)
}
req, err := http.NewRequestWithContext(ctx, "GET", url.String(), nil)
if err != nil {
return chord.Peer{}, err
return chord.Peer{}, "", err
}
resp, err := cl.HTTP.Do(req)
if err != nil {
return chord.Peer{}, err
return chord.Peer{}, "", err
}
p, err := readResponse[netip.AddrPort](resp)
p, err := readResponse[peervalue](resp)
if err != nil {
return chord.Peer{}, fmt.Errorf("%w (%s)", err, resp.Status)
return chord.Peer{}, "", fmt.Errorf("%w (%s)", err, resp.Status)
}
return chord.Address(p), nil
return chord.Address(p.Peer), p.Value, nil
}
// Notify tells s we believe n to be its predecessor.

View File

@ -45,3 +45,8 @@ type neighbors struct {
Succ []netip.AddrPort `json:"succ"`
Pred netip.AddrPort `json:"pred,omitzero"`
}
type peervalue struct {
Peer netip.AddrPort `json:"peer"`
Value string `json:"value,omitzero"`
}

View File

@ -45,7 +45,7 @@ func New(l net.Listener, cl chord.Client) (*Node, error) {
// Router creates a handler for the Chord HTTP endpoints.
func (n *Node) Router() http.Handler {
m := http.NewServeMux()
m.HandleFunc("GET /succ", n.successor)
m.HandleFunc("GET /key", n.key)
m.HandleFunc("POST /pred", n.notify)
m.HandleFunc("GET /neighbors", n.neighbors)
return m
@ -65,20 +65,21 @@ func (n *Node) Check(ctx context.Context) error {
return nil
}
func (n *Node) successor(w http.ResponseWriter, r *http.Request) {
func (n *Node) key(w http.ResponseWriter, r *http.Request) {
s := r.FormValue("s")
id, err := chord.ParseID(s)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
p, err := chord.Find(r.Context(), n.client, n.self, id)
p, v, err := chord.Find(r.Context(), n.client, n.self, id)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
_, addr := p.Values()
writeOk(w, addr)
pv := peervalue{addr, v}
writeOk(w, pv)
}
func (n *Node) notify(w http.ResponseWriter, r *http.Request) {