50 lines
928 B
Go
50 lines
928 B
Go
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
|
|
}
|