github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/meta/autoid/autoid_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package autoid_test 15 16 import ( 17 "fmt" 18 "math" 19 "math/rand" 20 "sync" 21 "testing" 22 "time" 23 24 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 25 . "github.com/whtcorpsinc/check" 26 "github.com/whtcorpsinc/errors" 27 "github.com/whtcorpsinc/failpoint" 28 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 29 "github.com/whtcorpsinc/milevadb/ekv" 30 "github.com/whtcorpsinc/milevadb/spacetime" 31 "github.com/whtcorpsinc/milevadb/spacetime/autoid" 32 ) 33 34 func TestT(t *testing.T) { 35 CustomVerboseFlag = true 36 TestingT(t) 37 } 38 39 var _ = SerialSuites(&testSuite{}) 40 41 type testSuite struct { 42 } 43 44 func (*testSuite) TestT(c *C) { 45 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange", `return(true)`), IsNil) 46 defer func() { 47 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange"), IsNil) 48 }() 49 50 causetstore, err := mockstore.NewMockStore() 51 c.Assert(err, IsNil) 52 defer causetstore.Close() 53 54 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 55 m := spacetime.NewMeta(txn) 56 err = m.CreateDatabase(&perceptron.DBInfo{ID: 1, Name: perceptron.NewCIStr("a")}) 57 c.Assert(err, IsNil) 58 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 1, Name: perceptron.NewCIStr("t")}) 59 c.Assert(err, IsNil) 60 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 2, Name: perceptron.NewCIStr("t1")}) 61 c.Assert(err, IsNil) 62 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 3, Name: perceptron.NewCIStr("t1")}) 63 c.Assert(err, IsNil) 64 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 4, Name: perceptron.NewCIStr("t2")}) 65 c.Assert(err, IsNil) 66 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 5, Name: perceptron.NewCIStr("t3")}) 67 c.Assert(err, IsNil) 68 return nil 69 }) 70 c.Assert(err, IsNil) 71 72 // Since the test here is applicable to any type of allocators, autoid.RowIDAllocType is chosen. 73 alloc := autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 74 c.Assert(alloc, NotNil) 75 76 globalAutoID, err := alloc.NextGlobalAutoID(1) 77 c.Assert(err, IsNil) 78 c.Assert(globalAutoID, Equals, int64(1)) 79 _, id, err := alloc.Alloc(1, 1, 1, 1) 80 c.Assert(err, IsNil) 81 c.Assert(id, Equals, int64(1)) 82 _, id, err = alloc.Alloc(1, 1, 1, 1) 83 c.Assert(err, IsNil) 84 c.Assert(id, Equals, int64(2)) 85 _, _, err = alloc.Alloc(0, 1, 1, 1) 86 c.Assert(err, NotNil) 87 globalAutoID, err = alloc.NextGlobalAutoID(1) 88 c.Assert(err, IsNil) 89 c.Assert(globalAutoID, Equals, autoid.GetStep()+1) 90 91 // rebase 92 err = alloc.Rebase(1, int64(1), true) 93 c.Assert(err, IsNil) 94 _, id, err = alloc.Alloc(1, 1, 1, 1) 95 c.Assert(err, IsNil) 96 c.Assert(id, Equals, int64(3)) 97 err = alloc.Rebase(1, int64(3), true) 98 c.Assert(err, IsNil) 99 _, id, err = alloc.Alloc(1, 1, 1, 1) 100 c.Assert(err, IsNil) 101 c.Assert(id, Equals, int64(4)) 102 err = alloc.Rebase(1, int64(10), true) 103 c.Assert(err, IsNil) 104 _, id, err = alloc.Alloc(1, 1, 1, 1) 105 c.Assert(err, IsNil) 106 c.Assert(id, Equals, int64(11)) 107 err = alloc.Rebase(1, int64(3010), true) 108 c.Assert(err, IsNil) 109 _, id, err = alloc.Alloc(1, 1, 1, 1) 110 c.Assert(err, IsNil) 111 c.Assert(id, Equals, int64(3011)) 112 113 alloc = autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 114 c.Assert(alloc, NotNil) 115 _, id, err = alloc.Alloc(1, 1, 1, 1) 116 c.Assert(err, IsNil) 117 c.Assert(id, Equals, autoid.GetStep()+1) 118 119 alloc = autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 120 c.Assert(alloc, NotNil) 121 err = alloc.Rebase(2, int64(1), false) 122 c.Assert(err, IsNil) 123 _, id, err = alloc.Alloc(2, 1, 1, 1) 124 c.Assert(err, IsNil) 125 c.Assert(id, Equals, int64(2)) 126 127 alloc = autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 128 c.Assert(alloc, NotNil) 129 err = alloc.Rebase(3, int64(3210), false) 130 c.Assert(err, IsNil) 131 alloc = autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 132 c.Assert(alloc, NotNil) 133 err = alloc.Rebase(3, int64(3000), false) 134 c.Assert(err, IsNil) 135 _, id, err = alloc.Alloc(3, 1, 1, 1) 136 c.Assert(err, IsNil) 137 c.Assert(id, Equals, int64(3211)) 138 err = alloc.Rebase(3, int64(6543), false) 139 c.Assert(err, IsNil) 140 _, id, err = alloc.Alloc(3, 1, 1, 1) 141 c.Assert(err, IsNil) 142 c.Assert(id, Equals, int64(6544)) 143 144 // Test the MaxInt64 is the upper bound of `alloc` function but not `rebase`. 145 err = alloc.Rebase(3, int64(math.MaxInt64-1), true) 146 c.Assert(err, IsNil) 147 _, _, err = alloc.Alloc(3, 1, 1, 1) 148 c.Assert(alloc, NotNil) 149 err = alloc.Rebase(3, int64(math.MaxInt64), true) 150 c.Assert(err, IsNil) 151 152 // alloc N for signed 153 alloc = autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 154 c.Assert(alloc, NotNil) 155 globalAutoID, err = alloc.NextGlobalAutoID(4) 156 c.Assert(err, IsNil) 157 c.Assert(globalAutoID, Equals, int64(1)) 158 min, max, err := alloc.Alloc(4, 1, 1, 1) 159 c.Assert(err, IsNil) 160 c.Assert(max-min, Equals, int64(1)) 161 c.Assert(min+1, Equals, int64(1)) 162 163 min, max, err = alloc.Alloc(4, 2, 1, 1) 164 c.Assert(err, IsNil) 165 c.Assert(max-min, Equals, int64(2)) 166 c.Assert(min+1, Equals, int64(2)) 167 c.Assert(max, Equals, int64(3)) 168 169 min, max, err = alloc.Alloc(4, 100, 1, 1) 170 c.Assert(err, IsNil) 171 c.Assert(max-min, Equals, int64(100)) 172 expected := int64(4) 173 for i := min + 1; i <= max; i++ { 174 c.Assert(i, Equals, expected) 175 expected++ 176 } 177 178 err = alloc.Rebase(4, int64(1000), false) 179 c.Assert(err, IsNil) 180 min, max, err = alloc.Alloc(4, 3, 1, 1) 181 c.Assert(err, IsNil) 182 c.Assert(max-min, Equals, int64(3)) 183 c.Assert(min+1, Equals, int64(1001)) 184 c.Assert(min+2, Equals, int64(1002)) 185 c.Assert(max, Equals, int64(1003)) 186 187 lastRemainOne := alloc.End() 188 err = alloc.Rebase(4, alloc.End()-2, false) 189 c.Assert(err, IsNil) 190 min, max, err = alloc.Alloc(4, 5, 1, 1) 191 c.Assert(err, IsNil) 192 c.Assert(max-min, Equals, int64(5)) 193 c.Assert(min+1, Greater, lastRemainOne) 194 195 // Test for increment & offset for signed. 196 alloc = autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 197 c.Assert(alloc, NotNil) 198 199 increment := int64(2) 200 offset := int64(100) 201 c.Assert(err, IsNil) 202 c.Assert(globalAutoID, Equals, int64(1)) 203 min, max, err = alloc.Alloc(5, 1, increment, offset) 204 c.Assert(err, IsNil) 205 c.Assert(min, Equals, int64(99)) 206 c.Assert(max, Equals, int64(100)) 207 208 min, max, err = alloc.Alloc(5, 2, increment, offset) 209 c.Assert(err, IsNil) 210 c.Assert(max-min, Equals, int64(4)) 211 c.Assert(max-min, Equals, autoid.CalcNeededBatchSize(100, 2, increment, offset, false)) 212 c.Assert(min, Equals, int64(100)) 213 c.Assert(max, Equals, int64(104)) 214 215 increment = int64(5) 216 min, max, err = alloc.Alloc(5, 3, increment, offset) 217 c.Assert(err, IsNil) 218 c.Assert(max-min, Equals, int64(11)) 219 c.Assert(max-min, Equals, autoid.CalcNeededBatchSize(104, 3, increment, offset, false)) 220 c.Assert(min, Equals, int64(104)) 221 c.Assert(max, Equals, int64(115)) 222 firstID := autoid.SeekToFirstAutoIDSigned(104, increment, offset) 223 c.Assert(firstID, Equals, int64(105)) 224 225 increment = int64(15) 226 min, max, err = alloc.Alloc(5, 2, increment, offset) 227 c.Assert(err, IsNil) 228 c.Assert(max-min, Equals, int64(30)) 229 c.Assert(max-min, Equals, autoid.CalcNeededBatchSize(115, 2, increment, offset, false)) 230 c.Assert(min, Equals, int64(115)) 231 c.Assert(max, Equals, int64(145)) 232 firstID = autoid.SeekToFirstAutoIDSigned(115, increment, offset) 233 c.Assert(firstID, Equals, int64(130)) 234 235 offset = int64(200) 236 min, max, err = alloc.Alloc(5, 2, increment, offset) 237 c.Assert(err, IsNil) 238 c.Assert(max-min, Equals, int64(16)) 239 // offset-1 > base will cause alloc rebase to offset-1. 240 c.Assert(max-min, Equals, autoid.CalcNeededBatchSize(offset-1, 2, increment, offset, false)) 241 c.Assert(min, Equals, int64(199)) 242 c.Assert(max, Equals, int64(215)) 243 firstID = autoid.SeekToFirstAutoIDSigned(offset-1, increment, offset) 244 c.Assert(firstID, Equals, int64(200)) 245 } 246 247 func (*testSuite) TestUnsignedAutoid(c *C) { 248 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange", `return(true)`), IsNil) 249 defer func() { 250 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange"), IsNil) 251 }() 252 253 causetstore, err := mockstore.NewMockStore() 254 c.Assert(err, IsNil) 255 defer causetstore.Close() 256 257 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 258 m := spacetime.NewMeta(txn) 259 err = m.CreateDatabase(&perceptron.DBInfo{ID: 1, Name: perceptron.NewCIStr("a")}) 260 c.Assert(err, IsNil) 261 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 1, Name: perceptron.NewCIStr("t")}) 262 c.Assert(err, IsNil) 263 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 2, Name: perceptron.NewCIStr("t1")}) 264 c.Assert(err, IsNil) 265 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 3, Name: perceptron.NewCIStr("t1")}) 266 c.Assert(err, IsNil) 267 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 4, Name: perceptron.NewCIStr("t2")}) 268 c.Assert(err, IsNil) 269 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 5, Name: perceptron.NewCIStr("t3")}) 270 c.Assert(err, IsNil) 271 return nil 272 }) 273 c.Assert(err, IsNil) 274 275 alloc := autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 276 c.Assert(alloc, NotNil) 277 278 globalAutoID, err := alloc.NextGlobalAutoID(1) 279 c.Assert(err, IsNil) 280 c.Assert(globalAutoID, Equals, int64(1)) 281 _, id, err := alloc.Alloc(1, 1, 1, 1) 282 c.Assert(err, IsNil) 283 c.Assert(id, Equals, int64(1)) 284 _, id, err = alloc.Alloc(1, 1, 1, 1) 285 c.Assert(err, IsNil) 286 c.Assert(id, Equals, int64(2)) 287 _, _, err = alloc.Alloc(0, 1, 1, 1) 288 c.Assert(err, NotNil) 289 globalAutoID, err = alloc.NextGlobalAutoID(1) 290 c.Assert(err, IsNil) 291 c.Assert(globalAutoID, Equals, autoid.GetStep()+1) 292 293 // rebase 294 err = alloc.Rebase(1, int64(1), true) 295 c.Assert(err, IsNil) 296 _, id, err = alloc.Alloc(1, 1, 1, 1) 297 c.Assert(err, IsNil) 298 c.Assert(id, Equals, int64(3)) 299 err = alloc.Rebase(1, int64(3), true) 300 c.Assert(err, IsNil) 301 _, id, err = alloc.Alloc(1, 1, 1, 1) 302 c.Assert(err, IsNil) 303 c.Assert(id, Equals, int64(4)) 304 err = alloc.Rebase(1, int64(10), true) 305 c.Assert(err, IsNil) 306 _, id, err = alloc.Alloc(1, 1, 1, 1) 307 c.Assert(err, IsNil) 308 c.Assert(id, Equals, int64(11)) 309 err = alloc.Rebase(1, int64(3010), true) 310 c.Assert(err, IsNil) 311 _, id, err = alloc.Alloc(1, 1, 1, 1) 312 c.Assert(err, IsNil) 313 c.Assert(id, Equals, int64(3011)) 314 315 alloc = autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 316 c.Assert(alloc, NotNil) 317 _, id, err = alloc.Alloc(1, 1, 1, 1) 318 c.Assert(err, IsNil) 319 c.Assert(id, Equals, autoid.GetStep()+1) 320 321 alloc = autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 322 c.Assert(alloc, NotNil) 323 err = alloc.Rebase(2, int64(1), false) 324 c.Assert(err, IsNil) 325 _, id, err = alloc.Alloc(2, 1, 1, 1) 326 c.Assert(err, IsNil) 327 c.Assert(id, Equals, int64(2)) 328 329 alloc = autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 330 c.Assert(alloc, NotNil) 331 err = alloc.Rebase(3, int64(3210), false) 332 c.Assert(err, IsNil) 333 alloc = autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 334 c.Assert(alloc, NotNil) 335 err = alloc.Rebase(3, int64(3000), false) 336 c.Assert(err, IsNil) 337 _, id, err = alloc.Alloc(3, 1, 1, 1) 338 c.Assert(err, IsNil) 339 c.Assert(id, Equals, int64(3211)) 340 err = alloc.Rebase(3, int64(6543), false) 341 c.Assert(err, IsNil) 342 _, id, err = alloc.Alloc(3, 1, 1, 1) 343 c.Assert(err, IsNil) 344 c.Assert(id, Equals, int64(6544)) 345 346 // Test the MaxUint64 is the upper bound of `alloc` func but not `rebase`. 347 var n uint64 = math.MaxUint64 - 1 348 un := int64(n) 349 err = alloc.Rebase(3, un, true) 350 c.Assert(err, IsNil) 351 _, _, err = alloc.Alloc(3, 1, 1, 1) 352 c.Assert(err, NotNil) 353 un = int64(n + 1) 354 err = alloc.Rebase(3, un, true) 355 c.Assert(err, IsNil) 356 357 // alloc N for unsigned 358 alloc = autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 359 c.Assert(alloc, NotNil) 360 globalAutoID, err = alloc.NextGlobalAutoID(4) 361 c.Assert(err, IsNil) 362 c.Assert(globalAutoID, Equals, int64(1)) 363 364 min, max, err := alloc.Alloc(4, 2, 1, 1) 365 c.Assert(err, IsNil) 366 c.Assert(max-min, Equals, int64(2)) 367 c.Assert(min+1, Equals, int64(1)) 368 c.Assert(max, Equals, int64(2)) 369 370 err = alloc.Rebase(4, int64(500), true) 371 c.Assert(err, IsNil) 372 min, max, err = alloc.Alloc(4, 2, 1, 1) 373 c.Assert(err, IsNil) 374 c.Assert(max-min, Equals, int64(2)) 375 c.Assert(min+1, Equals, int64(501)) 376 c.Assert(max, Equals, int64(502)) 377 378 lastRemainOne := alloc.End() 379 err = alloc.Rebase(4, alloc.End()-2, false) 380 c.Assert(err, IsNil) 381 min, max, err = alloc.Alloc(4, 5, 1, 1) 382 c.Assert(err, IsNil) 383 c.Assert(max-min, Equals, int64(5)) 384 c.Assert(min+1, Greater, lastRemainOne) 385 386 // Test increment & offset for unsigned. Using AutoRandomType to avoid valid range check for increment and offset. 387 alloc = autoid.NewSlabPredictor(causetstore, 1, true, autoid.AutoRandomType) 388 c.Assert(alloc, NotNil) 389 c.Assert(err, IsNil) 390 c.Assert(globalAutoID, Equals, int64(1)) 391 392 increment := int64(2) 393 n = math.MaxUint64 - 100 394 offset := int64(n) 395 396 min, max, err = alloc.Alloc(5, 2, increment, offset) 397 c.Assert(err, IsNil) 398 c.Assert(uint64(min), Equals, uint64(math.MaxUint64-101)) 399 c.Assert(uint64(max), Equals, uint64(math.MaxUint64-98)) 400 401 c.Assert(max-min, Equals, autoid.CalcNeededBatchSize(int64(uint64(offset)-1), 2, increment, offset, true)) 402 firstID := autoid.SeekToFirstAutoIDUnSigned(uint64(min), uint64(increment), uint64(offset)) 403 c.Assert(firstID, Equals, uint64(math.MaxUint64-100)) 404 405 } 406 407 // TestConcurrentAlloc is used for the test that 408 // multiple allocators allocate ID with the same causet ID concurrently. 409 func (*testSuite) TestConcurrentAlloc(c *C) { 410 causetstore, err := mockstore.NewMockStore() 411 c.Assert(err, IsNil) 412 defer causetstore.Close() 413 autoid.SetStep(100) 414 defer func() { 415 autoid.SetStep(5000) 416 }() 417 418 dbID := int64(2) 419 tblID := int64(100) 420 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 421 m := spacetime.NewMeta(txn) 422 err = m.CreateDatabase(&perceptron.DBInfo{ID: dbID, Name: perceptron.NewCIStr("a")}) 423 c.Assert(err, IsNil) 424 err = m.CreateBlockOrView(dbID, &perceptron.BlockInfo{ID: tblID, Name: perceptron.NewCIStr("t")}) 425 c.Assert(err, IsNil) 426 return nil 427 }) 428 c.Assert(err, IsNil) 429 430 var mu sync.Mutex 431 wg := sync.WaitGroup{} 432 m := map[int64]struct{}{} 433 count := 10 434 errCh := make(chan error, count) 435 436 allocIDs := func() { 437 alloc := autoid.NewSlabPredictor(causetstore, dbID, false, autoid.RowIDAllocType) 438 for j := 0; j < int(autoid.GetStep())+5; j++ { 439 _, id, err1 := alloc.Alloc(tblID, 1, 1, 1) 440 if err1 != nil { 441 errCh <- err1 442 break 443 } 444 445 mu.Lock() 446 if _, ok := m[id]; ok { 447 errCh <- fmt.Errorf("duplicate id:%v", id) 448 mu.Unlock() 449 break 450 } 451 m[id] = struct{}{} 452 mu.Unlock() 453 454 //test Alloc N 455 N := rand.Uint64() % 100 456 min, max, err1 := alloc.Alloc(tblID, N, 1, 1) 457 if err1 != nil { 458 errCh <- err1 459 break 460 } 461 462 errFlag := false 463 mu.Lock() 464 for i := min + 1; i <= max; i++ { 465 if _, ok := m[i]; ok { 466 errCh <- fmt.Errorf("duplicate id:%v", i) 467 errFlag = true 468 mu.Unlock() 469 break 470 } 471 m[i] = struct{}{} 472 } 473 if errFlag { 474 break 475 } 476 mu.Unlock() 477 } 478 } 479 for i := 0; i < count; i++ { 480 wg.Add(1) 481 go func(num int) { 482 defer wg.Done() 483 time.Sleep(time.Duration(num%10) * time.Microsecond) 484 allocIDs() 485 }(i) 486 } 487 wg.Wait() 488 489 close(errCh) 490 err = <-errCh 491 c.Assert(err, IsNil) 492 } 493 494 // TestRollbackAlloc tests that when the allocation transaction commit failed, 495 // the local variable base and end doesn't change. 496 func (*testSuite) TestRollbackAlloc(c *C) { 497 causetstore, err := mockstore.NewMockStore() 498 c.Assert(err, IsNil) 499 defer causetstore.Close() 500 dbID := int64(1) 501 tblID := int64(2) 502 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 503 m := spacetime.NewMeta(txn) 504 err = m.CreateDatabase(&perceptron.DBInfo{ID: dbID, Name: perceptron.NewCIStr("a")}) 505 c.Assert(err, IsNil) 506 err = m.CreateBlockOrView(dbID, &perceptron.BlockInfo{ID: tblID, Name: perceptron.NewCIStr("t")}) 507 c.Assert(err, IsNil) 508 return nil 509 }) 510 c.Assert(err, IsNil) 511 512 injectConf := new(ekv.InjectionConfig) 513 injectConf.SetCommitError(errors.New("injected")) 514 injectedStore := ekv.NewInjectedStore(causetstore, injectConf) 515 alloc := autoid.NewSlabPredictor(injectedStore, 1, false, autoid.RowIDAllocType) 516 _, _, err = alloc.Alloc(2, 1, 1, 1) 517 c.Assert(err, NotNil) 518 c.Assert(alloc.Base(), Equals, int64(0)) 519 c.Assert(alloc.End(), Equals, int64(0)) 520 521 err = alloc.Rebase(2, 100, true) 522 c.Assert(err, NotNil) 523 c.Assert(alloc.Base(), Equals, int64(0)) 524 c.Assert(alloc.End(), Equals, int64(0)) 525 } 526 527 // TestNextStep tests generate next auto id step. 528 func (*testSuite) TestNextStep(c *C) { 529 nextStep := autoid.NextStep(2000000, 1*time.Nanosecond) 530 c.Assert(nextStep, Equals, int64(2000000)) 531 nextStep = autoid.NextStep(678910, 10*time.Second) 532 c.Assert(nextStep, Equals, int64(678910)) 533 nextStep = autoid.NextStep(50000, 10*time.Minute) 534 c.Assert(nextStep, Equals, int64(30000)) 535 } 536 537 func BenchmarkSlabPredictor_Alloc(b *testing.B) { 538 b.StopTimer() 539 causetstore, err := mockstore.NewMockStore() 540 if err != nil { 541 return 542 } 543 defer causetstore.Close() 544 dbID := int64(1) 545 tblID := int64(2) 546 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 547 m := spacetime.NewMeta(txn) 548 err = m.CreateDatabase(&perceptron.DBInfo{ID: dbID, Name: perceptron.NewCIStr("a")}) 549 if err != nil { 550 return err 551 } 552 err = m.CreateBlockOrView(dbID, &perceptron.BlockInfo{ID: tblID, Name: perceptron.NewCIStr("t")}) 553 if err != nil { 554 return err 555 } 556 return nil 557 }) 558 if err != nil { 559 return 560 } 561 alloc := autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 562 b.StartTimer() 563 for i := 0; i < b.N; i++ { 564 alloc.Alloc(2, 1, 1, 1) 565 } 566 } 567 568 func BenchmarkSlabPredictor_SequenceAlloc(b *testing.B) { 569 b.StopTimer() 570 causetstore, err := mockstore.NewMockStore() 571 if err != nil { 572 return 573 } 574 defer causetstore.Close() 575 var seq *perceptron.SequenceInfo 576 var sequenceBase int64 577 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 578 m := spacetime.NewMeta(txn) 579 err = m.CreateDatabase(&perceptron.DBInfo{ID: 1, Name: perceptron.NewCIStr("a")}) 580 if err != nil { 581 return err 582 } 583 seq = &perceptron.SequenceInfo{ 584 Start: 1, 585 Cycle: true, 586 Cache: false, 587 MinValue: -10, 588 MaxValue: math.MaxInt64, 589 Increment: 2, 590 CacheValue: 2000000, 591 } 592 seqBlock := &perceptron.BlockInfo{ 593 ID: 1, 594 Name: perceptron.NewCIStr("seq"), 595 Sequence: seq, 596 } 597 sequenceBase = seq.Start - 1 598 err = m.CreateSequenceAndSetSeqValue(1, seqBlock, sequenceBase) 599 return err 600 }) 601 if err != nil { 602 return 603 } 604 alloc := autoid.NewSequenceSlabPredictor(causetstore, 1, seq) 605 b.StartTimer() 606 for i := 0; i < b.N; i++ { 607 _, _, _, err := alloc.AllocSeqCache(1) 608 if err != nil { 609 fmt.Println("err") 610 } 611 } 612 } 613 614 func BenchmarkSlabPredictor_Seek(b *testing.B) { 615 base := int64(21421948021) 616 offset := int64(-351354365326) 617 increment := int64(3) 618 b.StartTimer() 619 for i := 0; i < b.N; i++ { 620 autoid.CalcSequenceBatchSize(base, 3, increment, offset, math.MinInt64, math.MaxInt64) 621 } 622 } 623 624 func (*testSuite) TestSequenceAutoid(c *C) { 625 causetstore, err := mockstore.NewMockStore() 626 c.Assert(err, IsNil) 627 defer causetstore.Close() 628 629 var seq *perceptron.SequenceInfo 630 var sequenceBase int64 631 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 632 m := spacetime.NewMeta(txn) 633 err = m.CreateDatabase(&perceptron.DBInfo{ID: 1, Name: perceptron.NewCIStr("a")}) 634 c.Assert(err, IsNil) 635 seq = &perceptron.SequenceInfo{ 636 Start: 1, 637 Cycle: true, 638 Cache: true, 639 MinValue: -10, 640 MaxValue: 10, 641 Increment: 2, 642 CacheValue: 3, 643 } 644 seqBlock := &perceptron.BlockInfo{ 645 ID: 1, 646 Name: perceptron.NewCIStr("seq"), 647 Sequence: seq, 648 } 649 sequenceBase = seq.Start - 1 650 err = m.CreateSequenceAndSetSeqValue(1, seqBlock, sequenceBase) 651 c.Assert(err, IsNil) 652 return nil 653 }) 654 c.Assert(err, IsNil) 655 656 alloc := autoid.NewSequenceSlabPredictor(causetstore, 1, seq) 657 c.Assert(alloc, NotNil) 658 659 // allocate sequence cache. 660 base, end, round, err := alloc.AllocSeqCache(1) 661 c.Assert(err, IsNil) 662 c.Assert(base, Equals, int64(0)) 663 c.Assert(end, Equals, int64(5)) 664 c.Assert(round, Equals, int64(0)) 665 666 // test the sequence batch size. 667 offset := seq.Start 668 size, err := autoid.CalcSequenceBatchSize(sequenceBase, seq.CacheValue, seq.Increment, offset, seq.MinValue, seq.MaxValue) 669 c.Assert(err, IsNil) 670 c.Assert(size, Equals, end-base) 671 672 // simulate the next value allocation. 673 nextVal, ok := autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 674 c.Assert(ok, Equals, true) 675 c.Assert(nextVal, Equals, int64(1)) 676 base = nextVal 677 678 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 679 c.Assert(ok, Equals, true) 680 c.Assert(nextVal, Equals, int64(3)) 681 base = nextVal 682 683 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 684 c.Assert(ok, Equals, true) 685 c.Assert(nextVal, Equals, int64(5)) 686 687 base, end, round, err = alloc.AllocSeqCache(1) 688 c.Assert(err, IsNil) 689 c.Assert(base, Equals, int64(5)) 690 c.Assert(end, Equals, int64(10)) 691 c.Assert(round, Equals, int64(0)) 692 693 // test the sequence batch size. 694 size, err = autoid.CalcSequenceBatchSize(sequenceBase, seq.CacheValue, seq.Increment, offset, seq.MinValue, seq.MaxValue) 695 c.Assert(err, IsNil) 696 c.Assert(size, Equals, end-base) 697 698 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 699 c.Assert(ok, Equals, true) 700 c.Assert(nextVal, Equals, int64(7)) 701 base = nextVal 702 703 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 704 c.Assert(ok, Equals, true) 705 c.Assert(nextVal, Equals, int64(9)) 706 base = nextVal 707 708 _, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 709 // the rest in cache in not enough for next value. 710 c.Assert(ok, Equals, false) 711 712 base, end, round, err = alloc.AllocSeqCache(1) 713 c.Assert(err, IsNil) 714 c.Assert(base, Equals, int64(-11)) 715 c.Assert(end, Equals, int64(-6)) 716 // the round is already in cycle. 717 c.Assert(round, Equals, int64(1)) 718 719 // test the sequence batch size. 720 size, err = autoid.CalcSequenceBatchSize(sequenceBase, seq.CacheValue, seq.Increment, offset, seq.MinValue, seq.MaxValue) 721 c.Assert(err, IsNil) 722 c.Assert(size, Equals, end-base) 723 724 offset = seq.MinValue 725 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 726 c.Assert(ok, Equals, true) 727 c.Assert(nextVal, Equals, int64(-10)) 728 base = nextVal 729 730 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 731 c.Assert(ok, Equals, true) 732 c.Assert(nextVal, Equals, int64(-8)) 733 base = nextVal 734 735 nextVal, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 736 c.Assert(ok, Equals, true) 737 c.Assert(nextVal, Equals, int64(-6)) 738 base = nextVal 739 740 _, ok = autoid.SeekToFirstSequenceValue(base, seq.Increment, offset, base, end) 741 // the cache is already empty. 742 c.Assert(ok, Equals, false) 743 } 744 745 func (*testSuite) TestConcurrentAllocSequence(c *C) { 746 causetstore, err := mockstore.NewMockStore() 747 c.Assert(err, IsNil) 748 defer causetstore.Close() 749 750 var seq *perceptron.SequenceInfo 751 var sequenceBase int64 752 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 753 m := spacetime.NewMeta(txn) 754 err1 := m.CreateDatabase(&perceptron.DBInfo{ID: 2, Name: perceptron.NewCIStr("a")}) 755 c.Assert(err1, IsNil) 756 seq = &perceptron.SequenceInfo{ 757 Start: 100, 758 Cycle: false, 759 Cache: true, 760 MinValue: -100, 761 MaxValue: 100, 762 Increment: -2, 763 CacheValue: 3, 764 } 765 seqBlock := &perceptron.BlockInfo{ 766 ID: 2, 767 Name: perceptron.NewCIStr("seq"), 768 Sequence: seq, 769 } 770 if seq.Increment >= 0 { 771 sequenceBase = seq.Start - 1 772 } else { 773 sequenceBase = seq.Start + 1 774 } 775 err1 = m.CreateSequenceAndSetSeqValue(2, seqBlock, sequenceBase) 776 c.Assert(err1, IsNil) 777 return nil 778 }) 779 c.Assert(err, IsNil) 780 781 var mu sync.Mutex 782 wg := sync.WaitGroup{} 783 m := map[int64]struct{}{} 784 count := 10 785 errCh := make(chan error, count) 786 787 allocSequence := func() { 788 alloc := autoid.NewSequenceSlabPredictor(causetstore, 2, seq) 789 for j := 0; j < 3; j++ { 790 base, end, _, err1 := alloc.AllocSeqCache(2) 791 if err1 != nil { 792 errCh <- err1 793 break 794 } 795 796 errFlag := false 797 mu.Lock() 798 // sequence is negative-growth here. 799 for i := base - 1; i >= end; i-- { 800 if _, ok := m[i]; ok { 801 errCh <- fmt.Errorf("duplicate id:%v", i) 802 errFlag = true 803 mu.Unlock() 804 break 805 } 806 m[i] = struct{}{} 807 } 808 if errFlag { 809 break 810 } 811 mu.Unlock() 812 } 813 } 814 for i := 0; i < count; i++ { 815 wg.Add(1) 816 go func(num int) { 817 time.Sleep(time.Duration(num%10) * time.Microsecond) 818 allocSequence() 819 wg.Done() 820 }(i) 821 } 822 wg.Wait() 823 824 close(errCh) 825 err = <-errCh 826 c.Assert(err, IsNil) 827 } 828 829 // Fix a computation logic bug in allocator computation. 830 func (*testSuite) TestAllocComputationIssue(c *C) { 831 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDCustomize", `return(true)`), IsNil) 832 defer func() { 833 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDCustomize"), IsNil) 834 }() 835 836 causetstore, err := mockstore.NewMockStore() 837 c.Assert(err, IsNil) 838 defer causetstore.Close() 839 840 err = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error { 841 m := spacetime.NewMeta(txn) 842 err = m.CreateDatabase(&perceptron.DBInfo{ID: 1, Name: perceptron.NewCIStr("a")}) 843 c.Assert(err, IsNil) 844 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 1, Name: perceptron.NewCIStr("t")}) 845 c.Assert(err, IsNil) 846 err = m.CreateBlockOrView(1, &perceptron.BlockInfo{ID: 2, Name: perceptron.NewCIStr("t1")}) 847 c.Assert(err, IsNil) 848 return nil 849 }) 850 c.Assert(err, IsNil) 851 852 // Since the test here is applicable to any type of allocators, autoid.RowIDAllocType is chosen. 853 unsignedAlloc := autoid.NewSlabPredictor(causetstore, 1, true, autoid.RowIDAllocType) 854 c.Assert(unsignedAlloc, NotNil) 855 signedAlloc := autoid.NewSlabPredictor(causetstore, 1, false, autoid.RowIDAllocType) 856 c.Assert(signedAlloc, NotNil) 857 858 // the next valid two value must be 13 & 16, batch size = 6. 859 err = unsignedAlloc.Rebase(1, 10, false) 860 c.Assert(err, IsNil) 861 // the next valid two value must be 10 & 13, batch size = 6. 862 err = signedAlloc.Rebase(2, 7, false) 863 c.Assert(err, IsNil) 864 // Simulate the rest cache is not enough for next batch, assuming 10 & 13, batch size = 4. 865 autoid.TestModifyBaseAndEndInjection(unsignedAlloc, 9, 9) 866 // Simulate the rest cache is not enough for next batch, assuming 10 & 13, batch size = 4. 867 autoid.TestModifyBaseAndEndInjection(signedAlloc, 4, 6) 868 869 // Here will recompute the new allocator batch size base on new base = 10, which will get 6. 870 min, max, err := unsignedAlloc.Alloc(1, 2, 3, 1) 871 c.Assert(err, IsNil) 872 c.Assert(min, Equals, int64(10)) 873 c.Assert(max, Equals, int64(16)) 874 min, max, err = signedAlloc.Alloc(2, 2, 3, 1) 875 c.Assert(err, IsNil) 876 c.Assert(min, Equals, int64(7)) 877 c.Assert(max, Equals, int64(13)) 878 }