-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconsistent.go
More file actions
109 lines (90 loc) · 2.12 KB
/
Copy pathconsistent.go
File metadata and controls
109 lines (90 loc) · 2.12 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package ConsistentHash
// Thanks for blog [http://michaelnielsen.org/blog/consistent-hashing/]
// Thanks golang ConsistenHash code https://github.com/stathat/consistent.git
import (
"errors"
"hash/crc32"
"sort"
"strconv"
"sync"
)
type uints []uint32
func (u uints) Len() int {
return len(u)
}
func (u uints) Swap(i, j int) {
u[i], u[j] = u[j], u[i]
}
func (u uints) Less(i, j int) bool {
return u[i] < u[j]
}
type ConsistentHash struct {
myHash map[uint32]string
replicas int
sortedHash uints
count int64
sync.RWMutex
}
func New() *ConsistentHash {
c := new(ConsistentHash)
c.replicas = 10
c.myHash = make(map[uint32]string)
return c
}
func (c *ConsistentHash) Add(station string) {
c.Lock()
defer c.Unlock()
c.add(station)
}
func (c *ConsistentHash) add(station string) {
for i := 0; i < c.replicas; i++ {
c.myHash[c.GetHashKey(c.MakeStationReplicationString(station, i))] = station
}
c.renewSortedHash()
c.count++
}
func (c *ConsistentHash) Remove(station string) {
c.Lock()
defer c.Unlock()
c.remove(station)
}
func (c *ConsistentHash) remove(station string) {
for i := 0; i < c.replicas; i++ {
delete(c.myHash, c.GetHashKey(c.MakeStationReplicationString(station, i)))
}
c.renewSortedHash()
c.count--
}
func (c *ConsistentHash) Get(key string) (string, error) {
c.RLock()
defer c.RUnlock()
if len(c.myHash) == 0 {
return "", errors.New("hash circle is empty")
}
index := c.get(c.GetHashKey(key))
return c.myHash[c.sortedHash[index]], nil
}
func (c *ConsistentHash) get(keyHash uint32) int {
f := func(j int) bool {
return c.sortedHash[j] > keyHash
}
index := sort.Search(len(c.sortedHash), f)
if index > len(c.sortedHash) {
index = 0
}
return index
}
func (c *ConsistentHash) MakeStationReplicationString(station string, replicasNum int) string {
return station + "_" + strconv.Itoa(replicasNum)
}
func (c *ConsistentHash) GetHashKey(station string) uint32 {
return crc32.ChecksumIEEE([]byte(station))
}
func (c *ConsistentHash) renewSortedHash() {
tmpHash := c.sortedHash[:0]
for i := range c.myHash {
tmpHash = append(tmpHash, i)
}
sort.Sort(tmpHash)
c.sortedHash = tmpHash
}