Browse Source

增加定时清理临时文件的机制

feature_gxh
Sydonian 5 months ago
parent
commit
4a38843585
12 changed files with 123 additions and 146 deletions
  1. +10
    -0
      client/internal/services/object.go
  2. +7
    -29
      client/internal/services/user_space.go
  3. +1
    -1
      client/internal/ticktock/change_redundancy.go
  4. +1
    -1
      client/internal/ticktock/redundancy_shrink.go
  5. +32
    -34
      client/internal/ticktock/shardstore_gc.go
  6. +1
    -1
      client/internal/ticktock/ticktock.go
  7. +3
    -3
      client/internal/uploader/uploader.go
  8. +8
    -17
      client/internal/uploader/user_space_upload.go
  9. +32
    -32
      common/pkgs/distlock/lockprovider/shard_store.go
  10. +18
    -18
      common/pkgs/distlock/lockprovider/shard_store_test.go
  11. +9
    -9
      common/pkgs/distlock/reqbuilder/shard_store.go
  12. +1
    -1
      common/pkgs/distlock/service.go

+ 10
- 0
client/internal/services/object.go View File

@@ -15,6 +15,7 @@ import (
"gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1" "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
"gitlink.org.cn/cloudream/jcs-pub/client/types" "gitlink.org.cn/cloudream/jcs-pub/client/types"
"gitlink.org.cn/cloudream/jcs-pub/common/models/datamap" "gitlink.org.cn/cloudream/jcs-pub/common/models/datamap"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/reqbuilder"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/plans" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/plans"
"gorm.io/gorm" "gorm.io/gorm"
@@ -681,6 +682,8 @@ func (svc *ObjectService) CompleteMultipartUpload(objectID types.ObjectID, index
objBlkMap[blk.Index] = blk objBlkMap[blk.Index] = blk
} }


lockBld := reqbuilder.NewBuilder()

var compBlks []types.ObjectBlock var compBlks []types.ObjectBlock
var compBlkSpaces []types.UserSpaceDetail var compBlkSpaces []types.UserSpaceDetail
var targetSpace types.UserSpaceDetail var targetSpace types.UserSpaceDetail
@@ -700,7 +703,14 @@ func (svc *ObjectService) CompleteMultipartUpload(objectID types.ObjectID, index
if i == 0 { if i == 0 {
targetSpace = *stg targetSpace = *stg
} }
lockBld.UserSpace().Buzy(stg.UserSpace.UserSpaceID)
}

mutex, err := lockBld.MutexLock(svc.PubLock)
if err != nil {
return types.Object{}, fmt.Errorf("acquire lock: %w", err)
} }
defer mutex.Unlock()


bld := exec.NewPlanBuilder() bld := exec.NewPlanBuilder()
err = plans.CompleteMultipart(compBlks, compBlkSpaces, targetSpace, "shard", bld) err = plans.CompleteMultipart(compBlks, compBlkSpaces, targetSpace, "shard", bld)


+ 7
- 29
client/internal/services/user_space.go View File

@@ -90,7 +90,7 @@ func (svc *UserSpaceService) DownloadPackage(packageID clitypes.PackageID, users
} }


