JCS-pub/common/pkgs/distlock/lockprovider/shard_store.go

130 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package lockprovider
import (
"fmt"
"gitlink.org.cn/cloudream/common/utils/lo2"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types"
)
const (
ShardStoreLockPathPrefix = "ShardStore"
ShardStoreStorageIDPathIndex = 1
ShardStoreBuzyLock = "Buzy"
ShardStoreGCLock = "GC"
)
type ShardStoreLock struct {
stgLocks map[string]*ShardStoreStorageLock
dummyLock *ShardStoreStorageLock
}
func NewShardStoreLock() *ShardStoreLock {
return &ShardStoreLock{
stgLocks: make(map[string]*ShardStoreStorageLock),
dummyLock: NewShardStoreStorageLock(),
}
}
// CanLock 判断这个锁能否锁定成功
func (l *ShardStoreLock) CanLock(lock types.Lock) error {
nodeLock, ok := l.stgLocks[lock.Path[ShardStoreStorageIDPathIndex]]
if !ok {
// 不能直接返回nil因为如果锁数据的格式不对也不能获取锁。
// 这里使用一个空Provider来进行检查。
return l.dummyLock.CanLock(lock)
}
return nodeLock.CanLock(lock)
}
// 锁定。在内部可以不用判断能否加锁外部需要保证调用此函数前调用了CanLock进行检查
func (l *ShardStoreLock) Lock(reqID types.RequestID, lock types.Lock) error {
stgID := lock.Path[ShardStoreStorageIDPathIndex]
nodeLock, ok := l.stgLocks[stgID]
if !ok {
nodeLock = NewShardStoreStorageLock()
l.stgLocks[stgID] = nodeLock
}
return nodeLock.Lock(reqID, lock)
}
// 解锁
func (l *ShardStoreLock) Unlock(reqID types.RequestID, lock types.Lock) error {
stgID := lock.Path[ShardStoreStorageIDPathIndex]
nodeLock, ok := l.stgLocks[stgID]
if !ok {
return nil
}
return nodeLock.Unlock(reqID, lock)
}
// Clear 清除内部所有状态
func (l *ShardStoreLock) Clear() {
l.stgLocks = make(map[string]*ShardStoreStorageLock)
}
type ShardStoreStorageLock struct {
buzyReqIDs []types.RequestID
gcReqIDs []types.RequestID
lockCompatibilityTable *LockCompatibilityTable
}
func NewShardStoreStorageLock() *ShardStoreStorageLock {
compTable := &LockCompatibilityTable{}
sdLock := ShardStoreStorageLock{
lockCompatibilityTable: compTable,
}
compTable.
Column(ShardStoreBuzyLock, func() bool { return len(sdLock.buzyReqIDs) > 0 }).
Column(ShardStoreGCLock, func() bool { return len(sdLock.gcReqIDs) > 0 })
comp := LockCompatible()
uncp := LockUncompatible()
compTable.MustRow(comp, uncp)
compTable.MustRow(uncp, comp)
return &sdLock
}
// CanLock 判断这个锁能否锁定成功
func (l *ShardStoreStorageLock) CanLock(lock types.Lock) error {
return l.lockCompatibilityTable.Test(lock)
}
// 锁定
func (l *ShardStoreStorageLock) Lock(reqID types.RequestID, lock types.Lock) error {
switch lock.Name {
case ShardStoreBuzyLock:
l.buzyReqIDs = append(l.buzyReqIDs, reqID)
case ShardStoreGCLock:
l.gcReqIDs = append(l.gcReqIDs, reqID)
default:
return fmt.Errorf("unknow lock name: %s", lock.Name)
}
return nil
}
// 解锁
func (l *ShardStoreStorageLock) Unlock(reqID types.RequestID, lock types.Lock) error {
switch lock.Name {
case ShardStoreBuzyLock:
l.buzyReqIDs = lo2.Remove(l.buzyReqIDs, reqID)
case ShardStoreGCLock:
l.gcReqIDs = lo2.Remove(l.gcReqIDs, reqID)
default:
return fmt.Errorf("unknow lock name: %s", lock.Name)
}
return nil
}