github.com/KinWaiYuen/client-go/v2@v2.5.4/txnkv/transaction/test_probe.go (about) 1 // Copyright 2021 TiKV Authors 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package transaction 16 17 import ( 18 "bytes" 19 "context" 20 "sync/atomic" 21 "time" 22 23 "github.com/KinWaiYuen/client-go/v2/internal/locate" 24 "github.com/KinWaiYuen/client-go/v2/internal/retry" 25 "github.com/KinWaiYuen/client-go/v2/internal/unionstore" 26 "github.com/KinWaiYuen/client-go/v2/tikvrpc" 27 "github.com/KinWaiYuen/client-go/v2/txnkv/txnsnapshot" 28 "github.com/pingcap/errors" 29 ) 30 31 // TxnProbe wraps a txn and exports internal states for testing purpose. 32 type TxnProbe struct { 33 *KVTxn 34 } 35 36 // SetStartTS resets the txn's start ts. 37 func (txn TxnProbe) SetStartTS(ts uint64) { 38 txn.startTS = ts 39 } 40 41 // GetCommitTS returns the commit ts. 42 func (txn TxnProbe) GetCommitTS() uint64 { 43 return txn.commitTS 44 } 45 46 // GetUnionStore returns transaction's embedded unionstore. 47 func (txn TxnProbe) GetUnionStore() *unionstore.KVUnionStore { 48 return txn.us 49 } 50 51 // IsAsyncCommit returns if the txn is committed using async commit. 52 func (txn TxnProbe) IsAsyncCommit() bool { 53 return txn.committer.isAsyncCommit() 54 } 55 56 // NewCommitter creates an committer. 57 func (txn TxnProbe) NewCommitter(sessionID uint64) (CommitterProbe, error) { 58 committer, err := newTwoPhaseCommitterWithInit(txn.KVTxn, sessionID) 59 return CommitterProbe{twoPhaseCommitter: committer}, err 60 } 61 62 // GetCommitter returns the transaction committer. 63 func (txn TxnProbe) GetCommitter() CommitterProbe { 64 return CommitterProbe{txn.committer} 65 } 66 67 // SetCommitter sets the bind committer of a transaction. 68 func (txn TxnProbe) SetCommitter(committer CommitterProbe) { 69 txn.committer = committer.twoPhaseCommitter 70 } 71 72 // CollectLockedKeys returns all locked keys of a transaction. 73 func (txn TxnProbe) CollectLockedKeys() [][]byte { 74 return txn.collectLockedKeys() 75 } 76 77 // BatchGetSingleRegion gets a batch of keys from a region. 78 func (txn TxnProbe) BatchGetSingleRegion(bo *retry.Backoffer, region locate.RegionVerID, keys [][]byte, collect func([]byte, []byte)) error { 79 snapshot := txnsnapshot.SnapshotProbe{KVSnapshot: txn.GetSnapshot()} 80 81 return snapshot.BatchGetSingleRegion(bo, region, keys, collect) 82 } 83 84 // NewScanner returns a scanner to iterate given key range. 85 func (txn TxnProbe) NewScanner(start, end []byte, batchSize int, reverse bool) (*txnsnapshot.Scanner, error) { 86 snapshot := txnsnapshot.SnapshotProbe{KVSnapshot: txn.GetSnapshot()} 87 return snapshot.NewScanner(start, end, batchSize, reverse) 88 } 89 90 // GetStartTime returns the time when txn starts. 91 func (txn TxnProbe) GetStartTime() time.Time { 92 return txn.startTime 93 } 94 95 func newTwoPhaseCommitterWithInit(txn *KVTxn, sessionID uint64) (*twoPhaseCommitter, error) { 96 c, err := newTwoPhaseCommitter(txn, sessionID) 97 if err != nil { 98 return nil, errors.Trace(err) 99 } 100 if err = c.initKeysAndMutations(); err != nil { 101 return nil, errors.Trace(err) 102 } 103 return c, nil 104 } 105 106 // CommitterProbe wraps a 2PC committer and exports internal states for testing purpose. 107 type CommitterProbe struct { 108 *twoPhaseCommitter 109 } 110 111 // InitKeysAndMutations prepares the committer for commit. 112 func (c CommitterProbe) InitKeysAndMutations() error { 113 return c.initKeysAndMutations() 114 } 115 116 // SetPrimaryKey resets the committer's commit ts. 117 func (c CommitterProbe) SetPrimaryKey(key []byte) { 118 c.primaryKey = key 119 } 120 121 // GetPrimaryKey returns primary key of the committer. 122 func (c CommitterProbe) GetPrimaryKey() []byte { 123 return c.primaryKey 124 } 125 126 // GetMutations returns the mutation buffer to commit. 127 func (c CommitterProbe) GetMutations() CommitterMutations { 128 return c.mutations 129 } 130 131 // SetMutations replace the mutation buffer. 132 func (c CommitterProbe) SetMutations(muts CommitterMutations) { 133 c.mutations = muts.(*memBufferMutations) 134 } 135 136 // SetCommitTS resets the committer's commit ts. 137 func (c CommitterProbe) SetCommitTS(ts uint64) { 138 atomic.StoreUint64(&c.commitTS, ts) 139 } 140 141 // GetCommitTS returns the commit ts of the committer. 142 func (c CommitterProbe) GetCommitTS() uint64 { 143 return atomic.LoadUint64(&c.commitTS) 144 } 145 146 // GetMinCommitTS returns the minimal commit ts can be used. 147 func (c CommitterProbe) GetMinCommitTS() uint64 { 148 return c.minCommitTS 149 } 150 151 // SetMinCommitTS sets the minimal commit ts can be used. 152 func (c CommitterProbe) SetMinCommitTS(ts uint64) { 153 c.minCommitTS = ts 154 } 155 156 // SetMaxCommitTS sets the max commit ts can be used. 157 func (c CommitterProbe) SetMaxCommitTS(ts uint64) { 158 c.maxCommitTS = ts 159 } 160 161 // SetSessionID sets the session id of the committer. 162 func (c CommitterProbe) SetSessionID(id uint64) { 163 c.sessionID = id 164 } 165 166 // GetForUpdateTS returns the pessimistic ForUpdate ts. 167 func (c CommitterProbe) GetForUpdateTS() uint64 { 168 return c.forUpdateTS 169 } 170 171 // SetForUpdateTS sets pessimistic ForUpdate ts. 172 func (c CommitterProbe) SetForUpdateTS(ts uint64) { 173 c.forUpdateTS = ts 174 } 175 176 // GetStartTS returns the start ts of the transaction. 177 func (c CommitterProbe) GetStartTS() uint64 { 178 return c.startTS 179 } 180 181 // GetLockTTL returns the lock ttl duration of the transaction. 182 func (c CommitterProbe) GetLockTTL() uint64 { 183 return c.lockTTL 184 } 185 186 // SetLockTTL sets the lock ttl duration. 187 func (c CommitterProbe) SetLockTTL(ttl uint64) { 188 c.lockTTL = ttl 189 } 190 191 // SetLockTTLByTimeAndSize sets the lock ttl duration by time and size. 192 func (c CommitterProbe) SetLockTTLByTimeAndSize(start time.Time, size int) { 193 c.lockTTL = txnLockTTL(start, size) 194 } 195 196 // SetTxnSize resets the txn size of the committer and updates lock TTL. 197 func (c CommitterProbe) SetTxnSize(sz int) { 198 c.txnSize = sz 199 c.lockTTL = txnLockTTL(c.txn.startTime, sz) 200 } 201 202 // SetUseAsyncCommit enables async commit feature. 203 func (c CommitterProbe) SetUseAsyncCommit() { 204 c.useAsyncCommit = 1 205 } 206 207 // Execute runs the commit process. 208 func (c CommitterProbe) Execute(ctx context.Context) error { 209 return c.execute(ctx) 210 } 211 212 // PrewriteAllMutations performs the first phase of commit. 213 func (c CommitterProbe) PrewriteAllMutations(ctx context.Context) error { 214 return c.PrewriteMutations(ctx, c.mutations) 215 } 216 217 // PrewriteMutations performs the first phase of commit for given keys. 218 func (c CommitterProbe) PrewriteMutations(ctx context.Context, mutations CommitterMutations) error { 219 return c.prewriteMutations(retry.NewBackofferWithVars(ctx, PrewriteMaxBackoff, nil), mutations) 220 } 221 222 // CommitMutations performs the second phase of commit. 223 func (c CommitterProbe) CommitMutations(ctx context.Context) error { 224 return c.commitMutations(retry.NewBackofferWithVars(ctx, int(atomic.LoadUint64(&CommitMaxBackoff)), nil), c.mutationsOfKeys([][]byte{c.primaryKey})) 225 } 226 227 // MutationsOfKeys returns mutations match the keys. 228 func (c CommitterProbe) MutationsOfKeys(keys [][]byte) CommitterMutations { 229 return c.mutationsOfKeys(keys) 230 } 231 232 // PessimisticRollbackMutations rolls mutations back. 233 func (c CommitterProbe) PessimisticRollbackMutations(ctx context.Context, muts CommitterMutations) error { 234 return c.pessimisticRollbackMutations(retry.NewBackofferWithVars(ctx, pessimisticRollbackMaxBackoff, nil), muts) 235 } 236 237 // Cleanup cleans dirty data of a committer. 238 func (c CommitterProbe) Cleanup(ctx context.Context) { 239 c.cleanup(ctx) 240 c.cleanWg.Wait() 241 } 242 243 // WaitCleanup waits for the committer to complete. 244 func (c CommitterProbe) WaitCleanup() { 245 c.cleanWg.Wait() 246 } 247 248 // IsOnePC returns if the committer is using one PC. 249 func (c CommitterProbe) IsOnePC() bool { 250 return c.isOnePC() 251 } 252 253 // BuildPrewriteRequest builds rpc request for mutation. 254 func (c CommitterProbe) BuildPrewriteRequest(regionID, regionConf, regionVersion uint64, mutations CommitterMutations, txnSize uint64) *tikvrpc.Request { 255 var batch batchMutations 256 batch.mutations = mutations 257 batch.region = locate.NewRegionVerID(regionID, regionConf, regionVersion) 258 for _, key := range mutations.GetKeys() { 259 if bytes.Equal(key, c.primary()) { 260 batch.isPrimary = true 261 break 262 } 263 } 264 return c.buildPrewriteRequest(batch, txnSize) 265 } 266 267 // IsAsyncCommit returns if the committer uses async commit. 268 func (c CommitterProbe) IsAsyncCommit() bool { 269 return c.isAsyncCommit() 270 } 271 272 // CheckAsyncCommit returns if async commit is available. 273 func (c CommitterProbe) CheckAsyncCommit() bool { 274 return c.checkAsyncCommit() 275 } 276 277 // GetOnePCCommitTS returns the commit ts of one pc. 278 func (c CommitterProbe) GetOnePCCommitTS() uint64 { 279 return c.onePCCommitTS 280 } 281 282 // IsTTLUninitialized returns if the TTL manager is uninitialized. 283 func (c CommitterProbe) IsTTLUninitialized() bool { 284 state := atomic.LoadUint32((*uint32)(&c.ttlManager.state)) 285 return state == uint32(stateUninitialized) 286 } 287 288 // IsTTLRunning returns if the TTL manager is running state. 289 func (c CommitterProbe) IsTTLRunning() bool { 290 state := atomic.LoadUint32((*uint32)(&c.ttlManager.state)) 291 return state == uint32(stateRunning) 292 } 293 294 // CloseTTLManager closes the TTL manager. 295 func (c CommitterProbe) CloseTTLManager() { 296 c.ttlManager.close() 297 } 298 299 // GetUndeterminedErr returns the encountered undetermined error (if any). 300 func (c CommitterProbe) GetUndeterminedErr() error { 301 c.mu.RLock() 302 defer c.mu.RUnlock() 303 return c.mu.undeterminedErr 304 } 305 306 // SetNoFallBack disallows async commit to fall back to normal mode. 307 func (c CommitterProbe) SetNoFallBack() { 308 c.testingKnobs.noFallBack = true 309 } 310 311 // SetPrimaryKeyBlocker is used to block committer after primary is sent. 312 func (c CommitterProbe) SetPrimaryKeyBlocker(ac, bk chan struct{}) { 313 c.testingKnobs.acAfterCommitPrimary = ac 314 c.testingKnobs.bkAfterCommitPrimary = bk 315 } 316 317 // CleanupMutations performs the clean up phase. 318 func (c CommitterProbe) CleanupMutations(ctx context.Context) error { 319 bo := retry.NewBackofferWithVars(ctx, cleanupMaxBackoff, nil) 320 return c.cleanupMutations(bo, c.mutations) 321 } 322 323 // SendTxnHeartBeat renews a txn's ttl. 324 func SendTxnHeartBeat(bo *retry.Backoffer, store kvstore, primary []byte, startTS, ttl uint64) (newTTL uint64, stopHeartBeat bool, err error) { 325 return sendTxnHeartBeat(bo, store, primary, startTS, ttl) 326 } 327 328 // ConfigProbe exposes configurations and global variables for testing purpose. 329 type ConfigProbe struct{} 330 331 // GetTxnCommitBatchSize returns the batch size to commit txn. 332 func (c ConfigProbe) GetTxnCommitBatchSize() uint64 { 333 return txnCommitBatchSize 334 } 335 336 // GetPessimisticLockMaxBackoff returns pessimisticLockMaxBackoff 337 func (c ConfigProbe) GetPessimisticLockMaxBackoff() int { 338 return pessimisticLockMaxBackoff 339 } 340 341 // GetDefaultLockTTL returns the default lock TTL. 342 func (c ConfigProbe) GetDefaultLockTTL() uint64 { 343 return defaultLockTTL 344 } 345 346 // GetTTLFactor returns the factor to calculate txn TTL. 347 func (c ConfigProbe) GetTTLFactor() int { 348 return ttlFactor 349 } 350 351 // LoadPreSplitDetectThreshold returns presplit detect threshold config. 352 func (c ConfigProbe) LoadPreSplitDetectThreshold() uint32 { 353 return atomic.LoadUint32(&preSplitDetectThreshold) 354 } 355 356 // StorePreSplitDetectThreshold updates presplit detect threshold config. 357 func (c ConfigProbe) StorePreSplitDetectThreshold(v uint32) { 358 atomic.StoreUint32(&preSplitDetectThreshold, v) 359 } 360 361 // LoadPreSplitSizeThreshold returns presplit size threshold config. 362 func (c ConfigProbe) LoadPreSplitSizeThreshold() uint32 { 363 return atomic.LoadUint32(&preSplitSizeThreshold) 364 } 365 366 // StorePreSplitSizeThreshold updates presplit size threshold config. 367 func (c ConfigProbe) StorePreSplitSizeThreshold(v uint32) { 368 atomic.StoreUint32(&preSplitSizeThreshold, v) 369 }