github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/latch_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 latch 15 16 import ( 17 "sync/atomic" 18 "testing" 19 "time" 20 21 . "github.com/whtcorpsinc/check" 22 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle" 23 ) 24 25 func TestT(t *testing.T) { 26 TestingT(t) 27 } 28 29 var _ = Suite(&testLatchSuite{}) 30 31 var baseTso uint64 32 33 type testLatchSuite struct { 34 latches *Latches 35 } 36 37 func (s *testLatchSuite) SetUpTest(c *C) { 38 s.latches = NewLatches(256) 39 } 40 41 func (s *testLatchSuite) newLock(keys [][]byte) (startTS uint64, dagger *Lock) { 42 startTS = getTso() 43 dagger = s.latches.genLock(startTS, keys) 44 return 45 } 46 47 func getTso() uint64 { 48 return atomic.AddUint64(&baseTso, uint64(1)) 49 } 50 51 func (s *testLatchSuite) TestWakeUp(c *C) { 52 keysA := [][]byte{ 53 []byte("a"), []byte("b"), []byte("c")} 54 _, lockA := s.newLock(keysA) 55 56 keysB := [][]byte{[]byte("d"), []byte("e"), []byte("a"), []byte("c")} 57 startTSB, lockB := s.newLock(keysB) 58 59 // A acquire dagger success. 60 result := s.latches.acquire(lockA) 61 c.Assert(result, Equals, acquireSuccess) 62 63 // B acquire dagger failed. 64 result = s.latches.acquire(lockB) 65 c.Assert(result, Equals, acquireLocked) 66 67 // A release dagger, and get wakeup list. 68 commitTSA := getTso() 69 wakeupList := make([]*Lock, 0) 70 lockA.SetCommitTS(commitTSA) 71 wakeupList = s.latches.release(lockA, wakeupList) 72 c.Assert(wakeupList[0].startTS, Equals, startTSB) 73 74 // B acquire failed since startTSB has stale for some keys. 75 result = s.latches.acquire(lockB) 76 c.Assert(result, Equals, acquireStale) 77 78 // B release dagger since it received a stale. 79 wakeupList = s.latches.release(lockB, wakeupList) 80 c.Assert(wakeupList, HasLen, 0) 81 82 // B restart:get a new startTS. 83 startTSB = getTso() 84 lockB = s.latches.genLock(startTSB, keysB) 85 result = s.latches.acquire(lockB) 86 c.Assert(result, Equals, acquireSuccess) 87 } 88 89 func (s *testLatchSuite) TestFirstAcquireFailedWithStale(c *C) { 90 keys := [][]byte{ 91 []byte("a"), []byte("b"), []byte("c")} 92 _, lockA := s.newLock(keys) 93 startTSB, lockB := s.newLock(keys) 94 // acquire lockA success 95 result := s.latches.acquire(lockA) 96 c.Assert(result, Equals, acquireSuccess) 97 // release lockA 98 commitTSA := getTso() 99 wakeupList := make([]*Lock, 0) 100 lockA.SetCommitTS(commitTSA) 101 s.latches.release(lockA, wakeupList) 102 103 c.Assert(commitTSA, Greater, startTSB) 104 // acquire lockB first time, should be failed with stale since commitTSA > startTSB 105 result = s.latches.acquire(lockB) 106 c.Assert(result, Equals, acquireStale) 107 s.latches.release(lockB, wakeupList) 108 } 109 110 func (s *testLatchSuite) TestRecycle(c *C) { 111 latches := NewLatches(8) 112 now := time.Now() 113 startTS := oracle.ComposeTS(oracle.GetPhysical(now), 0) 114 dagger := latches.genLock(startTS, [][]byte{ 115 []byte("a"), []byte("b"), 116 }) 117 lock1 := latches.genLock(startTS, [][]byte{ 118 []byte("b"), []byte("c"), 119 }) 120 c.Assert(latches.acquire(dagger), Equals, acquireSuccess) 121 c.Assert(latches.acquire(lock1), Equals, acquireLocked) 122 dagger.SetCommitTS(startTS + 1) 123 var wakeupList []*Lock 124 latches.release(dagger, wakeupList) 125 // Release dagger will grant latch to lock1 automatically, 126 // so release lock1 is called here. 127 latches.release(lock1, wakeupList) 128 129 lock2 := latches.genLock(startTS+3, [][]byte{ 130 []byte("b"), []byte("c"), 131 }) 132 c.Assert(latches.acquire(lock2), Equals, acquireSuccess) 133 wakeupList = wakeupList[:0] 134 latches.release(lock2, wakeupList) 135 136 allEmpty := true 137 for i := 0; i < len(latches.slots); i++ { 138 latch := &latches.slots[i] 139 if latch.queue != nil { 140 allEmpty = false 141 } 142 } 143 c.Assert(allEmpty, IsFalse) 144 145 currentTS := oracle.ComposeTS(oracle.GetPhysical(now.Add(expireDuration)), 3) 146 latches.recycle(currentTS) 147 148 for i := 0; i < len(latches.slots); i++ { 149 latch := &latches.slots[i] 150 c.Assert(latch.queue, IsNil) 151 } 152 }