forked from cchamplin/gocrush
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunweightedhashselector.go
68 lines (61 loc) · 1.5 KB
/
unweightedhashselector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package gocrush
import (
"fmt"
"sort"
)
type UnweightedHashSelector struct {
tokenList utokenList
tokenMap map[uint64]Node
}
type utokenList []uint64
func (t utokenList) Len() int {
return len(t)
}
func (t utokenList) Less(i, j int) bool {
return t[i] < t[j]
}
func (t utokenList) Swap(i, j int) {
t[i], t[j] = t[j], t[i]
}
func hashVal(bKey []byte) uint64 {
return ((uint64(bKey[3]) << 24) |
(uint64(bKey[2]) << 16) |
(uint64(bKey[1]) << 8) |
(uint64(bKey[0])))
}
func NewUnweightedHashSelector(n Node) *UnweightedHashSelector {
var s = new(UnweightedHashSelector)
if !n.IsLeaf() {
nodes := n.GetChildren()
s.tokenMap = make(map[uint64]Node)
var factor int = 60 * len(nodes) * len(nodes)
idx := 0
s.tokenList = make([]uint64, len(nodes)*factor*3)
for _, node := range nodes {
var bKey []byte
for c := 0; c < factor; c++ {
bKey = digestString(fmt.Sprintf("%s-%s", node.GetId(), c))
for i := 0; i < 3; i++ {
key := hashVal(bKey[i*4 : i*4+4])
s.tokenMap[key] = node
s.tokenList[idx] = key
idx += 1
}
}
}
}
sort.Sort(s.tokenList)
return s
}
func (s *UnweightedHashSelector) Select(input int64, round int64) Node {
var hash = hash2(input, round)
token := uint64(hash)
return s.tokenMap[s.findToken(token)]
}
func (s *UnweightedHashSelector) findToken(token uint64) uint64 {
i := sort.Search(len(s.tokenList), func(i int) bool { return s.tokenList[i] > token })
if i >= len(s.tokenList) {
return s.tokenList[0]
}
return s.tokenList[uint64(i)]
}