| @@ -98,13 +98,8 @@ func serveHTTP(configPath string, opts serveHTTPOptions) { | |||||
| hubMeta := metaCacheHost.AddHubMeta() | hubMeta := metaCacheHost.AddHubMeta() | ||||
| conMeta := metaCacheHost.AddConnectivity() | conMeta := metaCacheHost.AddConnectivity() | ||||
| // 分布式锁 | |||||
| distlockSvc, err := distlock.NewService(&config.Cfg().DistLock) | |||||
| if err != nil { | |||||
| logger.Warnf("new distlock service failed, err: %s", err.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| go serveDistLock(distlockSvc) | |||||
| // 公共锁 | |||||
| publock := distlock.NewService() | |||||
| // 访问统计 | // 访问统计 | ||||
| acStat := accessstat.NewAccessStat(accessstat.Config{ | acStat := accessstat.NewAccessStat(accessstat.Config{ | ||||
| @@ -124,10 +119,10 @@ func serveHTTP(configPath string, opts serveHTTPOptions) { | |||||
| dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol, stgPool, strgSel, db) | dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol, stgPool, strgSel, db) | ||||
| // 上传器 | // 上传器 | ||||
| uploader := uploader.NewUploader(distlockSvc, &conCol, stgPool, stgMeta, db) | |||||
| uploader := uploader.NewUploader(publock, &conCol, stgPool, stgMeta, db) | |||||
| // 定时任务 | // 定时任务 | ||||
| tktk := ticktock.New(config.Cfg().TickTock, db, stgMeta, stgPool, evtPub) | |||||
| tktk := ticktock.New(config.Cfg().TickTock, db, stgMeta, stgPool, evtPub, publock) | |||||
| tktk.Start() | tktk.Start() | ||||
| defer tktk.Stop() | defer tktk.Stop() | ||||
| @@ -148,7 +143,7 @@ func serveHTTP(configPath string, opts serveHTTPOptions) { | |||||
| mntChan := mnt.Start() | mntChan := mnt.Start() | ||||
| defer mnt.Stop() | defer mnt.Stop() | ||||
| svc := services.NewService(distlockSvc, dlder, acStat, uploader, strgSel, stgMeta, db, evtPub, mnt) | |||||
| svc := services.NewService(publock, dlder, acStat, uploader, strgSel, stgMeta, db, evtPub, mnt) | |||||
| // HTTP接口 | // HTTP接口 | ||||
| httpCfg := config.Cfg().HTTP | httpCfg := config.Cfg().HTTP | ||||
| @@ -250,18 +245,3 @@ loop: | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| func serveDistLock(svc *distlock.Service) { | |||||
| logger.Info("start serving distlock") | |||||
| err := svc.Serve() | |||||
| if err != nil { | |||||
| logger.Errorf("distlock stopped with error: %s", err.Error()) | |||||
| } | |||||
| logger.Info("distlock stopped") | |||||
| // TODO 仅简单结束了程序 | |||||
| os.Exit(1) | |||||
| } | |||||
| @@ -91,13 +91,8 @@ func vfsTest(configPath string, opts serveHTTPOptions) { | |||||
| hubMeta := metaCacheHost.AddHubMeta() | hubMeta := metaCacheHost.AddHubMeta() | ||||
| conMeta := metaCacheHost.AddConnectivity() | conMeta := metaCacheHost.AddConnectivity() | ||||
| // 分布式锁 | |||||
| distlockSvc, err := distlock.NewService(&config.Cfg().DistLock) | |||||
| if err != nil { | |||||
| logger.Warnf("new distlock service failed, err: %s", err.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| go serveDistLock(distlockSvc) | |||||
| // 公共锁 | |||||
| publock := distlock.NewService() | |||||
| // 访问统计 | // 访问统计 | ||||
| acStat := accessstat.NewAccessStat(accessstat.Config{ | acStat := accessstat.NewAccessStat(accessstat.Config{ | ||||
| @@ -117,7 +112,7 @@ func vfsTest(configPath string, opts serveHTTPOptions) { | |||||
| dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol, stgPool, strgSel, db) | dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol, stgPool, strgSel, db) | ||||
| // 上传器 | // 上传器 | ||||
| uploader := uploader.NewUploader(distlockSvc, &conCol, stgPool, stgMeta, db) | |||||
| uploader := uploader.NewUploader(publock, &conCol, stgPool, stgMeta, db) | |||||
| // 挂载 | // 挂载 | ||||
| mntCfg := config.Cfg().Mount | mntCfg := config.Cfg().Mount | ||||
| @@ -132,7 +127,7 @@ func vfsTest(configPath string, opts serveHTTPOptions) { | |||||
| mntChan := mnt.Start() | mntChan := mnt.Start() | ||||
| defer mnt.Stop() | defer mnt.Stop() | ||||
| svc := services.NewService(distlockSvc, dlder, acStat, uploader, strgSel, stgMeta, db, evtPub, mnt) | |||||
| svc := services.NewService(publock, dlder, acStat, uploader, strgSel, stgMeta, db, evtPub, mnt) | |||||
| // HTTP接口 | // HTTP接口 | ||||
| httpCfg := config.Cfg().HTTP | httpCfg := config.Cfg().HTTP | ||||
| @@ -1,7 +1,6 @@ | |||||
| package config | package config | ||||
| import ( | import ( | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/logger" | "gitlink.org.cn/cloudream/common/pkgs/logger" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/mq" | "gitlink.org.cn/cloudream/common/pkgs/mq" | ||||
| "gitlink.org.cn/cloudream/common/utils/config" | "gitlink.org.cn/cloudream/common/utils/config" | ||||
| @@ -22,7 +21,6 @@ type Config struct { | |||||
| Logger logger.Config `json:"logger"` | Logger logger.Config `json:"logger"` | ||||
| DB db.Config `json:"db"` | DB db.Config `json:"db"` | ||||
| RabbitMQ mq.Config `json:"rabbitMQ"` | RabbitMQ mq.Config `json:"rabbitMQ"` | ||||
| DistLock distlock.Config `json:"distlock"` | |||||
| Connectivity connectivity.Config `json:"connectivity"` | Connectivity connectivity.Config `json:"connectivity"` | ||||
| Downloader downloader.Config `json:"downloader"` | Downloader downloader.Config `json:"downloader"` | ||||
| DownloadStrategy strategy.Config `json:"downloadStrategy"` | DownloadStrategy strategy.Config `json:"downloadStrategy"` | ||||
| @@ -29,7 +29,7 @@ type downloadSpaceInfo struct { | |||||
| } | } | ||||
| type DownloadContext struct { | type DownloadContext struct { | ||||
| Distlock *distlock.Service | |||||
| PubLock *distlock.Service | |||||
| } | } | ||||
| type DownloadObjectIterator struct { | type DownloadObjectIterator struct { | ||||
| OnClosing func() | OnClosing func() | ||||
| @@ -1,7 +1,6 @@ | |||||
| package services | package services | ||||
| import ( | import ( | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/accessstat" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/accessstat" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader" | ||||
| @@ -9,12 +8,13 @@ import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/metacache" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/metacache" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/mount" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/mount" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/uploader" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/uploader" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/sysevent" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/sysevent" | ||||
| ) | ) | ||||
| // Service 结构体封装了分布锁服务和任务管理服务。 | // Service 结构体封装了分布锁服务和任务管理服务。 | ||||
| type Service struct { | type Service struct { | ||||
| DistLock *distlock.Service | |||||
| PubLock *distlock.Service | |||||
| Downloader *downloader.Downloader | Downloader *downloader.Downloader | ||||
| AccessStat *accessstat.AccessStat | AccessStat *accessstat.AccessStat | ||||
| Uploader *uploader.Uploader | Uploader *uploader.Uploader | ||||
| @@ -26,7 +26,7 @@ type Service struct { | |||||
| } | } | ||||
| func NewService( | func NewService( | ||||
| distlock *distlock.Service, | |||||
| publock *distlock.Service, | |||||
| downloader *downloader.Downloader, | downloader *downloader.Downloader, | ||||
| accStat *accessstat.AccessStat, | accStat *accessstat.AccessStat, | ||||
| uploder *uploader.Uploader, | uploder *uploader.Uploader, | ||||
| @@ -37,7 +37,7 @@ func NewService( | |||||
| mount *mount.Mount, | mount *mount.Mount, | ||||
| ) *Service { | ) *Service { | ||||
| return &Service{ | return &Service{ | ||||
| DistLock: distlock, | |||||
| PubLock: publock, | |||||
| Downloader: downloader, | Downloader: downloader, | ||||
| AccessStat: accStat, | AccessStat: accStat, | ||||
| Uploader: uploder, | Uploader: uploder, | ||||
| @@ -15,6 +15,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader/strategy" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader/strategy" | ||||
| 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/parser" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser" | ||||
| hubmq "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/mq/hub" | hubmq "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/mq/hub" | ||||
| @@ -95,17 +96,13 @@ func (svc *UserSpaceService) LoadPackage(packageID clitypes.PackageID, userspace | |||||
| } | } | ||||
| } | } | ||||
| // TODO2 加锁 | |||||
| // mutex, err := reqbuilder.NewBuilder(). | |||||
| // // 保护在userspace目录中下载的文件 | |||||
| // UserSpace().Buzy(userspaceID). | |||||
| // // 保护下载文件时同时保存到IPFS的文件 | |||||
| // Shard().Buzy(userspaceID). | |||||
| // MutexLock(svc.DistLock) | |||||
| // if err != nil { | |||||
| // return fmt.Errorf("acquire locks failed, err: %w", err) | |||||
| // } | |||||
| // defer mutex.Unlock() | |||||
| mutex, err := reqbuilder.NewBuilder(). | |||||
| Shard().Buzy(userspaceID). | |||||
| MutexLock(svc.PubLock) | |||||
| if err != nil { | |||||
| return fmt.Errorf("acquire locks failed, err: %w", err) | |||||
| } | |||||
| defer mutex.Unlock() | |||||
| // 记录访问统计 | // 记录访问统计 | ||||
| for _, obj := range details { | for _, obj := range details { | ||||
| @@ -9,6 +9,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" | ||||
| "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" | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| @@ -119,37 +120,34 @@ func (j *ChangeRedundancy) changeOne(ctx *changeRedundancyContext, pkg clitypes. | |||||
| } | } | ||||
| lastObjID = objs[len(objs)-1].Object.ObjectID | lastObjID = objs[len(objs)-1].Object.ObjectID | ||||
| reen := ctx.ticktock.pubLock.BeginReentrant() | |||||
| var allUpdatings []db.UpdatingObjectRedundancy | var allUpdatings []db.UpdatingObjectRedundancy | ||||
| var allSysEvts []datamap.SysEventBody | var allSysEvts []datamap.SysEventBody | ||||
| ctx.mostBlockStgIDs = j.summaryRepObjectBlockUserSpaces(ctx, objs, 2) | ctx.mostBlockStgIDs = j.summaryRepObjectBlockUserSpaces(ctx, objs, 2) | ||||
| // // TODO 加锁 | |||||
| // builder := reqbuilder.NewBuilder() | |||||
| // for _, storage := range newRepStgs { | |||||
| // builder.Shard().Buzy(storage.Storage.Storage.StorageID) | |||||
| // } | |||||
| // for _, storage := range newECStgs { | |||||
| // builder.Shard().Buzy(storage.Storage.Storage.StorageID) | |||||
| // } | |||||
| // mutex, err := builder.MutexLock(execCtx.Args.DistLock) | |||||
| // if err != nil { | |||||
| // log.Warnf("acquiring dist lock: %s", err.Error()) | |||||
| // return | |||||
| // } | |||||
| // defer mutex.Unlock() | |||||
| var willShrinks []clitypes.ObjectDetail | var willShrinks []clitypes.ObjectDetail | ||||
| for _, obj := range objs { | for _, obj := range objs { | ||||
| newRed, selectedStorages := j.chooseRedundancy(ctx, obj) | |||||
| newRed, selectedSpaces := j.chooseRedundancy(ctx, obj) | |||||
| // 冗余策略不需要调整,就检查是否需要收缩 | // 冗余策略不需要调整,就检查是否需要收缩 | ||||
| if newRed == nil { | if newRed == nil { | ||||
| willShrinks = append(willShrinks, obj) | willShrinks = append(willShrinks, obj) | ||||
| continue | continue | ||||
| } | } | ||||
| updating, evt, err := j.doChangeRedundancy(ctx, obj, newRed, selectedStorages) | |||||
| reqBlder := reqbuilder.NewBuilder() | |||||
| for _, space := range selectedSpaces { | |||||
| reqBlder.Shard().Buzy(space.UserSpace.UserSpace.UserSpaceID) | |||||
| } | |||||
| err := reen.Lock(reqBlder.Build()) | |||||
| if err != nil { | |||||
| log.WithField("ObjectID", obj.Object.ObjectID).Warnf("acquire lock: %s", err.Error()) | |||||
| continue | |||||
| } | |||||
| updating, evt, err := j.doChangeRedundancy(ctx, obj, newRed, selectedSpaces) | |||||
| if updating != nil { | if updating != nil { | ||||
| allUpdatings = append(allUpdatings, *updating) | allUpdatings = append(allUpdatings, *updating) | ||||
| } | } | ||||
| @@ -158,24 +156,27 @@ func (j *ChangeRedundancy) changeOne(ctx *changeRedundancyContext, pkg clitypes. | |||||
| } | } | ||||
| if err != nil { | if err != nil { | ||||
| log.WithField("ObjectID", obj.Object.ObjectID).Warnf("%s, its redundancy wont be changed", err.Error()) | log.WithField("ObjectID", obj.Object.ObjectID).Warnf("%s, its redundancy wont be changed", err.Error()) | ||||
| continue | |||||
| } | } | ||||
| } | } | ||||
| udpatings, sysEvts, err := j.doRedundancyShrink(ctx, pkg, willShrinks) | |||||
| udpatings, sysEvts, err := j.doRedundancyShrink(ctx, pkg, willShrinks, reen) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("redundancy shrink: %s", err.Error()) | log.Warnf("redundancy shrink: %s", err.Error()) | ||||
| return err | |||||
| } else { | |||||
| allUpdatings = append(allUpdatings, udpatings...) | |||||
| allSysEvts = append(allSysEvts, sysEvts...) | |||||
| } | } | ||||
| allUpdatings = append(allUpdatings, udpatings...) | |||||
| allSysEvts = append(allSysEvts, sysEvts...) | |||||
| if len(allUpdatings) > 0 { | if len(allUpdatings) > 0 { | ||||
| err := db.DoTx10(db2, db2.Object().BatchUpdateRedundancy, allUpdatings) | err := db.DoTx10(db2, db2.Object().BatchUpdateRedundancy, allUpdatings) | ||||
| if err != nil { | if err != nil { | ||||
| reen.Unlock() | |||||
| log.Warnf("update object redundancy: %s", err.Error()) | log.Warnf("update object redundancy: %s", err.Error()) | ||||
| return err | return err | ||||
| } | } | ||||
| } | } | ||||
| reen.Unlock() | |||||
| for _, e := range allSysEvts { | for _, e := range allSysEvts { | ||||
| ctx.ticktock.evtPub.Publish(e) | ctx.ticktock.evtPub.Publish(e) | ||||
| @@ -18,12 +18,14 @@ import ( | |||||
| clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/consts" | "gitlink.org.cn/cloudream/jcs-pub/common/consts" | ||||
| "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" | |||||
| "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" | ||||
| ) | ) | ||||
| func (t *ChangeRedundancy) doRedundancyShrink(execCtx *changeRedundancyContext, pkg clitypes.PackageDetail, objs []clitypes.ObjectDetail) ([]db.UpdatingObjectRedundancy, []datamap.SysEventBody, error) { | |||||
| func (t *ChangeRedundancy) doRedundancyShrink(execCtx *changeRedundancyContext, pkg clitypes.PackageDetail, objs []clitypes.ObjectDetail, reen *distlock.Reentrant) ([]db.UpdatingObjectRedundancy, []datamap.SysEventBody, error) { | |||||
| log := logger.WithType[ChangeRedundancy]("TickTock") | log := logger.WithType[ChangeRedundancy]("TickTock") | ||||
| var readerStgIDs []clitypes.UserSpaceID | var readerStgIDs []clitypes.UserSpaceID | ||||
| @@ -78,7 +80,7 @@ func (t *ChangeRedundancy) doRedundancyShrink(execCtx *changeRedundancyContext, | |||||
| sysEvents = append(sysEvents, t.generateSysEventForECObject(solu, obj)...) | sysEvents = append(sysEvents, t.generateSysEventForECObject(solu, obj)...) | ||||
| } | } | ||||
| ioSwRets, err := t.executePlans(execCtx, planBld, planningStgIDs) | |||||
| ioSwRets, err := t.executePlans(execCtx, planBld, planningStgIDs, reen) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warn(err.Error()) | log.Warn(err.Error()) | ||||
| return nil, nil, fmt.Errorf("execute plans: %w", err) | return nil, nil, fmt.Errorf("execute plans: %w", err) | ||||
| @@ -904,17 +906,15 @@ func (t *ChangeRedundancy) generateSysEventForECObject(solu annealingSolution, o | |||||
| return []datamap.SysEventBody{transEvt, distEvt} | return []datamap.SysEventBody{transEvt, distEvt} | ||||
| } | } | ||||
| func (t *ChangeRedundancy) executePlans(ctx *changeRedundancyContext, planBld *exec.PlanBuilder, planningStgIDs map[clitypes.UserSpaceID]bool) (map[string]exec.VarValue, error) { | |||||
| // TODO 统一加锁,有重复也没关系 | |||||
| // lockBld := reqbuilder.NewBuilder() | |||||
| // for id := range planningStgIDs { | |||||
| // lockBld.Shard().Buzy(id) | |||||
| // } | |||||
| // lock, err := lockBld.MutexLock(ctx.Args.DistLock) | |||||
| // if err != nil { | |||||
| // return nil, fmt.Errorf("acquiring distlock: %w", err) | |||||
| // } | |||||
| // defer lock.Unlock() | |||||
| 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() | |||||
| for id, _ := range planningSpaceIDs { | |||||
| reqBlder.Shard().Buzy(id) | |||||
| } | |||||
| err := reen.Lock(reqBlder.Build()) | |||||
| if err != nil { | |||||
| return nil, fmt.Errorf("locking shard resources: %w", err) | |||||
| } | |||||
| wg := sync.WaitGroup{} | wg := sync.WaitGroup{} | ||||
| @@ -11,6 +11,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/types" | "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" | |||||
| hubmq "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/mq/hub" | hubmq "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/mq/hub" | ||||
| ) | ) | ||||
| @@ -30,18 +31,6 @@ func (j *ShardStoreGC) Execute(t *TickTock) { | |||||
| log.Debugf("job end, time: %v", time.Since(startTime)) | log.Debugf("job end, time: %v", time.Since(startTime)) | ||||
| }() | }() | ||||
| // TODO 加锁 | |||||
| // // 使用分布式锁进行资源锁定 | |||||
| // mutex, err := reqbuilder.NewBuilder(). | |||||
| // // 执行IPFS垃圾回收 | |||||
| // Shard().GC(j.StorageID). | |||||
| // MutexLock(execCtx.Args.DistLock) | |||||
| // if err != nil { | |||||
| // log.Warnf("acquire locks failed, err: %s", err.Error()) | |||||
| // return | |||||
| // } | |||||
| // defer mutex.Unlock() | |||||
| spaceIDs, err := t.db.UserSpace().GetAllIDs(t.db.DefCtx()) | spaceIDs, err := t.db.UserSpace().GetAllIDs(t.db.DefCtx()) | ||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("getting user space ids: %v", err) | log.Warnf("getting user space ids: %v", err) | ||||
| @@ -63,11 +52,17 @@ func (j *ShardStoreGC) Execute(t *TickTock) { | |||||
| } | } | ||||
| func (j *ShardStoreGC) gcOne(t *TickTock, space *types.UserSpaceDetail) error { | func (j *ShardStoreGC) gcOne(t *TickTock, space *types.UserSpaceDetail) error { | ||||
| mutex, err := reqbuilder.NewBuilder().Shard().GC(space.UserSpace.UserSpaceID).MutexLock(t.pubLock) | |||||
| if err != nil { | |||||
| return fmt.Errorf("acquire lock: %w", err) | |||||
| } | |||||
| defer mutex.Unlock() | |||||
| 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) | ||||
| @@ -7,6 +7,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/common/pkgs/logger" | "gitlink.org.cn/cloudream/common/pkgs/logger" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/metacache" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/metacache" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/pool" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/pool" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/sysevent" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/sysevent" | ||||
| ) | ) | ||||
| @@ -29,9 +30,10 @@ type TickTock struct { | |||||
| spaceMeta *metacache.UserSpaceMeta | spaceMeta *metacache.UserSpaceMeta | ||||
| stgPool *pool.Pool | stgPool *pool.Pool | ||||
| evtPub *sysevent.Publisher | evtPub *sysevent.Publisher | ||||
| pubLock *distlock.Service | |||||
| } | } | ||||
| func New(cfg Config, db *db.DB, spaceMeta *metacache.UserSpaceMeta, stgPool *pool.Pool, evtPub *sysevent.Publisher) *TickTock { | |||||
| func New(cfg Config, db *db.DB, spaceMeta *metacache.UserSpaceMeta, stgPool *pool.Pool, evtPub *sysevent.Publisher, pubLock *distlock.Service) *TickTock { | |||||
| sch, _ := gocron.NewScheduler() | sch, _ := gocron.NewScheduler() | ||||
| t := &TickTock{ | t := &TickTock{ | ||||
| cfg: cfg, | cfg: cfg, | ||||
| @@ -41,6 +43,7 @@ func New(cfg Config, db *db.DB, spaceMeta *metacache.UserSpaceMeta, stgPool *poo | |||||
| spaceMeta: spaceMeta, | spaceMeta: spaceMeta, | ||||
| stgPool: stgPool, | stgPool: stgPool, | ||||
| evtPub: evtPub, | evtPub: evtPub, | ||||
| pubLock: pubLock, | |||||
| } | } | ||||
| t.initJobs() | t.initJobs() | ||||
| return t | return t | ||||
| @@ -11,6 +11,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec" | "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/types" | "gitlink.org.cn/cloudream/jcs-pub/client/types" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | |||||
| "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" | ||||
| @@ -21,10 +22,10 @@ type CreateLoadUploader struct { | |||||
| targetSpaces []types.UserSpaceDetail | targetSpaces []types.UserSpaceDetail | ||||
| loadRoots []string | loadRoots []string | ||||
| uploader *Uploader | uploader *Uploader | ||||
| // distlock *distlock.Mutex | |||||
| successes []db.AddObjectEntry | |||||
| lock sync.Mutex | |||||
| commited bool | |||||
| pubLock *distlock.Mutex | |||||
| successes []db.AddObjectEntry | |||||
| lock sync.Mutex | |||||
| commited bool | |||||
| } | } | ||||
| type CreateLoadResult struct { | type CreateLoadResult struct { | ||||
| @@ -92,7 +93,7 @@ func (u *CreateLoadUploader) Commit() (CreateLoadResult, error) { | |||||
| } | } | ||||
| u.commited = true | u.commited = true | ||||
| // defer u.distlock.Unlock() | |||||
| defer u.pubLock.Unlock() | |||||
| var addedObjs []types.Object | var addedObjs []types.Object | ||||
| err := u.uploader.db.DoTx(func(tx db.SQLContext) error { | err := u.uploader.db.DoTx(func(tx db.SQLContext) error { | ||||
| @@ -125,7 +126,8 @@ func (u *CreateLoadUploader) Abort() { | |||||
| } | } | ||||
| u.commited = true | u.commited = true | ||||
| // u.distlock.Unlock() | |||||
| u.pubLock.Unlock() | |||||
| // TODO 可以考虑删除PackageID | |||||
| db2 := u.uploader.db | |||||
| db.DoTx10(db2, db2.Package().DeleteComplete, u.pkg.PackageID) | |||||
| } | } | ||||
| @@ -12,16 +12,17 @@ import ( | |||||
| "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec" | "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/types" | "gitlink.org.cn/cloudream/jcs-pub/client/types" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | |||||
| "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" | ||||
| ) | ) | ||||
| type UpdateUploader struct { | type UpdateUploader struct { | ||||
| uploader *Uploader | |||||
| pkgID types.PackageID | |||||
| targetSpace types.UserSpaceDetail | |||||
| // distMutex *distlock.Mutex | |||||
| uploader *Uploader | |||||
| pkgID types.PackageID | |||||
| targetSpace types.UserSpaceDetail | |||||
| pubLock *distlock.Mutex | |||||
| loadToSpaces []types.UserSpaceDetail | loadToSpaces []types.UserSpaceDetail | ||||
| loadToPath []string | loadToPath []string | ||||
| successes []db.AddObjectEntry | successes []db.AddObjectEntry | ||||
| @@ -125,7 +126,7 @@ func (w *UpdateUploader) Commit() (UpdateResult, error) { | |||||
| } | } | ||||
| w.commited = true | w.commited = true | ||||
| // defer w.distMutex.Unlock() | |||||
| defer w.pubLock.Unlock() | |||||
| var addedObjs []types.Object | var addedObjs []types.Object | ||||
| err := w.uploader.db.DoTx(func(tx db.SQLContext) error { | err := w.uploader.db.DoTx(func(tx db.SQLContext) error { | ||||
| @@ -157,5 +158,5 @@ func (w *UpdateUploader) Abort() { | |||||
| } | } | ||||
| w.commited = true | w.commited = true | ||||
| // w.distMutex.Unlock() | |||||
| w.pubLock.Unlock() | |||||
| } | } | ||||
| @@ -18,6 +18,7 @@ import ( | |||||
| 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/connectivity" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/connectivity" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | ||||
| "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" | ||||
| @@ -25,16 +26,16 @@ import ( | |||||
| ) | ) | ||||
| type Uploader struct { | type Uploader struct { | ||||
| distlock *distlock.Service | |||||
| pubLock *distlock.Service | |||||
| connectivity *connectivity.Collector | connectivity *connectivity.Collector | ||||
| stgPool *pool.Pool | stgPool *pool.Pool | ||||
| spaceMeta *metacache.UserSpaceMeta | spaceMeta *metacache.UserSpaceMeta | ||||
| db *db.DB | db *db.DB | ||||
| } | } | ||||
| func NewUploader(distlock *distlock.Service, connectivity *connectivity.Collector, stgPool *pool.Pool, spaceMeta *metacache.UserSpaceMeta, db *db.DB) *Uploader { | |||||
| func NewUploader(pubLock *distlock.Service, connectivity *connectivity.Collector, stgPool *pool.Pool, spaceMeta *metacache.UserSpaceMeta, db *db.DB) *Uploader { | |||||
| return &Uploader{ | return &Uploader{ | ||||
| distlock: distlock, | |||||
| pubLock: pubLock, | |||||
| connectivity: connectivity, | connectivity: connectivity, | ||||
| stgPool: stgPool, | stgPool: stgPool, | ||||
| spaceMeta: spaceMeta, | spaceMeta: spaceMeta, | ||||
| @@ -93,20 +94,17 @@ func (u *Uploader) BeginUpdate(pkgID clitypes.PackageID, affinity clitypes.UserS | |||||
| target := u.chooseUploadStorage(uploadSpaces, affinity) | target := u.chooseUploadStorage(uploadSpaces, affinity) | ||||
| // TODO2 加锁 | |||||
| // 给上传节点的IPFS加锁 | |||||
| // TODO 考虑加Object的Create锁 | |||||
| // 防止上传的副本被清除 | // 防止上传的副本被清除 | ||||
| // distMutex, err := reqbuilder.NewBuilder().Shard().Buzy(target.Space.Storage.StorageID).MutexLock(u.distlock) | |||||
| // if err != nil { | |||||
| // return nil, fmt.Errorf("acquire distlock: %w", err) | |||||
| // } | |||||
| pubLock, err := reqbuilder.NewBuilder().Shard().Buzy(target.Space.UserSpace.UserSpaceID).MutexLock(u.pubLock) | |||||
| if err != nil { | |||||
| return nil, fmt.Errorf("acquire lock: %w", err) | |||||
| } | |||||
| return &UpdateUploader{ | return &UpdateUploader{ | ||||
| uploader: u, | |||||
| pkgID: pkgID, | |||||
| targetSpace: target.Space, | |||||
| // distMutex: distMutex, | |||||
| uploader: u, | |||||
| pkgID: pkgID, | |||||
| targetSpace: target.Space, | |||||
| pubLock: pubLock, | |||||
| loadToSpaces: loadToSpaces, | loadToSpaces: loadToSpaces, | ||||
| loadToPath: loadToPath, | loadToPath: loadToPath, | ||||
| }, nil | }, nil | ||||
| @@ -158,23 +156,21 @@ func (u *Uploader) BeginCreateLoad(bktID clitypes.BucketID, pkgName string, load | |||||
| return nil, fmt.Errorf("create package: %w", err) | return nil, fmt.Errorf("create package: %w", err) | ||||
| } | } | ||||
| // TODO2 加锁 | |||||
| // reqBld := reqbuilder.NewBuilder() | |||||
| // for _, stg := range spacesStgs { | |||||
| // reqBld.Shard().Buzy(stg.Storage.StorageID) | |||||
| // reqBld.Storage().Buzy(stg.Storage.StorageID) | |||||
| // } | |||||
| // lock, err := reqBld.MutexLock(u.distlock) | |||||
| // if err != nil { | |||||
| // return nil, fmt.Errorf("acquire distlock: %w", err) | |||||
| // } | |||||
| reqBld := reqbuilder.NewBuilder() | |||||
| for _, stg := range spacesStgs { | |||||
| reqBld.Shard().Buzy(stg.UserSpace.UserSpaceID) | |||||
| } | |||||
| lock, err := reqBld.MutexLock(u.pubLock) | |||||
| if err != nil { | |||||
| return nil, fmt.Errorf("acquire lock: %w", err) | |||||
| } | |||||
| return &CreateLoadUploader{ | return &CreateLoadUploader{ | ||||
| pkg: pkg, | pkg: pkg, | ||||
| targetSpaces: spacesStgs, | targetSpaces: spacesStgs, | ||||
| loadRoots: loadToPath, | loadRoots: loadToPath, | ||||
| uploader: u, | uploader: u, | ||||
| // distlock: lock, | |||||
| pubLock: lock, | |||||
| }, nil | }, nil | ||||
| } | } | ||||
| @@ -236,12 +232,11 @@ func (u *Uploader) UploadPart(objID clitypes.ObjectID, index int, stream io.Read | |||||
| space = u.chooseUploadStorage(userStgs, 0).Space | space = u.chooseUploadStorage(userStgs, 0).Space | ||||
| } | } | ||||
| // TODO2 加锁 | |||||
| // lock, err := reqbuilder.NewBuilder().Shard().Buzy(space.Storage.StorageID).MutexLock(u.distlock) | |||||
| // if err != nil { | |||||
| // return fmt.Errorf("acquire distlock: %w", err) | |||||
| // } | |||||
| // defer lock.Unlock() | |||||
| lock, err := reqbuilder.NewBuilder().Shard().Buzy(space.UserSpace.UserSpaceID).MutexLock(u.pubLock) | |||||
| if err != nil { | |||||
| return fmt.Errorf("acquire lock: %w", err) | |||||
| } | |||||
| defer lock.Unlock() | |||||
| ft := ioswitch2.NewFromTo() | ft := ioswitch2.NewFromTo() | ||||
| fromDrv, hd := ioswitch2.NewFromDriver(ioswitch2.RawStream()) | fromDrv, hd := ioswitch2.NewFromDriver(ioswitch2.RawStream()) | ||||
| @@ -12,7 +12,6 @@ | |||||
| - `pkgs`:一些相对独立的功能模块。 | - `pkgs`:一些相对独立的功能模块。 | ||||
| - `cmd`:公用的业务逻辑,比如上传Package和下载Package。 | - `cmd`:公用的业务逻辑,比如上传Package和下载Package。 | ||||
| - `db`:数据库的数据结构和操作函数。 | - `db`:数据库的数据结构和操作函数。 | ||||
| - `distlock`:分布式锁服务,核心机制使用的是`common/pkgs/distlock`,增加了根据存储系统的业务需求设计的锁。 | |||||
| - `ec`:纠删码的库。 | - `ec`:纠删码的库。 | ||||
| - `grpc`:存放proto文件,以及使用protogen工具生成的代码文件。 | - `grpc`:存放proto文件,以及使用protogen工具生成的代码文件。 | ||||
| - `ioswitch`:IOSwitch模块。 | - `ioswitch`:IOSwitch模块。 | ||||
| @@ -28,14 +28,6 @@ | |||||
| "retryInterval": 5000 | "retryInterval": 5000 | ||||
| } | } | ||||
| }, | }, | ||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a client" | |||||
| }, | |||||
| "connectivity": { | "connectivity": { | ||||
| "testInterval": 300 | "testInterval": 300 | ||||
| }, | }, | ||||
| @@ -25,14 +25,6 @@ | |||||
| "retryInterval": 5000 | "retryInterval": 5000 | ||||
| } | } | ||||
| }, | }, | ||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a hub" | |||||
| }, | |||||
| "connectivity": { | "connectivity": { | ||||
| "testInterval": 300 | "testInterval": 300 | ||||
| } | } | ||||
| @@ -1,35 +0,0 @@ | |||||
| { | |||||
| "accessStatHistoryAmount": 0.8, | |||||
| "ecFileSizeThreshold": 104857600, | |||||
| "hubUnavailableSeconds": 300, | |||||
| "logger": { | |||||
| "output": "file", | |||||
| "outputFileName": "scanner", | |||||
| "outputDirectory": "log", | |||||
| "level": "debug" | |||||
| }, | |||||
| "db": { | |||||
| "address": "127.0.0.1:3306", | |||||
| "account": "", | |||||
| "password": "", | |||||
| "databaseName": "cloudream" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "", | |||||
| "password": "", | |||||
| "vhost": "/", | |||||
| "param": { | |||||
| "retryNum": 5, | |||||
| "retryInterval": 5000 | |||||
| } | |||||
| }, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a scanner" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| package lockprovider | |||||
| import "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| type EmptyTarget struct{} | |||||
| func NewEmptyTarget() *EmptyTarget { | |||||
| return &EmptyTarget{} | |||||
| } | |||||
| func (e *EmptyTarget) Equals(other types.LockTarget) bool { | |||||
| _, ok := other.(*EmptyTarget) | |||||
| return ok | |||||
| } | |||||
| @@ -4,7 +4,7 @@ import ( | |||||
| "fmt" | "fmt" | ||||
| "github.com/samber/lo" | "github.com/samber/lo" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| @@ -16,7 +16,7 @@ const ( | |||||
| type HasSuchLockFn = func() bool | type HasSuchLockFn = func() bool | ||||
| // LockCompatibilitySpecialFn 判断锁与指定的锁名是否兼容 | // LockCompatibilitySpecialFn 判断锁与指定的锁名是否兼容 | ||||
| type LockCompatibilitySpecialFn func(lock distlock.Lock, testLockName string) bool | |||||
| type LockCompatibilitySpecialFn func(lock types.Lock, testLockName string) bool | |||||
| type LockCompatibilityType string | type LockCompatibilityType string | ||||
| @@ -95,7 +95,7 @@ func (t *LockCompatibilityTable) Row(comps ...LockCompatibility) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func (t *LockCompatibilityTable) Test(lock distlock.Lock) error { | |||||
| func (t *LockCompatibilityTable) Test(lock types.Lock) error { | |||||
| row, ok := lo.Find(t.rows, func(row LockCompatibilityTableRow) bool { return lock.Name == row.LockName }) | row, ok := lo.Find(t.rows, func(row LockCompatibilityTableRow) bool { return lock.Name == row.LockName }) | ||||
| if !ok { | if !ok { | ||||
| return fmt.Errorf("unknow lock name %s", lock.Name) | return fmt.Errorf("unknow lock name %s", lock.Name) | ||||
| @@ -108,13 +108,13 @@ func (t *LockCompatibilityTable) Test(lock distlock.Lock) error { | |||||
| if c.Type == LOCK_COMPATIBILITY_UNCOMPATIBLE { | if c.Type == LOCK_COMPATIBILITY_UNCOMPATIBLE { | ||||
| if t.rows[i].HasSuchLockFn() { | if t.rows[i].HasSuchLockFn() { | ||||
| return distlock.NewLockTargetBusyError(t.rows[i].LockName) | |||||
| return types.NewLockTargetBusyError(t.rows[i].LockName) | |||||
| } | } | ||||
| } | } | ||||
| if c.Type == LOCK_COMPATIBILITY_SPECIAL { | if c.Type == LOCK_COMPATIBILITY_SPECIAL { | ||||
| if !c.SpecialFn(lock, t.rows[i].LockName) { | if !c.SpecialFn(lock, t.rows[i].LockName) { | ||||
| return distlock.NewLockTargetBusyError(t.rows[i].LockName) | |||||
| return types.NewLockTargetBusyError(t.rows[i].LockName) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -4,7 +4,7 @@ import ( | |||||
| "testing" | "testing" | ||||
| . "github.com/smartystreets/goconvey/convey" | . "github.com/smartystreets/goconvey/convey" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| func Test_LockCompatibilityTable(t *testing.T) { | func Test_LockCompatibilityTable(t *testing.T) { | ||||
| @@ -18,22 +18,22 @@ func Test_LockCompatibilityTable(t *testing.T) { | |||||
| comp := LockCompatible() | comp := LockCompatible() | ||||
| uncp := LockUncompatible() | uncp := LockUncompatible() | ||||
| spcl := LockSpecial(func(lock distlock.Lock, testLockName string) bool { return true }) | |||||
| spcl := LockSpecial(func(lock types.Lock, testLockName string) bool { return true }) | |||||
| table.Row(comp, comp, comp) | table.Row(comp, comp, comp) | ||||
| table.Row(comp, uncp, comp) | table.Row(comp, uncp, comp) | ||||
| table.Row(comp, comp, spcl) | table.Row(comp, comp, spcl) | ||||
| err := table.Test(distlock.Lock{ | |||||
| err := table.Test(types.Lock{ | |||||
| Name: "l1", | Name: "l1", | ||||
| }) | }) | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| err = table.Test(distlock.Lock{ | |||||
| err = table.Test(types.Lock{ | |||||
| Name: "l2", | Name: "l2", | ||||
| }) | }) | ||||
| So(err, ShouldNotBeNil) | So(err, ShouldNotBeNil) | ||||
| err = table.Test(distlock.Lock{ | |||||
| err = table.Test(types.Lock{ | |||||
| Name: "l3", | Name: "l3", | ||||
| }) | }) | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| @@ -1,122 +0,0 @@ | |||||
| package lockprovider | |||||
| import ( | |||||
| "fmt" | |||||
| "github.com/samber/lo" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | |||||
| ) | |||||
| const ( | |||||
| MetadataLockPathPrefix = "Metadata" | |||||
| MetadataCreateLock = "Create" | |||||
| ) | |||||
| type metadataElementLock struct { | |||||
| target StringLockTarget | |||||
| requestIDs []string | |||||
| } | |||||
| type MetadataLock struct { | |||||
| createReqIDs []*metadataElementLock | |||||
| lockCompatibilityTable LockCompatibilityTable | |||||
| } | |||||
| func NewMetadataLock() *MetadataLock { | |||||
| metadataLock := MetadataLock{ | |||||
| lockCompatibilityTable: LockCompatibilityTable{}, | |||||
| } | |||||
| compTable := &metadataLock.lockCompatibilityTable | |||||
| compTable. | |||||
| Column(MetadataCreateLock, func() bool { return len(metadataLock.createReqIDs) > 0 }) | |||||
| trgt := LockSpecial(func(lock distlock.Lock, testLockName string) bool { | |||||
| strTar := lock.Target.(StringLockTarget) | |||||
| return lo.NoneBy(metadataLock.createReqIDs, func(other *metadataElementLock) bool { return strTar.IsConflict(&other.target) }) | |||||
| }) | |||||
| compTable.MustRow(trgt) | |||||
| return &metadataLock | |||||
| } | |||||
| // CanLock 判断这个锁能否锁定成功 | |||||
| func (l *MetadataLock) CanLock(lock distlock.Lock) error { | |||||
| return l.lockCompatibilityTable.Test(lock) | |||||
| } | |||||
| // 锁定 | |||||
| func (l *MetadataLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| switch lock.Name { | |||||
| case MetadataCreateLock: | |||||
| l.createReqIDs = l.addElementLock(lock, l.createReqIDs, reqID) | |||||
| default: | |||||
| return fmt.Errorf("unknow lock name: %s", lock.Name) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| func (l *MetadataLock) addElementLock(lock distlock.Lock, locks []*metadataElementLock, reqID string) []*metadataElementLock { | |||||
| strTarget := lock.Target.(StringLockTarget) | |||||
| lck, ok := lo.Find(locks, func(l *metadataElementLock) bool { return strTarget.IsConflict(&l.target) }) | |||||
| if !ok { | |||||
| lck = &metadataElementLock{ | |||||
| target: strTarget, | |||||
| } | |||||
| locks = append(locks, lck) | |||||
| } | |||||
| lck.requestIDs = append(lck.requestIDs, reqID) | |||||
| return locks | |||||
| } | |||||
| // 解锁 | |||||
| func (l *MetadataLock) Unlock(reqID string, lock distlock.Lock) error { | |||||
| switch lock.Name { | |||||
| case MetadataCreateLock: | |||||
| l.createReqIDs = l.removeElementLock(lock, l.createReqIDs, reqID) | |||||
| default: | |||||
| return fmt.Errorf("unknow lock name: %s", lock.Name) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| func (l *MetadataLock) removeElementLock(lock distlock.Lock, locks []*metadataElementLock, reqID string) []*metadataElementLock { | |||||
| strTarget := lock.Target.(StringLockTarget) | |||||
| lck, index, ok := lo.FindIndexOf(locks, func(l *metadataElementLock) bool { return strTarget.IsConflict(&l.target) }) | |||||
| if !ok { | |||||
| return locks | |||||
| } | |||||
| lck.requestIDs = lo2.Remove(lck.requestIDs, reqID) | |||||
| if len(lck.requestIDs) == 0 { | |||||
| locks = lo2.RemoveAt(locks, index) | |||||
| } | |||||
| return locks | |||||
| } | |||||
| // GetTargetString 将锁对象序列化为字符串,方便存储到ETCD | |||||
| func (l *MetadataLock) GetTargetString(target any) (string, error) { | |||||
| tar := target.(StringLockTarget) | |||||
| return StringLockTargetToString(&tar) | |||||
| } | |||||
| // ParseTargetString 解析字符串格式的锁对象数据 | |||||
| func (l *MetadataLock) ParseTargetString(targetStr string) (any, error) { | |||||
| return StringLockTargetFromString(targetStr) | |||||
| } | |||||
| // Clear 清除内部所有状态 | |||||
| func (l *MetadataLock) Clear() { | |||||
| l.createReqIDs = nil | |||||
| } | |||||
| @@ -3,8 +3,8 @@ package lockprovider | |||||
| import ( | import ( | ||||
| "fmt" | "fmt" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | "gitlink.org.cn/cloudream/common/utils/lo2" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| @@ -27,7 +27,7 @@ func NewShardStoreLock() *ShardStoreLock { | |||||
| } | } | ||||
| // CanLock 判断这个锁能否锁定成功 | // CanLock 判断这个锁能否锁定成功 | ||||
| func (l *ShardStoreLock) CanLock(lock distlock.Lock) error { | |||||
| func (l *ShardStoreLock) CanLock(lock types.Lock) error { | |||||
| nodeLock, ok := l.stgLocks[lock.Path[ShardStoreStorageIDPathIndex]] | nodeLock, ok := l.stgLocks[lock.Path[ShardStoreStorageIDPathIndex]] | ||||
| if !ok { | if !ok { | ||||
| // 不能直接返回nil,因为如果锁数据的格式不对,也不能获取锁。 | // 不能直接返回nil,因为如果锁数据的格式不对,也不能获取锁。 | ||||
| @@ -39,7 +39,7 @@ func (l *ShardStoreLock) CanLock(lock distlock.Lock) error { | |||||
| } | } | ||||
| // 锁定。在内部可以不用判断能否加锁,外部需要保证调用此函数前调用了CanLock进行检查 | // 锁定。在内部可以不用判断能否加锁,外部需要保证调用此函数前调用了CanLock进行检查 | ||||
| func (l *ShardStoreLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| func (l *ShardStoreLock) Lock(reqID types.RequestID, lock types.Lock) error { | |||||
| stgID := lock.Path[ShardStoreStorageIDPathIndex] | stgID := lock.Path[ShardStoreStorageIDPathIndex] | ||||
| nodeLock, ok := l.stgLocks[stgID] | nodeLock, ok := l.stgLocks[stgID] | ||||
| @@ -52,7 +52,7 @@ func (l *ShardStoreLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| } | } | ||||
| // 解锁 | // 解锁 | ||||
| func (l *ShardStoreLock) Unlock(reqID string, lock distlock.Lock) error { | |||||
| func (l *ShardStoreLock) Unlock(reqID types.RequestID, lock types.Lock) error { | |||||
| stgID := lock.Path[ShardStoreStorageIDPathIndex] | stgID := lock.Path[ShardStoreStorageIDPathIndex] | ||||
| nodeLock, ok := l.stgLocks[stgID] | nodeLock, ok := l.stgLocks[stgID] | ||||
| @@ -63,25 +63,14 @@ func (l *ShardStoreLock) Unlock(reqID string, lock distlock.Lock) error { | |||||
| return nodeLock.Unlock(reqID, lock) | return nodeLock.Unlock(reqID, lock) | ||||
| } | } | ||||
| // GetTargetString 将锁对象序列化为字符串,方便存储到ETCD | |||||
| func (l *ShardStoreLock) GetTargetString(target any) (string, error) { | |||||
| tar := target.(StringLockTarget) | |||||
| return StringLockTargetToString(&tar) | |||||
| } | |||||
| // ParseTargetString 解析字符串格式的锁对象数据 | |||||
| func (l *ShardStoreLock) ParseTargetString(targetStr string) (any, error) { | |||||
| return StringLockTargetFromString(targetStr) | |||||
| } | |||||
| // Clear 清除内部所有状态 | // Clear 清除内部所有状态 | ||||
| func (l *ShardStoreLock) Clear() { | func (l *ShardStoreLock) Clear() { | ||||
| l.stgLocks = make(map[string]*ShardStoreStorageLock) | l.stgLocks = make(map[string]*ShardStoreStorageLock) | ||||
| } | } | ||||
| type ShardStoreStorageLock struct { | type ShardStoreStorageLock struct { | ||||
| buzyReqIDs []string | |||||
| gcReqIDs []string | |||||
| buzyReqIDs []types.RequestID | |||||
| gcReqIDs []types.RequestID | |||||
| lockCompatibilityTable *LockCompatibilityTable | lockCompatibilityTable *LockCompatibilityTable | ||||
| } | } | ||||
| @@ -107,12 +96,12 @@ func NewShardStoreStorageLock() *ShardStoreStorageLock { | |||||
| } | } | ||||
| // CanLock 判断这个锁能否锁定成功 | // CanLock 判断这个锁能否锁定成功 | ||||
| func (l *ShardStoreStorageLock) CanLock(lock distlock.Lock) error { | |||||
| func (l *ShardStoreStorageLock) CanLock(lock types.Lock) error { | |||||
| return l.lockCompatibilityTable.Test(lock) | return l.lockCompatibilityTable.Test(lock) | ||||
| } | } | ||||
| // 锁定 | // 锁定 | ||||
| func (l *ShardStoreStorageLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| func (l *ShardStoreStorageLock) Lock(reqID types.RequestID, lock types.Lock) error { | |||||
| switch lock.Name { | switch lock.Name { | ||||
| case ShardStoreBuzyLock: | case ShardStoreBuzyLock: | ||||
| l.buzyReqIDs = append(l.buzyReqIDs, reqID) | l.buzyReqIDs = append(l.buzyReqIDs, reqID) | ||||
| @@ -126,7 +115,7 @@ func (l *ShardStoreStorageLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| } | } | ||||
| // 解锁 | // 解锁 | ||||
| func (l *ShardStoreStorageLock) Unlock(reqID string, lock distlock.Lock) error { | |||||
| func (l *ShardStoreStorageLock) Unlock(reqID types.RequestID, lock types.Lock) error { | |||||
| switch lock.Name { | switch lock.Name { | ||||
| case ShardStoreBuzyLock: | case ShardStoreBuzyLock: | ||||
| l.buzyReqIDs = lo2.Remove(l.buzyReqIDs, reqID) | l.buzyReqIDs = lo2.Remove(l.buzyReqIDs, reqID) | ||||
| @@ -4,25 +4,25 @@ import ( | |||||
| "testing" | "testing" | ||||
| . "github.com/smartystreets/goconvey/convey" | . "github.com/smartystreets/goconvey/convey" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| func Test_ShardStoreLock(t *testing.T) { | func Test_ShardStoreLock(t *testing.T) { | ||||
| cases := []struct { | cases := []struct { | ||||
| title string | title string | ||||
| initLocks []distlock.Lock | |||||
| doLock distlock.Lock | |||||
| initLocks []types.Lock | |||||
| doLock types.Lock | |||||
| wantOK bool | wantOK bool | ||||
| }{ | }{ | ||||
| { | { | ||||
| title: "同节点,同一个Buzy锁", | title: "同节点,同一个Buzy锁", | ||||
| initLocks: []distlock.Lock{ | |||||
| initLocks: []types.Lock{ | |||||
| { | { | ||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreBuzyLock, | Name: ShardStoreBuzyLock, | ||||
| }, | }, | ||||
| }, | }, | ||||
| doLock: distlock.Lock{ | |||||
| doLock: types.Lock{ | |||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreBuzyLock, | Name: ShardStoreBuzyLock, | ||||
| }, | }, | ||||
| @@ -30,13 +30,13 @@ func Test_ShardStoreLock(t *testing.T) { | |||||
| }, | }, | ||||
| { | { | ||||
| title: "同节点,同一个GC锁", | title: "同节点,同一个GC锁", | ||||
| initLocks: []distlock.Lock{ | |||||
| initLocks: []types.Lock{ | |||||
| { | { | ||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreGCLock, | Name: ShardStoreGCLock, | ||||
| }, | }, | ||||
| }, | }, | ||||
| doLock: distlock.Lock{ | |||||
| doLock: types.Lock{ | |||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreGCLock, | Name: ShardStoreGCLock, | ||||
| }, | }, | ||||
| @@ -44,17 +44,17 @@ func Test_ShardStoreLock(t *testing.T) { | |||||
| }, | }, | ||||
| { | { | ||||
| title: "同时设置Buzy和GC", | title: "同时设置Buzy和GC", | ||||
| initLocks: []distlock.Lock{ | |||||
| initLocks: []types.Lock{ | |||||
| { | { | ||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreBuzyLock, | Name: ShardStoreBuzyLock, | ||||
| Target: *NewStringLockTarget(), | |||||
| Target: NewStringLockTarget(), | |||||
| }, | }, | ||||
| }, | }, | ||||
| doLock: distlock.Lock{ | |||||
| doLock: types.Lock{ | |||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreGCLock, | Name: ShardStoreGCLock, | ||||
| Target: *NewStringLockTarget(), | |||||
| Target: NewStringLockTarget(), | |||||
| }, | }, | ||||
| wantOK: false, | wantOK: false, | ||||
| }, | }, | ||||
| @@ -80,7 +80,7 @@ func Test_ShardStoreLock(t *testing.T) { | |||||
| Convey("解锁", t, func() { | Convey("解锁", t, func() { | ||||
| ipfsLock := NewShardStoreLock() | ipfsLock := NewShardStoreLock() | ||||
| lock := distlock.Lock{ | |||||
| lock := types.Lock{ | |||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreBuzyLock, | Name: ShardStoreBuzyLock, | ||||
| } | } | ||||
| @@ -92,7 +92,7 @@ func Test_ShardStoreLock(t *testing.T) { | |||||
| ipfsLock.Unlock("req1", lock) | ipfsLock.Unlock("req1", lock) | ||||
| lock = distlock.Lock{ | |||||
| lock = types.Lock{ | |||||
| Path: []string{ShardStoreLockPathPrefix, "hub1"}, | Path: []string{ShardStoreLockPathPrefix, "hub1"}, | ||||
| Name: ShardStoreGCLock, | Name: ShardStoreGCLock, | ||||
| } | } | ||||
| @@ -1,140 +0,0 @@ | |||||
| package lockprovider | |||||
| import ( | |||||
| "fmt" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | |||||
| ) | |||||
| const ( | |||||
| StorageLockPathPrefix = "Storage" | |||||
| StorageHubIDPathIndex = 1 | |||||
| StorageBuzyLock = "Buzy" | |||||
| StorageGCLock = "GC" | |||||
| ) | |||||
| type StorageLock struct { | |||||
| nodeLocks map[string]*StorageNodeLock | |||||
| dummyLock *StorageNodeLock | |||||
| } | |||||
| func NewStorageLock() *StorageLock { | |||||
| return &StorageLock{ | |||||
| nodeLocks: make(map[string]*StorageNodeLock), | |||||
| dummyLock: NewStorageNodeLock(), | |||||
| } | |||||
| } | |||||
| // CanLock 判断这个锁能否锁定成功 | |||||
| func (l *StorageLock) CanLock(lock distlock.Lock) error { | |||||
| nodeLock, ok := l.nodeLocks[lock.Path[StorageHubIDPathIndex]] | |||||
| if !ok { | |||||
| // 不能直接返回nil,因为如果锁数据的格式不对,也不能获取锁。 | |||||
| // 这里使用一个空Provider来进行检查。 | |||||
| return l.dummyLock.CanLock(lock) | |||||
| } | |||||
| return nodeLock.CanLock(lock) | |||||
| } | |||||
| // 锁定。在内部可以不用判断能否加锁,外部需要保证调用此函数前调用了CanLock进行检查 | |||||
| func (l *StorageLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| hubID := lock.Path[StorageHubIDPathIndex] | |||||
| nodeLock, ok := l.nodeLocks[hubID] | |||||
| if !ok { | |||||
| nodeLock = NewStorageNodeLock() | |||||
| l.nodeLocks[hubID] = nodeLock | |||||
| } | |||||
| return nodeLock.Lock(reqID, lock) | |||||
| } | |||||
| // 解锁 | |||||
| func (l *StorageLock) Unlock(reqID string, lock distlock.Lock) error { | |||||
| hubID := lock.Path[StorageHubIDPathIndex] | |||||
| nodeLock, ok := l.nodeLocks[hubID] | |||||
| if !ok { | |||||
| return nil | |||||
| } | |||||
| return nodeLock.Unlock(reqID, lock) | |||||
| } | |||||
| // GetTargetString 将锁对象序列化为字符串,方便存储到ETCD | |||||
| func (l *StorageLock) GetTargetString(target any) (string, error) { | |||||
| tar := target.(StringLockTarget) | |||||
| return StringLockTargetToString(&tar) | |||||
| } | |||||
| // ParseTargetString 解析字符串格式的锁对象数据 | |||||
| func (l *StorageLock) ParseTargetString(targetStr string) (any, error) { | |||||
| return StringLockTargetFromString(targetStr) | |||||
| } | |||||
| // Clear 清除内部所有状态 | |||||
| func (l *StorageLock) Clear() { | |||||
| l.nodeLocks = make(map[string]*StorageNodeLock) | |||||
| } | |||||
| type StorageNodeLock struct { | |||||
| buzyReqIDs []string | |||||
| gcReqIDs []string | |||||
| lockCompatibilityTable *LockCompatibilityTable | |||||
| } | |||||
| func NewStorageNodeLock() *StorageNodeLock { | |||||
| compTable := &LockCompatibilityTable{} | |||||
| StorageLock := StorageNodeLock{ | |||||
| lockCompatibilityTable: compTable, | |||||
| } | |||||
| compTable. | |||||
| Column(StorageBuzyLock, func() bool { return len(StorageLock.buzyReqIDs) > 0 }). | |||||
| Column(StorageGCLock, func() bool { return len(StorageLock.gcReqIDs) > 0 }) | |||||
| comp := LockCompatible() | |||||
| uncp := LockUncompatible() | |||||
| compTable.MustRow(comp, uncp) | |||||
| compTable.MustRow(uncp, comp) | |||||
| return &StorageLock | |||||
| } | |||||
| // CanLock 判断这个锁能否锁定成功 | |||||
| func (l *StorageNodeLock) CanLock(lock distlock.Lock) error { | |||||
| return l.lockCompatibilityTable.Test(lock) | |||||
| } | |||||
| // 锁定 | |||||
| func (l *StorageNodeLock) Lock(reqID string, lock distlock.Lock) error { | |||||
| switch lock.Name { | |||||
| case StorageBuzyLock: | |||||
| l.buzyReqIDs = append(l.buzyReqIDs, reqID) | |||||
| case StorageGCLock: | |||||
| l.gcReqIDs = append(l.gcReqIDs, reqID) | |||||
| default: | |||||
| return fmt.Errorf("unknow lock name: %s", lock.Name) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| // 解锁 | |||||
| func (l *StorageNodeLock) Unlock(reqID string, lock distlock.Lock) error { | |||||
| switch lock.Name { | |||||
| case StorageBuzyLock: | |||||
| l.buzyReqIDs = lo2.Remove(l.buzyReqIDs, reqID) | |||||
| case StorageGCLock: | |||||
| l.gcReqIDs = lo2.Remove(l.gcReqIDs, reqID) | |||||
| default: | |||||
| return fmt.Errorf("unknow lock name: %s", lock.Name) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -5,6 +5,7 @@ import ( | |||||
| "github.com/samber/lo" | "github.com/samber/lo" | ||||
| "gitlink.org.cn/cloudream/common/utils/serder" | "gitlink.org.cn/cloudream/common/utils/serder" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| type StringLockTarget struct { | type StringLockTarget struct { | ||||
| @@ -43,6 +44,25 @@ func (t *StringLockTarget) IsConflict(other *StringLockTarget) bool { | |||||
| return false | return false | ||||
| } | } | ||||
| func (t *StringLockTarget) Equals(other types.LockTarget) bool { | |||||
| st, ok := other.(*StringLockTarget) | |||||
| if !ok { | |||||
| return false | |||||
| } | |||||
| if len(t.Components) != len(st.Components) { | |||||
| return false | |||||
| } | |||||
| for i := 0; i < len(t.Components); i++ { | |||||
| if !t.Components[i].IsEquals(&st.Components[i]) { | |||||
| return false | |||||
| } | |||||
| } | |||||
| return true | |||||
| } | |||||
| type StringLockTargetComponet struct { | type StringLockTargetComponet struct { | ||||
| Values []string `json:"values"` | Values []string `json:"values"` | ||||
| } | } | ||||
| @@ -0,0 +1,15 @@ | |||||
| package distlock | |||||
| import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | |||||
| type Mutex struct { | |||||
| svc *Service | |||||
| lockReq types.LockRequest | |||||
| lockReqID types.RequestID | |||||
| } | |||||
| func (m *Mutex) Unlock() { | |||||
| m.svc.release(m.lockReqID, m.lockReq) | |||||
| } | |||||
| @@ -0,0 +1,53 @@ | |||||
| package distlock | |||||
| import "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| type Reentrant struct { | |||||
| svc *Service | |||||
| reqs []types.LockRequest | |||||
| locked []*Mutex | |||||
| } | |||||
| func (r *Reentrant) Lock(req types.LockRequest, opt ...AcquireOptionFn) error { | |||||
| var willLock []types.Lock | |||||
| loop: | |||||
| for _, lock := range req.Locks { | |||||
| for _, req := range r.reqs { | |||||
| for _, locked := range req.Locks { | |||||
| if locked.Equals(lock) { | |||||
| continue loop | |||||
| } | |||||
| } | |||||
| } | |||||
| willLock = append(willLock, lock) | |||||
| } | |||||
| if len(willLock) == 0 { | |||||
| return nil | |||||
| } | |||||
| newReq := types.LockRequest{ | |||||
| Reason: req.Reason, | |||||
| Locks: willLock, | |||||
| } | |||||
| m, err := r.svc.Acquire(newReq, opt...) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| r.reqs = append(r.reqs, newReq) | |||||
| r.locked = append(r.locked, m) | |||||
| return nil | |||||
| } | |||||
| func (r *Reentrant) Unlock() { | |||||
| for i := len(r.reqs) - 1; i >= 0; i-- { | |||||
| r.locked[i].Unlock() | |||||
| } | |||||
| r.locked = nil | |||||
| r.reqs = nil | |||||
| } | |||||
| @@ -1,30 +1,29 @@ | |||||
| package reqbuilder | package reqbuilder | ||||
| import ( | import ( | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | "gitlink.org.cn/cloudream/common/utils/lo2" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| type LockRequestBuilder struct { | type LockRequestBuilder struct { | ||||
| locks []distlock.Lock | |||||
| locks []types.Lock | |||||
| } | } | ||||
| func NewBuilder() *LockRequestBuilder { | func NewBuilder() *LockRequestBuilder { | ||||
| return &LockRequestBuilder{} | return &LockRequestBuilder{} | ||||
| } | } | ||||
| func (b *LockRequestBuilder) Build() distlock.LockRequest { | |||||
| return distlock.LockRequest{ | |||||
| Locks: lo2.ArrayClone(b.locks), | |||||
| } | |||||
| func (b *LockRequestBuilder) IsEmpty() bool { | |||||
| return len(b.locks) == 0 | |||||
| } | } | ||||
| func (b *LockRequestBuilder) MutexLock(svc *distlock.Service) (*distlock.Mutex, error) { | |||||
| mutex := distlock.NewMutex(svc, b.Build()) | |||||
| err := mutex.Lock() | |||||
| if err != nil { | |||||
| return nil, err | |||||
| func (b *LockRequestBuilder) Build() types.LockRequest { | |||||
| return types.LockRequest{ | |||||
| Locks: lo2.ArrayClone(b.locks), | |||||
| } | } | ||||
| } | |||||
| return mutex, nil | |||||
| func (b *LockRequestBuilder) MutexLock(svc *distlock.Service, opt ...distlock.AcquireOptionFn) (*distlock.Mutex, error) { | |||||
| return svc.Acquire(b.Build(), opt...) | |||||
| } | } | ||||
| @@ -1,17 +0,0 @@ | |||||
| package reqbuilder | |||||
| import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | |||||
| ) | |||||
| type MetadataLockReqBuilder struct { | |||||
| *LockRequestBuilder | |||||
| } | |||||
| func (b *LockRequestBuilder) Metadata() *MetadataLockReqBuilder { | |||||
| return &MetadataLockReqBuilder{LockRequestBuilder: b} | |||||
| } | |||||
| func (b *MetadataLockReqBuilder) makePath(tableName string) []string { | |||||
| return []string{lockprovider.MetadataLockPathPrefix, tableName} | |||||
| } | |||||
| @@ -1,24 +0,0 @@ | |||||
| package reqbuilder | |||||
| import ( | |||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | |||||
| ) | |||||
| type MetadataObjectLockReqBuilder struct { | |||||
| *MetadataLockReqBuilder | |||||
| } | |||||
| func (b *MetadataLockReqBuilder) Object() *MetadataObjectLockReqBuilder { | |||||
| return &MetadataObjectLockReqBuilder{MetadataLockReqBuilder: b} | |||||
| } | |||||
| func (b *MetadataObjectLockReqBuilder) CreateOne(packageID clitypes.PackageID, objectPath string) *MetadataObjectLockReqBuilder { | |||||
| b.locks = append(b.locks, distlock.Lock{ | |||||
| Path: b.makePath("Object"), | |||||
| Name: lockprovider.MetadataCreateLock, | |||||
| Target: *lockprovider.NewStringLockTarget().Add(packageID, objectPath), | |||||
| }) | |||||
| return b | |||||
| } | |||||
| @@ -3,9 +3,9 @@ package reqbuilder | |||||
| import ( | import ( | ||||
| "strconv" | "strconv" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | ||||
| cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| type ShardStoreLockReqBuilder struct { | type ShardStoreLockReqBuilder struct { | ||||
| @@ -15,24 +15,24 @@ type ShardStoreLockReqBuilder struct { | |||||
| func (b *LockRequestBuilder) Shard() *ShardStoreLockReqBuilder { | func (b *LockRequestBuilder) Shard() *ShardStoreLockReqBuilder { | ||||
| return &ShardStoreLockReqBuilder{LockRequestBuilder: b} | return &ShardStoreLockReqBuilder{LockRequestBuilder: b} | ||||
| } | } | ||||
| func (b *ShardStoreLockReqBuilder) Buzy(stgID cortypes.StorageID) *ShardStoreLockReqBuilder { | |||||
| b.locks = append(b.locks, distlock.Lock{ | |||||
| Path: b.makePath(stgID), | |||||
| func (b *ShardStoreLockReqBuilder) Buzy(spaceID clitypes.UserSpaceID) *ShardStoreLockReqBuilder { | |||||
| b.locks = append(b.locks, types.Lock{ | |||||
| Path: b.makePath(spaceID), | |||||
| Name: lockprovider.ShardStoreBuzyLock, | Name: lockprovider.ShardStoreBuzyLock, | ||||
| Target: *lockprovider.NewStringLockTarget(), | |||||
| Target: lockprovider.NewEmptyTarget(), | |||||
| }) | }) | ||||
| return b | return b | ||||
| } | } | ||||
| func (b *ShardStoreLockReqBuilder) GC(stgID cortypes.StorageID) *ShardStoreLockReqBuilder { | |||||
| b.locks = append(b.locks, distlock.Lock{ | |||||
| Path: b.makePath(stgID), | |||||
| func (b *ShardStoreLockReqBuilder) GC(spaceID clitypes.UserSpaceID) *ShardStoreLockReqBuilder { | |||||
| b.locks = append(b.locks, types.Lock{ | |||||
| Path: b.makePath(spaceID), | |||||
| Name: lockprovider.ShardStoreGCLock, | Name: lockprovider.ShardStoreGCLock, | ||||
| Target: *lockprovider.NewStringLockTarget(), | |||||
| Target: lockprovider.NewEmptyTarget(), | |||||
| }) | }) | ||||
| return b | return b | ||||
| } | } | ||||
| func (b *ShardStoreLockReqBuilder) makePath(hubID cortypes.StorageID) []string { | |||||
| func (b *ShardStoreLockReqBuilder) makePath(hubID clitypes.UserSpaceID) []string { | |||||
| return []string{lockprovider.ShardStoreLockPathPrefix, strconv.FormatInt(int64(hubID), 10)} | return []string{lockprovider.ShardStoreLockPathPrefix, strconv.FormatInt(int64(hubID), 10)} | ||||
| } | } | ||||
| @@ -1,39 +0,0 @@ | |||||
| package reqbuilder | |||||
| import ( | |||||
| "strconv" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | |||||
| cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" | |||||
| ) | |||||
| type StorageLockReqBuilder struct { | |||||
| *LockRequestBuilder | |||||
| } | |||||
| func (b *LockRequestBuilder) Storage() *StorageLockReqBuilder { | |||||
| return &StorageLockReqBuilder{LockRequestBuilder: b} | |||||
| } | |||||
| func (b *StorageLockReqBuilder) Buzy(storageID cortypes.StorageID) *StorageLockReqBuilder { | |||||
| b.locks = append(b.locks, distlock.Lock{ | |||||
| Path: b.makePath(storageID), | |||||
| Name: lockprovider.StorageBuzyLock, | |||||
| Target: *lockprovider.NewStringLockTarget(), | |||||
| }) | |||||
| return b | |||||
| } | |||||
| func (b *StorageLockReqBuilder) GC(storageID cortypes.StorageID) *StorageLockReqBuilder { | |||||
| b.locks = append(b.locks, distlock.Lock{ | |||||
| Path: b.makePath(storageID), | |||||
| Name: lockprovider.StorageGCLock, | |||||
| Target: *lockprovider.NewStringLockTarget(), | |||||
| }) | |||||
| return b | |||||
| } | |||||
| func (b *StorageLockReqBuilder) makePath(storageID cortypes.StorageID) []string { | |||||
| return []string{lockprovider.StorageLockPathPrefix, strconv.FormatInt(int64(storageID), 10)} | |||||
| } | |||||
| @@ -1,62 +1,194 @@ | |||||
| package distlock | package distlock | ||||
| import ( | import ( | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| "context" | |||||
| "fmt" | |||||
| "sync" | |||||
| "time" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/future" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/trie" | "gitlink.org.cn/cloudream/common/pkgs/trie" | ||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/lockprovider" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types" | |||||
| ) | ) | ||||
| type Service = distlock.Service | |||||
| type AcquireOption struct { | |||||
| Timeout time.Duration | |||||
| } | |||||
| type AcquireOptionFn func(opt *AcquireOption) | |||||
| func WithTimeout(timeout time.Duration) AcquireOptionFn { | |||||
| return func(opt *AcquireOption) { | |||||
| opt.Timeout = timeout | |||||
| } | |||||
| } | |||||
| type Service struct { | |||||
| lock *sync.Mutex | |||||
| provdersTrie *trie.Trie[types.LockProvider] | |||||
| acquirings []*acquireInfo | |||||
| nextReqID int64 | |||||
| } | |||||
| func NewService() *Service { | |||||
| svc := &Service{ | |||||
| lock: &sync.Mutex{}, | |||||
| provdersTrie: trie.NewTrie[types.LockProvider](), | |||||
| } | |||||
| type Mutex = distlock.Mutex | |||||
| svc.provdersTrie.Create([]any{lockprovider.ShardStoreLockPathPrefix, trie.WORD_ANY}).Value = lockprovider.NewShardStoreLock() | |||||
| return svc | |||||
| } | |||||
| func NewService(cfg *distlock.Config) (*distlock.Service, error) { | |||||
| srv, err := distlock.NewService(cfg, initProviders()) | |||||
| type acquireInfo struct { | |||||
| Request types.LockRequest | |||||
| Callback *future.SetValueFuture[types.RequestID] | |||||
| LastErr error | |||||
| } | |||||
| func (svc *Service) Acquire(req types.LockRequest, opts ...AcquireOptionFn) (*Mutex, error) { | |||||
| var opt = AcquireOption{ | |||||
| Timeout: time.Second * 10, | |||||
| } | |||||
| for _, fn := range opts { | |||||
| fn(&opt) | |||||
| } | |||||
| ctx := context.Background() | |||||
| if opt.Timeout != 0 { | |||||
| var cancel func() | |||||
| ctx, cancel = context.WithTimeout(ctx, opt.Timeout) | |||||
| defer cancel() | |||||
| } | |||||
| // 就地检测锁是否可用 | |||||
| svc.lock.Lock() | |||||
| defer svc.lock.Unlock() | |||||
| reqID, err := svc.tryAcquireOne(req) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| return srv, nil | |||||
| if reqID != "" { | |||||
| return &Mutex{ | |||||
| svc: svc, | |||||
| lockReq: req, | |||||
| lockReqID: reqID, | |||||
| }, nil | |||||
| } | |||||
| // 就地检测失败,那么就需要异步等待锁可用 | |||||
| info := &acquireInfo{ | |||||
| Request: req, | |||||
| Callback: future.NewSetValue[types.RequestID](), | |||||
| } | |||||
| svc.acquirings = append(svc.acquirings, info) | |||||
| // 等待的时候不加锁 | |||||
| svc.lock.Unlock() | |||||
| reqID, err = info.Callback.Wait(ctx) | |||||
| svc.lock.Lock() | |||||
| if err == nil { | |||||
| return &Mutex{ | |||||
| svc: svc, | |||||
| lockReq: req, | |||||
| lockReqID: reqID, | |||||
| }, nil | |||||
| } | |||||
| if err != future.ErrCanceled { | |||||
| lo2.Remove(svc.acquirings, info) | |||||
| return nil, err | |||||
| } | |||||
| // 如果第一次等待是超时错误,那么在锁里再尝试获取一次结果 | |||||
| reqID, err = info.Callback.TryGetValue() | |||||
| if err == nil { | |||||
| return &Mutex{ | |||||
| svc: svc, | |||||
| lockReq: req, | |||||
| lockReqID: reqID, | |||||
| }, nil | |||||
| } | |||||
| lo2.Remove(svc.acquirings, info) | |||||
| return nil, err | |||||
| } | |||||
| func (s *Service) BeginReentrant() *Reentrant { | |||||
| return &Reentrant{ | |||||
| svc: s, | |||||
| } | |||||
| } | } | ||||
| func initProviders() []distlock.PathProvider { | |||||
| var provs []distlock.PathProvider | |||||
| func (s *Service) release(reqID types.RequestID, req types.LockRequest) { | |||||
| s.lock.Lock() | |||||
| defer s.lock.Unlock() | |||||
| provs = append(provs, initMetadataLockProviders()...) | |||||
| s.releaseRequest(reqID, req) | |||||
| s.tryAcquirings() | |||||
| } | |||||
| func (a *Service) tryAcquirings() { | |||||
| for i := 0; i < len(a.acquirings); i++ { | |||||
| req := a.acquirings[i] | |||||
| provs = append(provs, initShardLockProviders()...) | |||||
| reqID, err := a.tryAcquireOne(req.Request) | |||||
| if err != nil { | |||||
| req.LastErr = err | |||||
| continue | |||||
| } | |||||
| provs = append(provs, initStorageLockProviders()...) | |||||
| req.Callback.SetValue(reqID) | |||||
| a.acquirings[i] = nil | |||||
| } | |||||
| return provs | |||||
| a.acquirings = lo2.RemoveAllDefault(a.acquirings) | |||||
| } | } | ||||
| func initMetadataLockProviders() []distlock.PathProvider { | |||||
| return []distlock.PathProvider{ | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Hub"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Storage"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "User"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "UserBucket"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "UserHub"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "UserStorage"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Bucket"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Object"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Package"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "ObjectRep"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "ObjectBlock"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Cache"), | |||||
| distlock.NewPathProvider(lockprovider.NewMetadataLock(), lockprovider.MetadataLockPathPrefix, "Location"), | |||||
| func (s *Service) tryAcquireOne(req types.LockRequest) (types.RequestID, error) { | |||||
| err := s.testOneRequest(req) | |||||
| if err != nil { | |||||
| return "", err | |||||
| } | } | ||||
| reqID := types.RequestID(fmt.Sprintf("%d", s.nextReqID)) | |||||
| s.nextReqID++ | |||||
| s.applyRequest(reqID, req) | |||||
| return reqID, nil | |||||
| } | |||||
| func (s *Service) testOneRequest(req types.LockRequest) error { | |||||
| for _, lock := range req.Locks { | |||||
| n, ok := s.provdersTrie.WalkEnd(lock.Path) | |||||
| if !ok || n.Value == nil { | |||||
| return fmt.Errorf("lock provider not found for path %v", lock.Path) | |||||
| } | |||||
| err := n.Value.CanLock(lock) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | } | ||||
| func initShardLockProviders() []distlock.PathProvider { | |||||
| return []distlock.PathProvider{ | |||||
| distlock.NewPathProvider(lockprovider.NewShardStoreLock(), lockprovider.ShardStoreLockPathPrefix, trie.WORD_ANY), | |||||
| func (s *Service) applyRequest(reqID types.RequestID, req types.LockRequest) { | |||||
| for _, lock := range req.Locks { | |||||
| p, _ := s.provdersTrie.WalkEnd(lock.Path) | |||||
| p.Value.Lock(reqID, lock) | |||||
| } | } | ||||
| } | } | ||||
| func initStorageLockProviders() []distlock.PathProvider { | |||||
| return []distlock.PathProvider{ | |||||
| distlock.NewPathProvider(lockprovider.NewStorageLock(), lockprovider.StorageLockPathPrefix, trie.WORD_ANY), | |||||
| func (s *Service) releaseRequest(reqID types.RequestID, req types.LockRequest) { | |||||
| for _, lock := range req.Locks { | |||||
| p, _ := s.provdersTrie.WalkEnd(lock.Path) | |||||
| p.Value.Unlock(reqID, lock) | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,60 @@ | |||||
| package types | |||||
| import ( | |||||
| "fmt" | |||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | |||||
| ) | |||||
| type RequestID string | |||||
| type Lock struct { | |||||
| Path []string // 锁路径,存储的是路径的每一部分 | |||||
| Name string // 锁名 | |||||
| Target LockTarget // 锁对象,由具体的Provider去解析 | |||||
| } | |||||
| func (b *Lock) Equals(other Lock) bool { | |||||
| return lo2.ArrayEquals(b.Path, other.Path) && b.Name == other.Name && b.Target.Equals(other.Target) | |||||
| } | |||||
| type LockTarget interface { | |||||
| Equals(other LockTarget) bool | |||||
| } | |||||
| type LockRequest struct { | |||||
| Reason string | |||||
| Locks []Lock | |||||
| } | |||||
| func (b *LockRequest) Add(lock Lock) { | |||||
| b.Locks = append(b.Locks, lock) | |||||
| } | |||||
| type LockProvider interface { | |||||
| // CanLock 判断这个锁能否锁定成功 | |||||
| CanLock(lock Lock) error | |||||
| // Lock 锁定。由于同一个锁请求内的锁不检查冲突,因此这个函数必须支持有冲突的锁进行锁定。 | |||||
| Lock(reqID RequestID, lock Lock) error | |||||
| // 解锁 | |||||
| Unlock(reqID RequestID, lock Lock) error | |||||
| // Clear 清除内部所有状态 | |||||
| Clear() | |||||
| } | |||||
| type LockTargetBusyError struct { | |||||
| lockName string | |||||
| } | |||||
| func (e *LockTargetBusyError) Error() string { | |||||
| return fmt.Sprintf("the lock object is locked by %s", e.lockName) | |||||
| } | |||||
| func NewLockTargetBusyError(lockName string) *LockTargetBusyError { | |||||
| return &LockTargetBusyError{ | |||||
| lockName: lockName, | |||||
| } | |||||
| } | |||||
| @@ -17,15 +17,6 @@ | |||||
| "password": "123456", | "password": "123456", | ||||
| "vhost": "/" | "vhost": "/" | ||||
| }, | }, | ||||
| "ipfs": null, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a client" | |||||
| }, | |||||
| "connectivity": { | "connectivity": { | ||||
| "testInterval": 300 | "testInterval": 300 | ||||
| }, | }, | ||||
| @@ -25,14 +25,6 @@ | |||||
| "ipfs": { | "ipfs": { | ||||
| "address": "127.0.0.1:5001" | "address": "127.0.0.1:5001" | ||||
| }, | }, | ||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a agent" | |||||
| }, | |||||
| "connectivity": { | "connectivity": { | ||||
| "testInterval": 300 | "testInterval": 300 | ||||
| }, | }, | ||||
| @@ -1,30 +0,0 @@ | |||||
| { | |||||
| "ecFileSizeThreshold": 104857600, | |||||
| "nodeUnavailableSeconds": 300, | |||||
| "logger": { | |||||
| "output": "file", | |||||
| "outputFileName": "scanner", | |||||
| "outputDirectory": "log", | |||||
| "level": "debug" | |||||
| }, | |||||
| "db": { | |||||
| "address": "127.0.0.1:3306", | |||||
| "account": "root", | |||||
| "password": "123456", | |||||
| "databaseName": "cloudream" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "cloudream", | |||||
| "password": "123456", | |||||
| "vhost": "/" | |||||
| }, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a scanner" | |||||
| } | |||||
| } | |||||
| @@ -17,15 +17,6 @@ | |||||
| "password": "123456", | "password": "123456", | ||||
| "vhost": "/" | "vhost": "/" | ||||
| }, | }, | ||||
| "ipfs": null, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a client" | |||||
| }, | |||||
| "connectivity": { | "connectivity": { | ||||
| "testInterval": 300 | "testInterval": 300 | ||||
| }, | }, | ||||
| @@ -22,17 +22,6 @@ | |||||
| "password": "123456", | "password": "123456", | ||||
| "vhost": "/" | "vhost": "/" | ||||
| }, | }, | ||||
| "ipfs": { | |||||
| "address": "127.0.0.1:5001" | |||||
| }, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a agent" | |||||
| }, | |||||
| "connectivity": { | "connectivity": { | ||||
| "testInterval": 300 | "testInterval": 300 | ||||
| }, | }, | ||||
| @@ -1,30 +0,0 @@ | |||||
| { | |||||
| "ecFileSizeThreshold": 104857600, | |||||
| "nodeUnavailableSeconds": 300, | |||||
| "logger": { | |||||
| "output": "file", | |||||
| "outputFileName": "scanner", | |||||
| "outputDirectory": "log", | |||||
| "level": "debug" | |||||
| }, | |||||
| "db": { | |||||
| "address": "127.0.0.1:3306", | |||||
| "account": "root", | |||||
| "password": "123456", | |||||
| "databaseName": "cloudream" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "cloudream", | |||||
| "password": "123456", | |||||
| "vhost": "/" | |||||
| }, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a scanner" | |||||
| } | |||||
| } | |||||
| @@ -16,7 +16,6 @@ import ( | |||||
| "gitlink.org.cn/cloudream/common/pkgs/mq" | "gitlink.org.cn/cloudream/common/pkgs/mq" | ||||
| 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/models/datamap" | "gitlink.org.cn/cloudream/jcs-pub/common/models/datamap" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock" | |||||
| hubrpc "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/grpc/hub" | hubrpc "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/grpc/hub" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/sysevent" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/sysevent" | ||||
| cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" | cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" | ||||
| @@ -130,12 +129,6 @@ func serve(configPath string, httpAddr string) { | |||||
| // }) | // }) | ||||
| // go serveAccessStat(acStat) | // go serveAccessStat(acStat) | ||||
| // 初始化分布式锁服务 | |||||
| distlock, err := distlock.NewService(&config.Cfg().DistLock) | |||||
| if err != nil { | |||||
| logger.Fatalf("new ipfs failed, err: %s", err.Error()) | |||||
| } | |||||
| // 初始化系统事件发布器 | // 初始化系统事件发布器 | ||||
| evtPub, err := sysevent.NewPublisher(sysevent.ConfigFromMQConfig(config.Cfg().RabbitMQ), &datamap.SourceHub{ | evtPub, err := sysevent.NewPublisher(sysevent.ConfigFromMQConfig(config.Cfg().RabbitMQ), &datamap.SourceHub{ | ||||
| HubID: hubCfg.Hub.HubID, | HubID: hubCfg.Hub.HubID, | ||||
| @@ -173,8 +166,6 @@ func serve(configPath string, httpAddr string) { | |||||
| hubrpc.RegisterHubServer(s, grpcsvc.NewService(&worker, stgPool)) | hubrpc.RegisterHubServer(s, grpcsvc.NewService(&worker, stgPool)) | ||||
| go serveGRPC(s, lis) | go serveGRPC(s, lis) | ||||
| go serveDistLock(distlock) | |||||
| foever := make(chan struct{}) | foever := make(chan struct{}) | ||||
| <-foever | <-foever | ||||
| } | } | ||||
| @@ -312,42 +303,3 @@ func serveHTTP(server *http.Server) { | |||||
| // TODO 仅简单结束了程序 | // TODO 仅简单结束了程序 | ||||
| os.Exit(1) | os.Exit(1) | ||||
| } | } | ||||
| func serveDistLock(svc *distlock.Service) { | |||||
| logger.Info("start serving distlock") | |||||
| err := svc.Serve() | |||||
| if err != nil { | |||||
| logger.Errorf("distlock stopped with error: %s", err.Error()) | |||||
| } | |||||
| logger.Info("distlock stopped") | |||||
| // TODO 仅简单结束了程序 | |||||
| os.Exit(1) | |||||
| } | |||||
| // func serveAccessStat(svc *accessstat.AccessStat) { | |||||
| // logger.Info("start serving access stat") | |||||
| // ch := svc.Start() | |||||
| // loop: | |||||
| // for { | |||||
| // val, err := ch.Receive() | |||||
| // if err != nil { | |||||
| // logger.Errorf("access stat stopped with error: %v", err) | |||||
| // break | |||||
| // } | |||||
| // switch val := val.(type) { | |||||
| // case error: | |||||
| // logger.Errorf("access stat stopped with error: %v", val) | |||||
| // break loop | |||||
| // } | |||||
| // } | |||||
| // logger.Info("access stat stopped") | |||||
| // // TODO 仅简单结束了程序 | |||||
| // os.Exit(1) | |||||
| // } | |||||
| @@ -1,7 +1,6 @@ | |||||
| package config | package config | ||||
| import ( | import ( | ||||
| "gitlink.org.cn/cloudream/common/pkgs/distlock" | |||||
| log "gitlink.org.cn/cloudream/common/pkgs/logger" | log "gitlink.org.cn/cloudream/common/pkgs/logger" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/mq" | "gitlink.org.cn/cloudream/common/pkgs/mq" | ||||
| c "gitlink.org.cn/cloudream/common/utils/config" | c "gitlink.org.cn/cloudream/common/utils/config" | ||||
| @@ -17,7 +16,6 @@ type Config struct { | |||||
| GRPC *grpc.Config `json:"grpc"` | GRPC *grpc.Config `json:"grpc"` | ||||
| Logger log.Config `json:"logger"` | Logger log.Config `json:"logger"` | ||||
| RabbitMQ mq.Config `json:"rabbitMQ"` | RabbitMQ mq.Config `json:"rabbitMQ"` | ||||
| DistLock distlock.Config `json:"distlock"` | |||||
| Connectivity connectivity.Config `json:"connectivity"` | Connectivity connectivity.Config `json:"connectivity"` | ||||
| } | } | ||||