github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/shardddl/pessimism/keeper.go (about) 1 // Copyright 2020 PingCAP, 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 pessimism 15 16 import ( 17 "sync" 18 19 "github.com/pingcap/tiflow/dm/master/metrics" 20 "github.com/pingcap/tiflow/dm/pkg/utils" 21 ) 22 23 // LockKeeper used to keep and handle DDL lock conveniently. 24 // The lock information do not need to be persistent, and can be re-constructed from the shard DDL info. 25 type LockKeeper struct { 26 mu sync.RWMutex 27 locks map[string]*Lock // lockID -> Lock 28 } 29 30 // NewLockKeeper creates a new LockKeeper instance. 31 func NewLockKeeper() *LockKeeper { 32 return &LockKeeper{ 33 locks: make(map[string]*Lock), 34 } 35 } 36 37 // TrySync tries to sync the lock. 38 func (lk *LockKeeper) TrySync(info Info, sources []string) (string, bool, int, error) { 39 var ( 40 lockID = genDDLLockID(info) 41 l *Lock 42 ok bool 43 ) 44 45 lk.mu.Lock() 46 defer lk.mu.Unlock() 47 48 if l, ok = lk.locks[lockID]; !ok { 49 lk.locks[lockID] = NewLock(lockID, info.Task, info.Source, info.DDLs, sources) 50 l = lk.locks[lockID] 51 } 52 53 synced, remain, err := l.TrySync(info.Source, info.DDLs, sources) 54 return lockID, synced, remain, err 55 } 56 57 // RemoveLock removes a lock. 58 func (lk *LockKeeper) RemoveLock(lockID string) bool { 59 lk.mu.Lock() 60 defer lk.mu.Unlock() 61 62 _, ok := lk.locks[lockID] 63 delete(lk.locks, lockID) 64 metrics.RemoveDDLPending(utils.ExtractTaskFromLockID(lockID)) 65 return ok 66 } 67 68 // RemoveLockByInfo removes a lock through given info. 69 func (lk *LockKeeper) RemoveLockByInfo(info Info) bool { 70 lockID := genDDLLockID(info) 71 return lk.RemoveLock(lockID) 72 } 73 74 // FindLock finds a lock. 75 func (lk *LockKeeper) FindLock(lockID string) *Lock { 76 lk.mu.RLock() 77 defer lk.mu.RUnlock() 78 79 return lk.locks[lockID] 80 } 81 82 // Locks return a copy of all Locks. 83 func (lk *LockKeeper) Locks() map[string]*Lock { 84 lk.mu.RLock() 85 defer lk.mu.RUnlock() 86 87 locks := make(map[string]*Lock, len(lk.locks)) 88 for k, v := range lk.locks { 89 locks[k] = v 90 } 91 return locks 92 } 93 94 // Clear clears all Locks. 95 func (lk *LockKeeper) Clear() { 96 lk.mu.Lock() 97 defer lk.mu.Unlock() 98 99 lk.locks = make(map[string]*Lock) 100 } 101 102 // genDDLLockID generates DDL lock ID from its info. 103 func genDDLLockID(info Info) string { 104 return utils.GenDDLLockID(info.Task, info.Schema, info.Table) 105 }