JCS-pub/client/internal/ticktock/change_redundancy.go

188 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

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

package 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/distlock/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.Debugf("job start")
defer func() {
log.Debugf("job end, time: %v", time.Since(startTime))
}()
ctx := &changeRedundancyContext{
ticktock: t,
allUserSpaces: make(map[clitypes.UserSpaceID]*userSpaceLoadInfo),
}
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] = &userSpaceLoadInfo{
UserSpace: space,
}
}
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
}
}
}
}
type changeRedundancyContext struct {
ticktock *TickTock
allUserSpaces map[clitypes.UserSpaceID]*userSpaceLoadInfo
mostBlockStgIDs []clitypes.UserSpaceID
}
type userSpaceLoadInfo 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.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 {
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
}