|
- package lock
-
- import (
- "github.com/go-xorm/xorm"
-
- "xorm.io/builder"
- )
-
- import (
- "github.com/transaction-wg/seata-golang/pkg/tc/model"
- "github.com/transaction-wg/seata-golang/pkg/util/log"
- )
-
- const (
- BatchDeleteLockByBranchID = `delete from lock_table where xid = ? AND branch_id = ?`
- GetLockDOCount = "select count(1) as total from lock_table"
- )
-
- type LockStore interface {
- AcquireLockByLockDO(lockDO *model.LockDO) bool
- AcquireLock(lockDOs []*model.LockDO) bool
- UnLockByLockDO(lockDO *model.LockDO) bool
- UnLock(lockDOs []*model.LockDO) bool
- UnLockByXIDAndBranchID(xid string, branchID int64) bool
- UnLockByXIDAndBranchIDs(xid string, branchIDs []int64) bool
- IsLockable(lockDOs []*model.LockDO) bool
- GetLockCount() int64
- }
-
- type LockStoreDataBaseDao struct {
- engine *xorm.Engine
- }
-
- func (dao *LockStoreDataBaseDao) AcquireLockByLockDO(lockDO *model.LockDO) bool {
- var lockDOs = []*model.LockDO{lockDO}
- return dao.AcquireLock(lockDOs)
- }
-
- func (dao *LockStoreDataBaseDao) AcquireLock(lockDOs []*model.LockDO) bool {
- locks, rowKeys := distinctByKey(lockDOs)
- var existedRowLocks []*model.LockDO
- err := dao.engine.Table("lock_table").
- Where(builder.In("row_key", rowKeys)).
- Find(&existedRowLocks)
- if err != nil {
- log.Errorf(err.Error())
- }
- currentXID := locks[0].Xid
- canLock := true
- existedRowKeys := make([]string, 0)
- unrepeatedLockDOs := make([]*model.LockDO, 0)
- for _, rowLock := range existedRowLocks {
- if rowLock.Xid != currentXID {
- log.Infof("Global lock on [{%s}:{%s}] is holding by xid {%s} branchID {%d}", "lock_table", rowLock.Pk, rowLock.Xid,
- rowLock.BranchID)
- canLock = false
- break
- }
- existedRowKeys = append(existedRowKeys, rowLock.RowKey)
- }
- if !canLock {
- return false
- }
- if len(existedRowKeys) > 0 {
- for _, lock := range locks {
- if !contains(existedRowKeys, lock.RowKey) {
- unrepeatedLockDOs = append(unrepeatedLockDOs, lock)
- }
- }
- } else {
- unrepeatedLockDOs = locks
- }
-
- if len(unrepeatedLockDOs) == 0 {
- return true
- }
-
- _, err = dao.engine.Table("lock_table").Insert(unrepeatedLockDOs)
- if err != nil {
- log.Errorf("Global locks batch acquire failed, %v, err: %v", unrepeatedLockDOs, err)
- return false
- }
- return true
- }
-
- func distinctByKey(lockDOs []*model.LockDO) ([]*model.LockDO, []string) {
- result := make([]*model.LockDO, 0)
- rowKeys := make([]string, 0)
- lockMap := make(map[string]byte)
- for _, lockDO := range lockDOs {
- l := len(lockMap)
- lockMap[lockDO.RowKey] = 0
- if len(lockMap) != l {
- result = append(result, lockDO)
- rowKeys = append(rowKeys, lockDO.RowKey)
- }
- }
- return result, rowKeys
- }
-
- func contains(s []string, e string) bool {
- for _, a := range s {
- if a == e {
- return true
- }
- }
- return false
- }
-
- func (dao *LockStoreDataBaseDao) UnLockByLockDO(lockDO *model.LockDO) bool {
- var lockDOs = []*model.LockDO{lockDO}
- return dao.UnLock(lockDOs)
- }
-
- func (dao *LockStoreDataBaseDao) UnLock(lockDOs []*model.LockDO) bool {
- if lockDOs != nil && len(lockDOs) == 0 {
- return true
- }
- rowKeys := make([]string, 0)
- for _, lockDO := range lockDOs {
- rowKeys = append(rowKeys, lockDO.RowKey)
- }
-
- var lock = model.LockDO{}
- _, err := dao.engine.Table("lock_table").
- Where(builder.In("row_key", rowKeys).And(builder.Eq{"xid": lockDOs[0].Xid})).
- Delete(&lock)
-
- if err != nil {
- log.Errorf(err.Error())
- return false
- }
- return true
- }
-
- func (dao *LockStoreDataBaseDao) UnLockByXIDAndBranchID(xid string, branchID int64) bool {
- _, err := dao.engine.Exec(BatchDeleteLockByBranchID, xid, branchID)
-
- if err != nil {
- log.Errorf(err.Error())
- return false
- }
- return true
- }
-
- func (dao *LockStoreDataBaseDao) UnLockByXIDAndBranchIDs(xid string, branchIDs []int64) bool {
- var lock = model.LockDO{}
- _, err := dao.engine.Table("lock_table").
- Where(builder.In("branch_id", branchIDs).And(builder.Eq{"xid": xid})).
- Delete(&lock)
-
- if err != nil {
- log.Errorf(err.Error())
- return false
- }
- return true
- }
-
- func (dao *LockStoreDataBaseDao) IsLockable(lockDOs []*model.LockDO) bool {
- var existedRowLocks []*model.LockDO
- rowKeys := make([]string, 0)
- for _, lockDO := range lockDOs {
- rowKeys = append(rowKeys, lockDO.RowKey)
- }
- err := dao.engine.Table("lock_table").
- Where(builder.In("row_key", rowKeys)).
- Find(&existedRowLocks)
- if err != nil {
- log.Errorf(err.Error())
- }
- currentXID := lockDOs[0].Xid
- for _, rowLock := range existedRowLocks {
- if rowLock.Xid != currentXID {
- return false
- }
- }
- return true
- }
-
- func (dao *LockStoreDataBaseDao) GetLockCount() int64 {
- var total int64
- dao.engine.SQL(GetLockDOCount).Cols("total").Get(&total)
- return total
- }
|