package ticktock import ( "fmt" "time" "gitlink.org.cn/cloudream/common/pkgs/logger" "gitlink.org.cn/cloudream/common/utils/reflect2" "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types" "gitlink.org.cn/cloudream/jcs-pub/client/internal/publock/reqbuilder" ) type UserSpaceGC struct { } func (j *UserSpaceGC) Name() string { return reflect2.TypeNameOf[UserSpaceGC]() } // Execute 执行垃圾回收操作。 func (j *UserSpaceGC) Execute(t *TickTock) { log := logger.WithType[UserSpaceGC]("Event") startTime := time.Now() log.Infof("job start") defer func() { log.Infof("job end, time: %v", time.Since(startTime)) }() spaceIDs, err := t.db.UserSpace().GetAllIDs(t.db.DefCtx()) if err != nil { log.Warnf("getting user space ids: %v", err) return } for _, spaceID := range spaceIDs { detail := t.spaceMeta.Get(spaceID) if detail == nil { continue } j.gcOne(t, detail) } } func (j *UserSpaceGC) gcOne(t *TickTock, space *jcstypes.UserSpaceDetail) { log := logger.WithType[UserSpaceGC]("Event") mutex, err := reqbuilder.NewBuilder().UserSpace().GC(space.UserSpace.UserSpaceID).MutexLock(t.pubLock) if err != nil { log.Warnf("acquire lock: %v", err) return } 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 *jcstypes.UserSpaceDetail) error { db2 := t.db // 收集需要进行垃圾回收的文件哈希值 var allFileHashes []jcstypes.FileHash err := db2.DoTx(func(tx db.SQLContext) error { blocks, err := db2.ObjectBlock().GetByUserSpaceID(tx, space.UserSpace.UserSpaceID) if err != nil { return fmt.Errorf("getting object blocks by hub id: %w", err) } for _, c := range blocks { allFileHashes = append(allFileHashes, c.FileHash) } objs, err := db2.PinnedObject().GetObjectsByUserSpaceID(tx, space.UserSpace.UserSpaceID) if err != nil { return fmt.Errorf("getting pinned objects by hub id: %w", err) } for _, o := range objs { allFileHashes = append(allFileHashes, o.FileHash) } return nil }) if err != nil { return err } store, err := t.stgPool.GetShardStore(space) if err != nil { return fmt.Errorf("getting shard store: %w", err) } err = store.GC(allFileHashes) if err != nil { return fmt.Errorf("gc shard store: %w", err) } return nil } func (j *UserSpaceGC) gcTemps(t *TickTock, space *jcstypes.UserSpaceDetail) error { store, err := t.stgPool.GetBaseStore(space) if err != nil { return fmt.Errorf("getting base store: %w", err) } store.CleanTemps() return nil }