|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- 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"
- 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/pkgs/publock/reqbuilder"
- )
-
- const (
- BatchGetPackageDetailCount = 100
- BatchGetObjectDetailCount = 1000
- )
-
- type ChangeRedundancy struct {
- }
-
- func (j *ChangeRedundancy) Name() string {
- return reflect2.TypeNameOf[ChangeRedundancy]()
- }
-
- func (j *ChangeRedundancy) Execute(t *TickTock) {
- log := logger.WithType[ChangeRedundancy]("TickTock")
- startTime := time.Now()
- log.Infof("job start")
- defer func() {
- log.Infof("job end, time: %v", time.Since(startTime))
- }()
-
- ctx := &changeRedundancyContext{
- ticktock: t,
- allUserSpaces: make(map[clitypes.UserSpaceID]*userSpaceUsageInfo),
- }
-
- spaceIDs, err := t.db.UserSpace().GetAllIDs(t.db.DefCtx())
- if err != nil {
- log.Warnf("get user space ids: %v", err)
- return
- }
-
- spaces := t.spaceMeta.GetMany(spaceIDs)
- for _, space := range spaces {
- if space == nil {
- continue
- }
-
- ctx.allUserSpaces[space.UserSpace.UserSpaceID] = &userSpaceUsageInfo{
- UserSpace: space,
- }
- }
- if len(ctx.allUserSpaces) == 0 {
- log.Warnf("no user space found")
- return
- }
-
- lastPkgID := clitypes.PackageID(0)
- for {
- pkgs, err := db.DoTx21(t.db, t.db.Package().BatchGetDetailPaged, lastPkgID, BatchGetPackageDetailCount)
- if err != nil {
- log.Warnf("get package details: %v", err)
- return
- }
- if len(pkgs) == 0 {
- break
- }
- lastPkgID = pkgs[len(pkgs)-1].Package.PackageID
-
- for _, p := range pkgs {
- err := j.changeOne(ctx, p)
- if err != nil {
- log.Warnf("change redundancy: %v", err)
- return
- }
- }
-
- // 如果执行超过两个小时,则停止
- if time.Since(startTime) > time.Hour*2 {
- break
- }
- }
- }
-
- type changeRedundancyContext struct {
- ticktock *TickTock
- allUserSpaces map[clitypes.UserSpaceID]*userSpaceUsageInfo
- mostBlockStgIDs []clitypes.UserSpaceID
- }
-
- type userSpaceUsageInfo struct {
- UserSpace *clitypes.UserSpaceDetail
- AccessAmount float64
- }
-
- func (j *ChangeRedundancy) changeOne(ctx *changeRedundancyContext, pkg clitypes.PackageDetail) error {
- log := logger.WithType[ChangeRedundancy]("TickTock")
- db2 := ctx.ticktock.db
-
- // allUserSpaces是复用的,所以需要先清空
- for _, space := range ctx.allUserSpaces {
- space.AccessAmount = 0
- }
-
- pkgAccessStats, err := db2.PackageAccessStat().GetByPackageID(db2.DefCtx(), pkg.Package.PackageID)
- if err != nil {
- return fmt.Errorf("get package access stats: %w", err)
- }
-
- for _, stat := range pkgAccessStats {
- info, ok := ctx.allUserSpaces[stat.UserSpaceID]
- if !ok {
- continue
- }
- info.AccessAmount = stat.Amount
- }
-
- lastObjID := clitypes.ObjectID(0)
- for {
- objs, err := db.DoTx31(db2, db2.Object().BatchGetDetailsPaged, pkg.Package.PackageID, lastObjID, BatchGetObjectDetailCount)
- if err != nil {
- return fmt.Errorf("get object details: %w", err)
- }
- if len(objs) == 0 {
- break
- }
- lastObjID = objs[len(objs)-1].Object.ObjectID
-
- reen := ctx.ticktock.pubLock.BeginReentrant()
-
- var allUpdatings []db.UpdatingObjectRedundancy
- var allSysEvts []datamap.SysEventBody
-
- ctx.mostBlockStgIDs = j.summaryRepObjectBlockUserSpaces(ctx, objs, 2)
-
- var willShrinks []clitypes.ObjectDetail
-
- for _, obj := range objs {
- newRed, selectedSpaces := j.chooseRedundancy(ctx, obj)
- // 冗余策略不需要调整,就检查是否需要收缩
- if newRed == nil {
- willShrinks = append(willShrinks, obj)
- continue
- }
-
- reqBlder := reqbuilder.NewBuilder()
- for _, space := range selectedSpaces {
- reqBlder.UserSpace().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 {
- allUpdatings = append(allUpdatings, *updating)
- }
- if evt != nil {
- allSysEvts = append(allSysEvts, evt)
- }
- if err != nil {
- log.WithField("ObjectID", obj.Object.ObjectID).Warnf("%s, its redundancy wont be changed", err.Error())
- continue
- }
- }
-
- udpatings, sysEvts, err := j.doRedundancyShrink(ctx, pkg, willShrinks, reen)
- if err != nil {
- log.Warnf("redundancy shrink: %s", err.Error())
- } else {
- allUpdatings = append(allUpdatings, udpatings...)
- allSysEvts = append(allSysEvts, sysEvts...)
- }
-
- if len(allUpdatings) > 0 {
- err := db.DoTx10(db2, db2.Object().BatchUpdateRedundancy, allUpdatings)
- if err != nil {
- reen.Unlock()
- log.Warnf("update object redundancy: %s", err.Error())
- return err
- }
- }
- reen.Unlock()
-
- for _, e := range allSysEvts {
- ctx.ticktock.evtPub.Publish(e)
- }
- }
-
- return nil
- }
|