package chord import ( "errors" "net/netip" ) // Node represents a node's topological relations within a Chord network. type Node struct { // self is the node's own address. self Peer // pred is the node's predecessor. // If not valid, the predecessor is not currently known. pred Peer // succ is the node's immediate successors for replication. Its capacity // is the replication factor for the network. // There is always at least one successor. If the number of nodes in the // network is not larger than the replication factor, then this node will // appear in its own successor list. succ []Peer // fingers is the node's finger table. fingers []Peer } func (n *Node) Successor() Peer { return n.succ[0] } // IsLocal reports whether this node owns the given key. func (n *Node) IsLocal(key string) bool { id := keyID(key) return contains(n.self.id, n.Successor().id, id) } // Peer is the ID and address of a node. type Peer struct { id ID addr netip.AddrPort } // Address constructs a peer from an address and port. func Address(addr netip.AddrPort) Peer { return Peer{id: addrID(addr), addr: addr} } // IsValid reports whether the peer was created using [Address] with an address // which was valid. func (p Peer) IsValid() bool { return p.addr.IsValid() && p.addr.Port() != 0 } // Create creates a new Chord network using the given address as the initial node. func Create(addr netip.AddrPort) (*Node, error) { if !addr.IsValid() { return nil, errors.New("chord: cannot create with invalid address") } self := Address(addr) n := &Node{ self: self, succ: []Peer{self}[:1:1], // extra cautious about capacity fingers: make([]Peer, len(ID{})*8), } return n, nil }