github.com/XiaoMi/Gaea@v1.2.5/proxy/router/shard.go (about) 1 // Copyright 2012, Google Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Copyright 2016 The kingshard Authors. All rights reserved. 6 // 7 // Licensed under the Apache License, Version 2.0 (the "License"): you may 8 // not use this file except in compliance with the License. You may obtain 9 // a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 // License for the specific language governing permissions and limitations 17 // under the License. 18 19 // Copyright 2019 The Gaea Authors. All Rights Reserved. 20 // 21 // Licensed under the Apache License, Version 2.0 (the "License"); 22 // you may not use this file except in compliance with the License. 23 // You may obtain a copy of the License at 24 // 25 // http://www.apache.org/licenses/LICENSE-2.0 26 // 27 // Unless required by applicable law or agreed to in writing, software 28 // distributed under the License is distributed on an "AS IS" BASIS, 29 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 30 // See the License for the specific language governing permissions and 31 // limitations under the License. 32 33 package router 34 35 import ( 36 "bytes" 37 "encoding/binary" 38 "fmt" 39 "hash/crc32" 40 "strconv" 41 "time" 42 43 "github.com/XiaoMi/Gaea/core/errors" 44 "github.com/XiaoMi/Gaea/util/hack" 45 ) 46 47 /*由分片ID找到分片,可用文件中的函数*/ 48 type KeyError string 49 50 func NewKeyError(format string, args ...interface{}) KeyError { 51 return KeyError(fmt.Sprintf(format, args...)) 52 } 53 54 func NewInvalidDateFormatKeyError(key interface{}) KeyError { 55 return KeyError(fmt.Sprintf("invalid date format %v", key)) 56 } 57 58 func (ke KeyError) Error() string { 59 return string(ke) 60 } 61 62 func handleError(err *error) { 63 if x := recover(); x != nil { 64 *err = x.(KeyError) 65 } 66 } 67 68 // Uint64Key is a uint64 that can be converted into a KeyspaceId. 69 type Uint64Key uint64 70 71 func (i Uint64Key) String() string { 72 buf := new(bytes.Buffer) 73 binary.Write(buf, binary.BigEndian, uint64(i)) 74 return buf.String() 75 } 76 77 // don't use this function like strconv.FormatInt()!!! 78 func EncodeValue(value interface{}) string { 79 switch val := value.(type) { 80 case int: 81 return Uint64Key(val).String() 82 case uint64: 83 return Uint64Key(val).String() 84 case int64: 85 return Uint64Key(val).String() 86 case string: 87 return val 88 case []byte: 89 return hack.String(val) 90 } 91 panic(NewKeyError("Unexpected key variable type %T", value)) 92 } 93 94 func GetString(value interface{}) string { 95 switch val := value.(type) { 96 case int: 97 return strconv.FormatInt(int64(val), 10) 98 case int64: 99 return strconv.FormatInt(val, 10) 100 case uint: 101 return strconv.FormatUint(uint64(val), 10) 102 case uint64: 103 return strconv.FormatUint(val, 10) 104 case string: 105 return val 106 case []byte: 107 return hack.String(val) 108 default: 109 panic(NewKeyError("Unexpected key variable type %T", value)) 110 } 111 } 112 113 func HashValue(value interface{}) uint64 { 114 switch val := value.(type) { 115 case int: 116 return uint64(val) 117 case uint64: 118 return uint64(val) 119 case int64: 120 return uint64(val) 121 case string: 122 if v, err := strconv.ParseUint(val, 10, 64); err != nil { 123 return uint64(crc32.ChecksumIEEE(hack.Slice(val))) 124 } else { 125 return uint64(v) 126 } 127 case []byte: 128 return uint64(crc32.ChecksumIEEE(val)) 129 } 130 panic(NewKeyError("Unexpected key variable type %T", value)) 131 } 132 133 func NumValue(value interface{}) int64 { 134 switch val := value.(type) { 135 case int: 136 return int64(val) 137 case uint64: 138 return int64(val) 139 case int64: 140 return int64(val) 141 case string: 142 if v, err := strconv.ParseInt(val, 10, 64); err != nil { 143 panic(NewKeyError("invalid num format %v", v)) 144 } else { 145 return v 146 } 147 case []byte: 148 if v, err := strconv.ParseInt(hack.String(val), 10, 64); err != nil { 149 panic(NewKeyError("invalid num format %v", v)) 150 } else { 151 return v 152 } 153 } 154 panic(NewKeyError("Unexpected key variable type %T", value)) 155 } 156 157 type Shard interface { 158 FindForKey(key interface{}) (int, error) 159 } 160 161 /*一个范围的分片,例如[start,end)*/ 162 type RangeShard interface { 163 Shard 164 EqualStart(key interface{}, index int) bool 165 } 166 167 type HashShard struct { 168 ShardNum int 169 } 170 171 func (s *HashShard) FindForKey(key interface{}) (int, error) { 172 h := HashValue(key) 173 174 return int(h % uint64(s.ShardNum)), nil 175 } 176 177 type ModShard struct { 178 ShardNum int 179 } 180 181 func (m *ModShard) FindForKey(key interface{}) (int, error) { 182 h := hack.Abs(NumValue(key)) 183 return int(h % int64(m.ShardNum)), nil 184 } 185 186 type NumRangeShard struct { 187 Shards []NumKeyRange 188 } 189 190 func (s *NumRangeShard) FindForKey(key interface{}) (int, error) { 191 v := NumValue(key) 192 for i, r := range s.Shards { 193 if r.Contains(v) { 194 return i, nil 195 } 196 } 197 return -1, errors.ErrKeyOutOfRange 198 } 199 200 func (s *NumRangeShard) EqualStart(key interface{}, index int) bool { 201 v := NumValue(key) 202 return s.Shards[index].Start == v 203 } 204 205 type DateYearShard struct { 206 } 207 208 func (s *DateYearShard) getNumYear(key interface{}) (int, error) { 209 switch val := key.(type) { 210 case int: 211 tm := time.Unix(int64(val), 0) 212 return tm.Year(), nil 213 case uint64: 214 tm := time.Unix(int64(val), 0) 215 return tm.Year(), nil 216 case int64: 217 tm := time.Unix(val, 0) 218 return tm.Year(), nil 219 case string: 220 if v, err := strconv.Atoi(val[:4]); err != nil { 221 return -1, NewInvalidDateFormatKeyError(key) 222 } else { 223 return v, nil 224 } 225 } 226 return -1, NewKeyError("Unexpected key variable type %T", key) 227 } 228 229 //the format of date is: YYYY-MM-DD HH:MM:SS,YYYY-MM-DD or unix timestamp(int) 230 func (s *DateYearShard) FindForKey(key interface{}) (int, error) { 231 return s.getNumYear(key) 232 } 233 234 func (s *DateYearShard) EqualStart(key interface{}, index int) bool { 235 numYear, err := s.getNumYear(key) 236 if err != nil { 237 return false 238 } 239 240 return numYear == index 241 } 242 243 type DateMonthShard struct { 244 } 245 246 func (s *DateMonthShard) getNumYearMonth(key interface{}) (int, error) { 247 timeFormat := "2006-01-02" 248 switch val := key.(type) { 249 case int: 250 tm := time.Unix(int64(val), 0) 251 dateStr := tm.Format(timeFormat) 252 s := dateStr[:4] + dateStr[5:7] 253 yearMonth, err := strconv.Atoi(s) 254 if err != nil { 255 return -1, NewInvalidDateFormatKeyError(key) 256 } 257 return yearMonth, nil 258 case uint64: 259 tm := time.Unix(int64(val), 0) 260 dateStr := tm.Format(timeFormat) 261 s := dateStr[:4] + dateStr[5:7] 262 yearMonth, err := strconv.Atoi(s) 263 if err != nil { 264 return -1, NewInvalidDateFormatKeyError(key) 265 } 266 return yearMonth, nil 267 case int64: 268 tm := time.Unix(val, 0) 269 dateStr := tm.Format(timeFormat) 270 s := dateStr[:4] + dateStr[5:7] 271 yearMonth, err := strconv.Atoi(s) 272 if err != nil { 273 return -1, NewInvalidDateFormatKeyError(key) 274 } 275 return yearMonth, nil 276 case string: 277 if len(val) < len(timeFormat) { 278 return -1, NewInvalidDateFormatKeyError(key) 279 } 280 s := val[:4] + val[5:7] 281 if v, err := strconv.Atoi(s); err != nil { 282 return -1, NewInvalidDateFormatKeyError(key) 283 } else { 284 return v, nil 285 } 286 } 287 return -1, NewKeyError("Unexpected key variable type %T", key) 288 } 289 290 //the format of date is: YYYY-MM-DD HH:MM:SS,YYYY-MM-DD or unix timestamp(int) 291 func (s *DateMonthShard) FindForKey(key interface{}) (int, error) { 292 return s.getNumYearMonth(key) 293 } 294 295 func (s *DateMonthShard) EqualStart(key interface{}, index int) bool { 296 numYear, err := s.getNumYearMonth(key) 297 if err != nil { 298 return false 299 } 300 301 return numYear == index 302 } 303 304 type DateDayShard struct { 305 } 306 307 func (s *DateDayShard) getNumYearMonthDay(key interface{}) (int, error) { 308 timeFormat := "2006-01-02" 309 switch val := key.(type) { 310 case int: 311 tm := time.Unix(int64(val), 0) 312 dateStr := tm.Format(timeFormat) 313 s := dateStr[:4] + dateStr[5:7] + dateStr[8:10] 314 yearMonthDay, err := strconv.Atoi(s) 315 if err != nil { 316 return -1, NewInvalidDateFormatKeyError(key) 317 } 318 return yearMonthDay, nil 319 case uint64: 320 tm := time.Unix(int64(val), 0) 321 dateStr := tm.Format(timeFormat) 322 s := dateStr[:4] + dateStr[5:7] + dateStr[8:10] 323 yearMonthDay, err := strconv.Atoi(s) 324 if err != nil { 325 return -1, NewInvalidDateFormatKeyError(key) 326 } 327 return yearMonthDay, nil 328 case int64: 329 tm := time.Unix(val, 0) 330 dateStr := tm.Format(timeFormat) 331 s := dateStr[:4] + dateStr[5:7] + dateStr[8:10] 332 yearMonthDay, err := strconv.Atoi(s) 333 if err != nil { 334 return -1, NewInvalidDateFormatKeyError(key) 335 } 336 return yearMonthDay, nil 337 case string: 338 if len(val) < len(timeFormat) { 339 return -1, NewInvalidDateFormatKeyError(key) 340 } 341 s := val[:4] + val[5:7] + val[8:10] 342 if v, err := strconv.Atoi(s); err != nil { 343 return -1, NewInvalidDateFormatKeyError(key) 344 } else { 345 return v, nil 346 } 347 } 348 return -1, NewKeyError("Unexpected key variable type %T", key) 349 } 350 351 //the format of date is: YYYY-MM-DD HH:MM:SS,YYYY-MM-DD or unix timestamp(int) 352 func (s *DateDayShard) FindForKey(key interface{}) (int, error) { 353 return s.getNumYearMonthDay(key) 354 } 355 356 func (s *DateDayShard) EqualStart(key interface{}, index int) bool { 357 numYear, err := s.getNumYearMonthDay(key) 358 if err != nil { 359 return false 360 } 361 362 return numYear == index 363 } 364 365 type DefaultShard struct { 366 } 367 368 func (s *DefaultShard) FindForKey(key interface{}) (int, error) { 369 return 0, nil 370 } 371 372 type GlobalTableShard struct { 373 } 374 375 func (s *GlobalTableShard) FindForKey(key interface{}) (int, error) { 376 panic("global table cannot find key") 377 } 378 379 func NewGlobalTableShard() *GlobalTableShard { 380 return &GlobalTableShard{} 381 }