forked from soarpenguin/redis-trib
-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.go
205 lines (176 loc) · 5.65 KB
/
utils.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package main
import (
"bufio"
"fmt"
"math"
"os"
"strings"
"github.com/Sirupsen/logrus"
)
// fatal prints the error's details if it is a libcontainer specific error type
// then exits the program with an exit status of 1.
func fatal(err error) {
// make sure the error is written to the logger
logrus.Error(err)
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
func Uniq(list []string) []string {
uniqset := make(map[string]bool, len(list))
for _, x := range list {
uniqset[x] = true
}
result := make([]string, 0, len(uniqset))
for x := range uniqset {
result = append(result, x)
}
return result
}
func MergeNumArray2NumRange(array []int) string {
var i = 0
var result = ""
for j, value := range array {
if j == len(array)-1 {
if i == j {
result += fmt.Sprintf("%d", array[j])
} else {
result += fmt.Sprintf("%d-%d", array[i], array[j])
}
break
}
if value != array[j+1]-1 {
if j == i {
result += fmt.Sprintf("%d,", array[i])
} else {
result += fmt.Sprintf("%d-%d,", array[i], array[j])
}
i = j + 1
}
}
return result
}
func ToInterfaceArray(in []string) []interface{} {
result := make([]interface{}, len(in))
for i, val := range in {
result[i] = interface{}(val)
}
return result
}
func ToStringArray(in []interface{}) []string {
result := make([]string, len(in))
for i, val := range in {
result[i] = fmt.Sprintf("%s", val)
}
return result
}
func YesOrDie(msg string) {
fmt.Printf("%s (type 'yes' to accept): ", msg)
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
if !strings.EqualFold(strings.TrimSpace(text), "yes") {
logrus.Fatalf("*** Aborting...")
}
}
func Round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
func ClusterNodeArray2String(nodes [](*ClusterNode)) (result string) {
for _, node := range nodes {
if node != nil {
result += node.String() + ","
}
}
if len(result) > 0 {
strings.TrimRight(result, ",")
}
return result
}
func NumArray2String(nums []int) (result string) {
if len(nums) > 0 {
result = fmt.Sprintf("%d", nums[0])
for _, id := range nums[1:] {
result += fmt.Sprintf("%s,%d", result, id)
}
if len(result) > 0 {
strings.TrimRight(result, ",")
}
}
return result
}
/* CRC16 implementation according to CCITT standards.
*
* Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the
* following parameters:
*
* Name : "XMODEM", also known as "ZMODEM", "CRC-16/ACORN"
* Width : 16 bit
* Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1)
* Initialization : 0000
* Reflect Input byte : False
* Reflect Output CRC : False
* Xor constant to output CRC : 0000
* Output for "123456789" : 31C3
*/
var crc16tab = [...]uint16{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
}
func crc16(s string) uint16 {
var crc uint16
for i := 0; i < len(s); i++ {
b := s[i]
crc = (crc << 8) ^ crc16tab[byte(crc>>8)^b]
}
return crc
}
const (
HASHTAG_START = "{"
HASHTAG_END = "}"
DEFAULT_SLOT_NUM = 16384
)
// Turn a key name into the corrisponding Redis Cluster slot.
func Key2Slot(key string) uint16 {
// Only hash what is inside {...} if there is such a pattern in the key.
// Note that the specification requires the content that is between
// the first { and the first } after the first {. If we found {} without
// nothing in the middle, the whole key is hashed as usually.
hashKey := key
start := strings.Index(key, HASHTAG_START)
if start >= 0 {
end := strings.LastIndex(key, HASHTAG_END)
if end >= 0 && start < end {
hashKey = key[start:end]
}
}
return crc16(hashKey) % DEFAULT_SLOT_NUM
}