This commit is contained in:
46
internal/mesh/catalog.go
Normal file
46
internal/mesh/catalog.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package mesh
|
||||
|
||||
import "sync"
|
||||
|
||||
type Catalog struct {
|
||||
mu sync.RWMutex
|
||||
byID map[string]NodeInfo
|
||||
}
|
||||
|
||||
func NewCatalog() *Catalog { return &Catalog{byID: map[string]NodeInfo{}} }
|
||||
|
||||
func (c *Catalog) Set(n NodeInfo) { c.mu.Lock(); c.byID[n.NodeID] = n; c.mu.Unlock() }
|
||||
|
||||
func (c *Catalog) Replace(nodes []NodeInfo) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.byID = map[string]NodeInfo{}
|
||||
for _, n := range nodes {
|
||||
c.byID[n.NodeID] = n
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Catalog) All() []NodeInfo {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
out := make([]NodeInfo, 0, len(c.byID))
|
||||
for _, n := range c.byID {
|
||||
out = append(out, n)
|
||||
}
|
||||
return out
|
||||
}
|
||||
func (c *Catalog) IDs() []string {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
out := make([]string, 0, len(c.byID))
|
||||
for id := range c.byID {
|
||||
out = append(out, id)
|
||||
}
|
||||
return out
|
||||
}
|
||||
func (c *Catalog) ByID(id string) (NodeInfo, bool) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
n, ok := c.byID[id]
|
||||
return n, ok
|
||||
}
|
||||
49
internal/mesh/rendezvous.go
Normal file
49
internal/mesh/rendezvous.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package mesh
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Rendezvous struct {
|
||||
mu sync.RWMutex
|
||||
nodes []string // node IDs
|
||||
}
|
||||
|
||||
func NewRendezvous() *Rendezvous { return &Rendezvous{} }
|
||||
|
||||
func (r *Rendezvous) Set(ids []string) {
|
||||
r.mu.Lock()
|
||||
r.nodes = append([]string(nil), ids...)
|
||||
r.mu.Unlock()
|
||||
}
|
||||
|
||||
func (r *Rendezvous) Owners(key string, k int) []string {
|
||||
r.mu.RLock()
|
||||
ids := append([]string(nil), r.nodes...)
|
||||
r.mu.RUnlock()
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
type pair struct {
|
||||
id string
|
||||
w uint64
|
||||
}
|
||||
ws := make([]pair, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
h := sha256.Sum256([]byte(id + "|" + key))
|
||||
w := binary.LittleEndian.Uint64(h[:8])
|
||||
ws = append(ws, pair{id: id, w: w})
|
||||
}
|
||||
sort.Slice(ws, func(i, j int) bool { return ws[i].w > ws[j].w })
|
||||
if k > len(ws) {
|
||||
k = len(ws)
|
||||
}
|
||||
out := make([]string, 0, k)
|
||||
for i := 0; i < k; i++ {
|
||||
out = append(out, ws[i].id)
|
||||
}
|
||||
return out
|
||||
}
|
||||
7
internal/mesh/types.go
Normal file
7
internal/mesh/types.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package mesh
|
||||
|
||||
type NodeInfo struct {
|
||||
NodeID string `json:"node_id"`
|
||||
PublicURL string `json:"public_url"`
|
||||
MeshURL string `json:"mesh_url"`
|
||||
}
|
||||
Reference in New Issue
Block a user