mutex, err := reqbuilder.NewBuilder(). mutex, err := reqbuilder.NewBuilder().
Shard().Buzy(userspaceID).
UserSpace().Buzy(userspaceID).
MutexLock(svc.PubLock) MutexLock(svc.PubLock)
if err != nil { if err != nil {
return fmt.Errorf("acquire locks failed, err: %w", err) return fmt.Errorf("acquire locks failed, err: %w", err)
@@ -122,12 +122,6 @@ func (svc *UserSpaceService) SpaceToSpace(srcSpaceID clitypes.UserSpaceID, srcPa
if err != nil { if err != nil {
return clitypes.SpaceToSpaceResult{}, fmt.Errorf("get source userspace store: %w", err) return clitypes.SpaceToSpaceResult{}, fmt.Errorf("get source userspace store: %w", err)
} }
// srcAddr, ok := srcSpace.RecommendHub.Address.(*cortypes.GRPCAddressInfo)
// if !ok {
// return clitypes.SpaceToSpaceResult{}, fmt.Errorf("source userspace %v has no grpc address", srcSpaceID)
// }
// srcSpaceCli := stgglb.HubRPCPool.Get(stgglb.SelectGRPCAddress(&srcSpace.RecommendHub, srcAddr))
// defer srcSpaceCli.Release()


dstSpace := svc.UserSpaceMeta.Get(dstSpaceID) dstSpace := svc.UserSpaceMeta.Get(dstSpaceID)
if dstSpace == nil { if dstSpace == nil {
@@ -138,12 +132,6 @@ func (svc *UserSpaceService) SpaceToSpace(srcSpaceID clitypes.UserSpaceID, srcPa
if err != nil { if err != nil {
return clitypes.SpaceToSpaceResult{}, fmt.Errorf("get destination userspace store: %w", err) return clitypes.SpaceToSpaceResult{}, fmt.Errorf("get destination userspace store: %w", err)
} }
// dstAddr, ok := dstSpace.RecommendHub.Address.(*cortypes.GRPCAddressInfo)
// if !ok {
// return clitypes.SpaceToSpaceResult{}, fmt.Errorf("destination userspace %v has no grpc address", srcSpaceID)
// }
// dstSpaceCli := stgglb.HubRPCPool.Get(stgglb.SelectGRPCAddress(&dstSpace.RecommendHub, dstAddr))
// defer dstSpaceCli.Release()


srcPath = strings.Trim(srcPath, cdssdk.ObjectPathSeparator) srcPath = strings.Trim(srcPath, cdssdk.ObjectPathSeparator)
dstPath = strings.Trim(dstPath, cdssdk.ObjectPathSeparator) dstPath = strings.Trim(dstPath, cdssdk.ObjectPathSeparator)
@@ -208,6 +196,12 @@ func (svc *UserSpaceService) SpaceToSpace(srcSpaceID clitypes.UserSpaceID, srcPa
return trie.VisitContinue return trie.VisitContinue
}) })


mutex, err := reqbuilder.NewBuilder().UserSpace().Buzy(srcSpaceID).Buzy(dstSpaceID).MutexLock(svc.PubLock)
if err != nil {
return clitypes.SpaceToSpaceResult{}, fmt.Errorf("acquire lock: %w", err)
}
defer mutex.Unlock()

var success []string var success []string
var failed []string var failed []string


@@ -243,10 +237,6 @@ func (svc *UserSpaceService) SpaceToSpace(srcSpaceID clitypes.UserSpaceID, srcPa
} }


for _, d := range newDirPathes { for _, d := range newDirPathes {
// mkdirResp, err := dstStore.Mkdir(context.Background(), &hubrpc.BaseStoreMkdirs{
// UserSpace: *dstSpace,
// Pathes: newDirPathes,
// })
err := dstStore.Mkdir(d) err := dstStore.Mkdir(d)
if err != nil { if err != nil {
failed = append(failed, d) failed = append(failed, d)
@@ -254,18 +244,6 @@ func (svc *UserSpaceService) SpaceToSpace(srcSpaceID clitypes.UserSpaceID, srcPa
success = append(success, d) success = append(success, d)
} }
} }
// if err != nil {
// failed = append(failed, dirPathes...)
// logger.Warnf("s2s: mkdirs to destination userspace: %v", err)
// } else {
// for i := range dirPathes {
// if mkdirResp.Successes[i] {
// success = append(success, dirPathes[i])
// } else {
// failed = append(failed, dirPathes[i])
// }
// }
// }


return clitypes.SpaceToSpaceResult{ return clitypes.SpaceToSpaceResult{
Success: success, Success: success,


+ 1
- 1
client/internal/ticktock/change_redundancy.go View File

@@ -143,7 +143,7 @@ func (j *ChangeRedundancy) changeOne(ctx *changeRedundancyContext, pkg clitypes.


reqBlder := reqbuilder.NewBuilder() reqBlder := reqbuilder.NewBuilder()
for _, space := range selectedSpaces { for _, space := range selectedSpaces {
reqBlder.Shard().Buzy(space.UserSpace.UserSpace.UserSpaceID)
reqBlder.UserSpace().Buzy(space.UserSpace.UserSpace.UserSpaceID)
} }
err := reen.Lock(reqBlder.Build()) err := reen.Lock(reqBlder.Build())
if err != nil { if err != nil {


+ 1
- 1
client/internal/ticktock/redundancy_shrink.go View File

@@ -909,7 +909,7 @@ func (t *ChangeRedundancy) generateSysEventForECObject(solu annealingSolution, o
func (t *ChangeRedundancy) executePlans(ctx *changeRedundancyContext, planBld *exec.PlanBuilder, planningSpaceIDs map[clitypes.UserSpaceID]bool, reen *distlock.Reentrant) (map[string]exec.VarValue, error) { func (t *ChangeRedundancy) executePlans(ctx *changeRedundancyContext, planBld *exec.PlanBuilder, planningSpaceIDs map[clitypes.UserSpaceID]bool, reen *distlock.Reentrant) (map[string]exec.VarValue, error) {
reqBlder := reqbuilder.NewBuilder() reqBlder := reqbuilder.NewBuilder()
for id, _ := range planningSpaceIDs { for id, _ := range planningSpaceIDs {
reqBlder.Shard().Buzy(id)
reqBlder.UserSpace().Buzy(id)
} }
err := reen.Lock(reqBlder.Build()) err := reen.Lock(reqBlder.Build())
if err != nil { if err != nil {


+ 32
- 34
client/internal/ticktock/shardstore_gc.go View File

@@ -12,16 +12,16 @@ import (
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/reqbuilder" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/reqbuilder"
) )


type ShardStoreGC struct {
type UserSpaceGC struct {
} }


func (j *ShardStoreGC) Name() string {
return reflect2.TypeNameOf[ShardStoreGC]()
func (j *UserSpaceGC) Name() string {
return reflect2.TypeNameOf[UserSpaceGC]()
} }


// Execute 执行垃圾回收操作。 // Execute 执行垃圾回收操作。
func (j *ShardStoreGC) Execute(t *TickTock) {
log := logger.WithType[ShardStoreGC]("Event")
func (j *UserSpaceGC) Execute(t *TickTock) {
log := logger.WithType[UserSpaceGC]("Event")
startTime := time.Now() startTime := time.Now()
log.Infof("job start") log.Infof("job start")
defer func() { defer func() {
@@ -40,26 +40,35 @@ func (j *ShardStoreGC) Execute(t *TickTock) {
continue continue
} }


err := j.gcOne(t, detail)
if err != nil {
log.Warnf("gc one user space: %v: %v", spaceID, err)
continue
}
j.gcOne(t, detail)
} }
} }


func (j *ShardStoreGC) gcOne(t *TickTock, space *types.UserSpaceDetail) error {
mutex, err := reqbuilder.NewBuilder().Shard().GC(space.UserSpace.UserSpaceID).MutexLock(t.pubLock)
func (j *UserSpaceGC) gcOne(t *TickTock, space *types.UserSpaceDetail) {
log := logger.WithType[UserSpaceGC]("Event")

mutex, err := reqbuilder.NewBuilder().UserSpace().GC(space.UserSpace.UserSpaceID).MutexLock(t.pubLock)
if err != nil { if err != nil {
return fmt.Errorf("acquire lock: %w", err)
log.Warnf("acquire lock: %v", err)
return
} }
defer mutex.Unlock() defer mutex.Unlock()


if err := j.gcShards(t, space); err != nil {
log.Warnf("gc shard store of %v: %v", space.UserSpace.UserSpaceID, err)
}

if err := j.gcTemps(t, space); err != nil {
log.Warnf("gc base store of %v: %v", space.UserSpace.UserSpaceID, err)
}
}

func (j *UserSpaceGC) gcShards(t *TickTock, space *types.UserSpaceDetail) error {
db2 := t.db db2 := t.db


// 收集需要进行垃圾回收的文件哈希值 // 收集需要进行垃圾回收的文件哈希值
var allFileHashes []types.FileHash var allFileHashes []types.FileHash
err = db2.DoTx(func(tx db.SQLContext) error {
err := db2.DoTx(func(tx db.SQLContext) error {
blocks, err := db2.ObjectBlock().GetByUserSpaceID(tx, space.UserSpace.UserSpaceID) blocks, err := db2.ObjectBlock().GetByUserSpaceID(tx, space.UserSpace.UserSpaceID)
if err != nil { if err != nil {
return fmt.Errorf("getting object blocks by hub id: %w", err) return fmt.Errorf("getting object blocks by hub id: %w", err)
@@ -93,25 +102,14 @@ func (j *ShardStoreGC) gcOne(t *TickTock, space *types.UserSpaceDetail) error {
} }


return nil return nil
}


// // 获取与节点通信的代理客户端
// addr, ok := space.RecommendHub.Address.(*cortypes.GRPCAddressInfo)
// if !ok {
// return fmt.Errorf("master of user space %v has no grpc address", space.UserSpace)
// }
// agtCli := stgglb.HubRPCPool.Get(stgglb.SelectGRPCAddress(&space.RecommendHub, addr))
// defer agtCli.Release()

// // 向代理发送垃圾回收请求
// ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
// defer cancel()

// _, cerr := agtCli.CacheGC(ctx, &hubrpc.CacheGC{
// UserSpace: *space,
// Availables: allFileHashes,
// })
// if cerr != nil {
// return fmt.Errorf("request to cache gc: %w", cerr.ToError())
// }
// return nil
func (j *UserSpaceGC) gcTemps(t *TickTock, space *types.UserSpaceDetail) error {
store, err := t.stgPool.GetBaseStore(space)
if err != nil {
return fmt.Errorf("getting base store: %w", err)
}

store.CleanTemps()
return nil
} }

+ 1
- 1
client/internal/ticktock/ticktock.go View File

@@ -97,7 +97,7 @@ func (t *TickTock) initJobs() {
gocron.NewAtTime(1, 0, 0), gocron.NewAtTime(1, 0, 0),
))) )))


t.addJob(&ShardStoreGC{}, gocron.DailyJob(1, gocron.NewAtTimes(
t.addJob(&UserSpaceGC{}, gocron.DailyJob(1, gocron.NewAtTimes(
gocron.NewAtTime(2, 0, 0), gocron.NewAtTime(2, 0, 0),
))) )))




+ 3
- 3
client/internal/uploader/uploader.go View File

@@ -97,7 +97,7 @@ func (u *Uploader) BeginUpdate(pkgID clitypes.PackageID, affinity clitypes.UserS
target := u.chooseUploadStorage(uploadSpaces, affinity) target := u.chooseUploadStorage(uploadSpaces, affinity)


// 防止上传的副本被清除 // 防止上传的副本被清除
pubLock, err := reqbuilder.NewBuilder().Shard().Buzy(target.Space.UserSpace.UserSpaceID).MutexLock(u.pubLock)
pubLock, err := reqbuilder.NewBuilder().UserSpace().Buzy(target.Space.UserSpace.UserSpaceID).MutexLock(u.pubLock)
if err != nil { if err != nil {
return nil, fmt.Errorf("acquire lock: %w", err) return nil, fmt.Errorf("acquire lock: %w", err)
} }
@@ -160,7 +160,7 @@ func (u *Uploader) BeginCreateUpload(bktID clitypes.BucketID, pkgName string, co


reqBld := reqbuilder.NewBuilder() reqBld := reqbuilder.NewBuilder()
for _, stg := range spacesStgs { for _, stg := range spacesStgs {
reqBld.Shard().Buzy(stg.UserSpace.UserSpaceID)
reqBld.UserSpace().Buzy(stg.UserSpace.UserSpaceID)
} }
lock, err := reqBld.MutexLock(u.pubLock) lock, err := reqBld.MutexLock(u.pubLock)
if err != nil { if err != nil {
@@ -242,7 +242,7 @@ func (u *Uploader) UploadPart(objID clitypes.ObjectID, index int, stream io.Read
space = u.chooseUploadStorage(userStgs, 0).Space space = u.chooseUploadStorage(userStgs, 0).Space
} }


lock, err := reqbuilder.NewBuilder().Shard().Buzy(space.UserSpace.UserSpaceID).MutexLock(u.pubLock)
lock, err := reqbuilder.NewBuilder().UserSpace().Buzy(space.UserSpace.UserSpaceID).MutexLock(u.pubLock)
if err != nil { if err != nil {
return fmt.Errorf("acquire lock: %w", err) return fmt.Errorf("acquire lock: %w", err)
} }


+ 8
- 17
client/internal/uploader/user_space_upload.go View File

@@ -12,6 +12,7 @@ import (
"gitlink.org.cn/cloudream/jcs-pub/client/internal/db" "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
stgglb "gitlink.org.cn/cloudream/jcs-pub/common/globals" stgglb "gitlink.org.cn/cloudream/jcs-pub/common/globals"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/reqbuilder"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser"
@@ -98,23 +99,6 @@ func (u *Uploader) UserSpaceUpload(userSpaceID clitypes.UserSpaceID, rootPath st


targetSapce := u.chooseUploadStorage(uploadSpaces, uploadAffinity) targetSapce := u.chooseUploadStorage(uploadSpaces, uploadAffinity)


// addr, ok := srcSpace.RecommendHub.Address.(*cortypes.GRPCAddressInfo)
// if !ok {
// delPkg()
// return nil, fmt.Errorf("master of user space %v has no grpc address", srcSpace.UserSpace)
// }
// srcHubCli := stgglb.HubRPCPool.Get(stgglb.SelectGRPCAddress(&srcSpace.RecommendHub, addr))
// defer srcHubCli.Release()

// listAllResp, cerr := srcHubCli.BaseStoreListAll(context.Background(), &hubrpc.BaseStoreListAll{
// UserSpace: *srcSpace,
// Path: rootPath,
// })
// if cerr != nil {
// delPkg()
// return nil, fmt.Errorf("listing base store: %w", cerr.ToError())
// }

store, err := u.stgPool.GetBaseStore(srcSpace) store, err := u.stgPool.GetBaseStore(srcSpace)
if err != nil { if err != nil {
delPkg() delPkg()
@@ -126,6 +110,13 @@ func (u *Uploader) UserSpaceUpload(userSpaceID clitypes.UserSpaceID, rootPath st
return nil, fmt.Errorf("listing base store: %w", err) return nil, fmt.Errorf("listing base store: %w", err)
} }


mutex, err := reqbuilder.NewBuilder().UserSpace().Buzy(srcSpace.UserSpace.UserSpaceID).Buzy(targetSapce.Space.UserSpace.UserSpaceID).MutexLock(u.pubLock)
if err != nil {
delPkg()
return nil, fmt.Errorf("acquire lock: %w", err)
}
defer mutex.Unlock()

adds, err := u.uploadFromBaseStore(srcSpace, &targetSapce.Space, entries, rootPath) adds, err := u.uploadFromBaseStore(srcSpace, &targetSapce.Space, entries, rootPath)
if err != nil { if err != nil {
delPkg() delPkg()


+ 32
- 32
common/pkgs/distlock/lockprovider/shard_store.go View File

@@ -8,27 +8,27 @@ import (
) )


const ( const (
ShardStoreLockPathPrefix = "ShardStore"
ShardStoreStorageIDPathIndex = 1
ShardStoreBuzyLock = "Buzy"
ShardStoreGCLock = "GC"
UserSpaceLockPathPrefix = "UserSpace"
UserSpaceStorageIDPathIndex = 1
UserSpaceBuzyLock = "Buzy"
UserSpaceGCLock = "GC"
) )


type ShardStoreLock struct {
stgLocks map[string]*ShardStoreStorageLock
dummyLock *ShardStoreStorageLock
type UserSpaceLock struct {
stgLocks map[string]*UserSpaceStorageLock
dummyLock *UserSpaceStorageLock
} }


func NewShardStoreLock() *ShardStoreLock {
return &ShardStoreLock{
stgLocks: make(map[string]*ShardStoreStorageLock),
dummyLock: NewShardStoreStorageLock(),
func NewUserSpaceLock() *UserSpaceLock {
return &UserSpaceLock{
stgLocks: make(map[string]*UserSpaceStorageLock),
dummyLock: NewUserSpaceStorageLock(),
} }
} }


// CanLock 判断这个锁能否锁定成功 // CanLock 判断这个锁能否锁定成功
func (l *ShardStoreLock) CanLock(lock types.Lock) error {
nodeLock, ok := l.stgLocks[lock.Path[ShardStoreStorageIDPathIndex]]
func (l *UserSpaceLock) CanLock(lock types.Lock) error {
nodeLock, ok := l.stgLocks[lock.Path[UserSpaceStorageIDPathIndex]]
if !ok { if !ok {
// 不能直接返回nil,因为如果锁数据的格式不对,也不能获取锁。 // 不能直接返回nil,因为如果锁数据的格式不对,也不能获取锁。
// 这里使用一个空Provider来进行检查。 // 这里使用一个空Provider来进行检查。
@@ -39,12 +39,12 @@ func (l *ShardStoreLock) CanLock(lock types.Lock) error {
} }


// 锁定。在内部可以不用判断能否加锁,外部需要保证调用此函数前调用了CanLock进行检查 // 锁定。在内部可以不用判断能否加锁,外部需要保证调用此函数前调用了CanLock进行检查
func (l *ShardStoreLock) Lock(reqID types.RequestID, lock types.Lock) error {
stgID := lock.Path[ShardStoreStorageIDPathIndex]
func (l *UserSpaceLock) Lock(reqID types.RequestID, lock types.Lock) error {
stgID := lock.Path[UserSpaceStorageIDPathIndex]


nodeLock, ok := l.stgLocks[stgID] nodeLock, ok := l.stgLocks[stgID]
if !ok { if !ok {
nodeLock = NewShardStoreStorageLock()
nodeLock = NewUserSpaceStorageLock()
l.stgLocks[stgID] = nodeLock l.stgLocks[stgID] = nodeLock
} }


@@ -52,8 +52,8 @@ func (l *ShardStoreLock) Lock(reqID types.RequestID, lock types.Lock) error {
} }


// 解锁 // 解锁
func (l *ShardStoreLock) Unlock(reqID types.RequestID, lock types.Lock) error {
stgID := lock.Path[ShardStoreStorageIDPathIndex]
func (l *UserSpaceLock) Unlock(reqID types.RequestID, lock types.Lock) error {
stgID := lock.Path[UserSpaceStorageIDPathIndex]


nodeLock, ok := l.stgLocks[stgID] nodeLock, ok := l.stgLocks[stgID]
if !ok { if !ok {
@@ -64,27 +64,27 @@ func (l *ShardStoreLock) Unlock(reqID types.RequestID, lock types.Lock) error {
} }


// Clear 清除内部所有状态 // Clear 清除内部所有状态
func (l *ShardStoreLock) Clear() {
l.stgLocks = make(map[string]*ShardStoreStorageLock)
func (l *UserSpaceLock) Clear() {
l.stgLocks = make(map[string]*UserSpaceStorageLock)
} }


type ShardStoreStorageLock struct {
type UserSpaceStorageLock struct {
buzyReqIDs []types.RequestID buzyReqIDs []types.RequestID
gcReqIDs []types.RequestID gcReqIDs []types.RequestID


lockCompatibilityTable *LockCompatibilityTable lockCompatibilityTable *LockCompatibilityTable
} }


func NewShardStoreStorageLock() *ShardStoreStorageLock {
func NewUserSpaceStorageLock() *UserSpaceStorageLock {
compTable := &LockCompatibilityTable{} compTable := &LockCompatibilityTable{}


sdLock := ShardStoreStorageLock{
sdLock := UserSpaceStorageLock{
lockCompatibilityTable: compTable, lockCompatibilityTable: compTable,
} }


compTable. compTable.
Column(ShardStoreBuzyLock, func() bool { return len(sdLock.buzyReqIDs) > 0 }).
Column(ShardStoreGCLock, func() bool { return len(sdLock.gcReqIDs) > 0 })
Column(UserSpaceBuzyLock, func() bool { return len(sdLock.buzyReqIDs) > 0 }).
Column(UserSpaceGCLock, func() bool { return len(sdLock.gcReqIDs) > 0 })


comp := LockCompatible() comp := LockCompatible()
uncp := LockUncompatible() uncp := LockUncompatible()
@@ -96,16 +96,16 @@ func NewShardStoreStorageLock() *ShardStoreStorageLock {
} }


// CanLock 判断这个锁能否锁定成功 // CanLock 判断这个锁能否锁定成功
func (l *ShardStoreStorageLock) CanLock(lock types.Lock) error {
func (l *UserSpaceStorageLock) CanLock(lock types.Lock) error {
return l.lockCompatibilityTable.Test(lock) return l.lockCompatibilityTable.Test(lock)
} }


// 锁定 // 锁定
func (l *ShardStoreStorageLock) Lock(reqID types.RequestID, lock types.Lock) error {
func (l *UserSpaceStorageLock) Lock(reqID types.RequestID, lock types.Lock) error {
switch lock.Name { switch lock.Name {
case ShardStoreBuzyLock:
case UserSpaceBuzyLock:
l.buzyReqIDs = append(l.buzyReqIDs, reqID) l.buzyReqIDs = append(l.buzyReqIDs, reqID)
case ShardStoreGCLock:
case UserSpaceGCLock:
l.gcReqIDs = append(l.gcReqIDs, reqID) l.gcReqIDs = append(l.gcReqIDs, reqID)
default: default:
return fmt.Errorf("unknow lock name: %s", lock.Name) return fmt.Errorf("unknow lock name: %s", lock.Name)
@@ -115,11 +115,11 @@ func (l *ShardStoreStorageLock) Lock(reqID types.RequestID, lock types.Lock) err
} }


// 解锁 // 解锁
func (l *ShardStoreStorageLock) Unlock(reqID types.RequestID, lock types.Lock) error {
func (l *UserSpaceStorageLock) Unlock(reqID types.RequestID, lock types.Lock) error {
switch lock.Name { switch lock.Name {
case ShardStoreBuzyLock:
case UserSpaceBuzyLock:
l.buzyReqIDs = lo2.Remove(l.buzyReqIDs, reqID) l.buzyReqIDs = lo2.Remove(l.buzyReqIDs, reqID)
case ShardStoreGCLock:
case UserSpaceGCLock:
l.gcReqIDs = lo2.Remove(l.gcReqIDs, reqID) l.gcReqIDs = lo2.Remove(l.gcReqIDs, reqID)
default: default:
return fmt.Errorf("unknow lock name: %s", lock.Name) return fmt.Errorf("unknow lock name: %s", lock.Name)


+ 18
- 18
common/pkgs/distlock/lockprovider/shard_store_test.go View File

@@ -18,13 +18,13 @@ func Test_ShardStoreLock(t *testing.T) {
title: "同节点,同一个Buzy锁", title: "同节点,同一个Buzy锁",
initLocks: []types.Lock{ initLocks: []types.Lock{
{ {
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreBuzyLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceBuzyLock,
}, },
}, },
doLock: types.Lock{ doLock: types.Lock{
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreBuzyLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceBuzyLock,
}, },
wantOK: true, wantOK: true,
}, },
@@ -32,13 +32,13 @@ func Test_ShardStoreLock(t *testing.T) {
title: "同节点,同一个GC锁", title: "同节点,同一个GC锁",
initLocks: []types.Lock{ initLocks: []types.Lock{
{ {
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreGCLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceGCLock,
}, },
}, },
doLock: types.Lock{ doLock: types.Lock{
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreGCLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceGCLock,
}, },
wantOK: true, wantOK: true,
}, },
@@ -46,14 +46,14 @@ func Test_ShardStoreLock(t *testing.T) {
title: "同时设置Buzy和GC", title: "同时设置Buzy和GC",
initLocks: []types.Lock{ initLocks: []types.Lock{
{ {
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreBuzyLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceBuzyLock,
Target: NewStringLockTarget(), Target: NewStringLockTarget(),
}, },
}, },
doLock: types.Lock{ doLock: types.Lock{
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreGCLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceGCLock,
Target: NewStringLockTarget(), Target: NewStringLockTarget(),
}, },
wantOK: false, wantOK: false,
@@ -62,7 +62,7 @@ func Test_ShardStoreLock(t *testing.T) {


for _, ca := range cases { for _, ca := range cases {
Convey(ca.title, t, func() { Convey(ca.title, t, func() {
ipfsLock := NewShardStoreLock()
ipfsLock := NewUserSpaceLock()


for _, l := range ca.initLocks { for _, l := range ca.initLocks {
ipfsLock.Lock("req1", l) ipfsLock.Lock("req1", l)
@@ -78,11 +78,11 @@ func Test_ShardStoreLock(t *testing.T) {
} }


Convey("解锁", t, func() { Convey("解锁", t, func() {
ipfsLock := NewShardStoreLock()
ipfsLock := NewUserSpaceLock()


lock := types.Lock{ lock := types.Lock{
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreBuzyLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceBuzyLock,
} }


ipfsLock.Lock("req1", lock) ipfsLock.Lock("req1", lock)
@@ -93,8 +93,8 @@ func Test_ShardStoreLock(t *testing.T) {
ipfsLock.Unlock("req1", lock) ipfsLock.Unlock("req1", lock)


lock = types.Lock{ lock = types.Lock{
Path: []string{ShardStoreLockPathPrefix, "hub1"},
Name: ShardStoreGCLock,
Path: []string{UserSpaceLockPathPrefix, "hub1"},
Name: UserSpaceGCLock,
} }
err = ipfsLock.CanLock(lock) err = ipfsLock.CanLock(lock)
So(err, ShouldBeNil) So(err, ShouldBeNil)


+ 9
- 9
common/pkgs/distlock/reqbuilder/shard_store.go View File

@@ -8,31 +8,31 @@ import (
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types"
) )


type ShardStoreLockReqBuilder struct {
type UserSpaceLockReqBuilder struct {
*LockRequestBuilder *LockRequestBuilder
} }


func (b *LockRequestBuilder) Shard() *ShardStoreLockReqBuilder {
return &ShardStoreLockReqBuilder{LockRequestBuilder: b}
func (b *LockRequestBuilder) UserSpace() *UserSpaceLockReqBuilder {
return &UserSpaceLockReqBuilder{LockRequestBuilder: b}
} }
func (b *ShardStoreLockReqBuilder) Buzy(spaceID clitypes.UserSpaceID) *ShardStoreLockReqBuilder {
func (b *UserSpaceLockReqBuilder) Buzy(spaceID clitypes.UserSpaceID) *UserSpaceLockReqBuilder {
b.locks = append(b.locks, types.Lock{ b.locks = append(b.locks, types.Lock{
Path: b.makePath(spaceID), Path: b.makePath(spaceID),
Name: lockprovider.ShardStoreBuzyLock,
Name: lockprovider.UserSpaceBuzyLock,
Target: lockprovider.NewEmptyTarget(), Target: lockprovider.NewEmptyTarget(),
}) })
return b return b
} }


func (b *ShardStoreLockReqBuilder) GC(spaceID clitypes.UserSpaceID) *ShardStoreLockReqBuilder {
func (b *UserSpaceLockReqBuilder) GC(spaceID clitypes.UserSpaceID) *UserSpaceLockReqBuilder {
b.locks = append(b.locks, types.Lock{ b.locks = append(b.locks, types.Lock{
Path: b.makePath(spaceID), Path: b.makePath(spaceID),
Name: lockprovider.ShardStoreGCLock,
Name: lockprovider.UserSpaceGCLock,
Target: lockprovider.NewEmptyTarget(), Target: lockprovider.NewEmptyTarget(),
}) })
return b return b
} }


func (b *ShardStoreLockReqBuilder) makePath(hubID clitypes.UserSpaceID) []string {
return []string{lockprovider.ShardStoreLockPathPrefix, strconv.FormatInt(int64(hubID), 10)}
func (b *UserSpaceLockReqBuilder) makePath(hubID clitypes.UserSpaceID) []string {
return []string{lockprovider.UserSpaceLockPathPrefix, strconv.FormatInt(int64(hubID), 10)}
} }

+ 1
- 1
common/pkgs/distlock/service.go View File

@@ -38,7 +38,7 @@ func NewService() *Service {
provdersTrie: trie.NewTrie[types.LockProvider](), provdersTrie: trie.NewTrie[types.LockProvider](),
} }


svc.provdersTrie.Create([]any{lockprovider.ShardStoreLockPathPrefix, trie.WORD_ANY}).Value = lockprovider.NewShardStoreLock()
svc.provdersTrie.Create([]any{lockprovider.UserSpaceLockPathPrefix, trie.WORD_ANY}).Value = lockprovider.NewUserSpaceLock()
return svc return svc
} }




Loading…
Cancel
Save