mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-11 04:30:13 +00:00
ac97ea573c
* Update go-redis to v8.4.0 * github.com/go-redis/redis/v8 v8.4.0 -> v8.5.0 * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * TODO * Use the Queue termination channel as the default context for pushes Signed-off-by: Andrew Thornton <art27@cantab.net> * missed one Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: zeripath <art27@cantab.net>
80 lines
1.4 KiB
Go
Vendored
80 lines
1.4 KiB
Go
Vendored
package rendezvous
|
|
|
|
type Rendezvous struct {
|
|
nodes map[string]int
|
|
nstr []string
|
|
nhash []uint64
|
|
hash Hasher
|
|
}
|
|
|
|
type Hasher func(s string) uint64
|
|
|
|
func New(nodes []string, hash Hasher) *Rendezvous {
|
|
r := &Rendezvous{
|
|
nodes: make(map[string]int, len(nodes)),
|
|
nstr: make([]string, len(nodes)),
|
|
nhash: make([]uint64, len(nodes)),
|
|
hash: hash,
|
|
}
|
|
|
|
for i, n := range nodes {
|
|
r.nodes[n] = i
|
|
r.nstr[i] = n
|
|
r.nhash[i] = hash(n)
|
|
}
|
|
|
|
return r
|
|
}
|
|
|
|
func (r *Rendezvous) Lookup(k string) string {
|
|
// short-circuit if we're empty
|
|
if len(r.nodes) == 0 {
|
|
return ""
|
|
}
|
|
|
|
khash := r.hash(k)
|
|
|
|
var midx int
|
|
var mhash = xorshiftMult64(khash ^ r.nhash[0])
|
|
|
|
for i, nhash := range r.nhash[1:] {
|
|
if h := xorshiftMult64(khash ^ nhash); h > mhash {
|
|
midx = i + 1
|
|
mhash = h
|
|
}
|
|
}
|
|
|
|
return r.nstr[midx]
|
|
}
|
|
|
|
func (r *Rendezvous) Add(node string) {
|
|
r.nodes[node] = len(r.nstr)
|
|
r.nstr = append(r.nstr, node)
|
|
r.nhash = append(r.nhash, r.hash(node))
|
|
}
|
|
|
|
func (r *Rendezvous) Remove(node string) {
|
|
// find index of node to remove
|
|
nidx := r.nodes[node]
|
|
|
|
// remove from the slices
|
|
l := len(r.nstr)
|
|
r.nstr[nidx] = r.nstr[l]
|
|
r.nstr = r.nstr[:l]
|
|
|
|
r.nhash[nidx] = r.nhash[l]
|
|
r.nhash = r.nhash[:l]
|
|
|
|
// update the map
|
|
delete(r.nodes, node)
|
|
moved := r.nstr[nidx]
|
|
r.nodes[moved] = nidx
|
|
}
|
|
|
|
func xorshiftMult64(x uint64) uint64 {
|
|
x ^= x >> 12 // a
|
|
x ^= x << 25 // b
|
|
x ^= x >> 27 // c
|
|
return x * 2685821657736338717
|
|
}
|