forked from armon/go-chord
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutil.go
112 lines (95 loc) · 2.19 KB
/
util.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
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
110
111
112
package chord
import (
"bytes"
"fmt"
"math/big"
"math/rand"
"time"
)
// Generates a random stabilization time
func randStabilize(conf *Config) time.Duration {
min := conf.StabilizeMin
max := conf.StabilizeMax
r := rand.Float64()
return time.Duration((r * float64(max-min)) + float64(min))
}
// Checks if a key is STRICTLY between two ID's exclusively
func between(id1, id2, key []byte) bool {
// Check for ring wrap around
if bytes.Compare(id1, id2) == 1 {
return bytes.Compare(id1, key) == -1 ||
bytes.Compare(id2, key) == 1
}
// Handle the normal case
return bytes.Compare(id1, key) == -1 &&
bytes.Compare(id2, key) == 1
}
// Checks if a key is between two ID's, right inclusive
func betweenRightIncl(id1, id2, key []byte) bool {
// Check for ring wrap around
if bytes.Compare(id1, id2) == 1 {
return bytes.Compare(id1, key) == -1 ||
bytes.Compare(id2, key) >= 0
}
return bytes.Compare(id1, key) == -1 &&
bytes.Compare(id2, key) >= 0
}
// Computes the offset by (n + 2^exp) % (2^mod)
func powerOffset(id []byte, exp int, mod int) []byte {
// Copy the existing slice
off := make([]byte, len(id))
copy(off, id)
// Convert the ID to a bigint
idInt := big.Int{}
idInt.SetBytes(id)
// Get the offset
two := big.NewInt(2)
offset := big.Int{}
offset.Exp(two, big.NewInt(int64(exp)), nil)
// Sum
sum := big.Int{}
sum.Add(&idInt, &offset)
// Get the ceiling
ceil := big.Int{}
ceil.Exp(two, big.NewInt(int64(mod)), nil)
// Apply the mod
idInt.Mod(&sum, &ceil)
// Add together
return idInt.Bytes()
}
// max returns the max of two ints
func max(a, b int) int {
if a >= b {
return a
} else {
return b
}
}
// min returns the min of two ints
func min(a, b int) int {
if a <= b {
return a
} else {
return b
}
}
// Returns the vnode nearest a key
func nearestVnodeToKey(vnodes []*Vnode, key []byte) *Vnode {
for i := len(vnodes) - 1; i >= 0; i-- {
if bytes.Compare(vnodes[i].Id, key) == -1 {
return vnodes[i]
}
}
// Return the last vnode
return vnodes[len(vnodes)-1]
}
// Merges errors together
func mergeErrors(err1, err2 error) error {
if err1 == nil {
return err2
} else if err2 == nil {
return err1
} else {
return fmt.Errorf("%s\n%s", err1, err2)
}
}