Browse Source

增加Object的访问量统计

gitlink
Sydonian 1 year ago
parent
commit
e2fa2a507c
21 changed files with 325 additions and 180 deletions
  1. +1
    -1
      agent/internal/task/cache_move_package.go
  2. +1
    -1
      agent/internal/task/storage_load_package.go
  3. +4
    -4
      agent/internal/task/task.go
  4. +9
    -9
      agent/main.go
  5. +1
    -1
      client/internal/cmdline/getp.go
  6. +1
    -1
      client/internal/http/object.go
  7. +10
    -10
      client/internal/services/service.go
  8. +9
    -9
      client/main.go
  9. +9
    -1
      common/assets/scripts/create_database.sql
  10. +72
    -0
      common/pkgs/accessstat/access_stat.go
  11. +1
    -1
      common/pkgs/accessstat/config.go
  12. +7
    -0
      common/pkgs/db/model/model.go
  13. +20
    -0
      common/pkgs/db/object.go
  14. +76
    -0
      common/pkgs/db/object_access_stat.go
  15. +26
    -0
      common/pkgs/db/package.go
  16. +4
    -4
      common/pkgs/db/package_access_stat.go
  17. +27
    -0
      common/pkgs/mq/coordinator/object.go
  18. +0
    -33
      common/pkgs/mq/coordinator/package.go
  19. +0
    -98
      common/pkgs/package_stat/package_stat.go
  20. +5
    -0
      coordinator/internal/mq/object.go
  21. +42
    -7
      coordinator/internal/mq/package.go

+ 1
- 1
agent/internal/task/cache_move_package.go View File

@@ -77,7 +77,7 @@ func (t *CacheMovePackage) do(ctx TaskContext) error {
return fmt.Errorf("creating ipfs file: %w", err)
}

ctx.packageStat.AddAccessCounter(t.packageID, *stgglb.Local.NodeID, 1)
ctx.accessStat.AddAccessCounter(obj.Object.ObjectID, t.packageID, *stgglb.Local.NodeID, 1)
}

_, err = coorCli.CachePackageMoved(coormq.NewCachePackageMoved(t.packageID, *stgglb.Local.NodeID))


+ 1
- 1
agent/internal/task/storage_load_package.go View File

@@ -99,7 +99,7 @@ func (t *StorageLoadPackage) do(task *task.Task[TaskContext], ctx TaskContext) e
if err != nil {
return err
}
ctx.packageStat.AddAccessCounter(t.packageID, *stgglb.Local.NodeID, 1)
ctx.accessStat.AddAccessCounter(obj.Object.ObjectID, t.packageID, *stgglb.Local.NodeID, 1)
}

_, err = coorCli.StoragePackageLoaded(coormq.NewStoragePackageLoaded(t.userID, t.storageID, t.packageID, t.pinnedBlocks))


+ 4
- 4
agent/internal/task/task.go View File

@@ -3,16 +3,16 @@ package task
import (
"gitlink.org.cn/cloudream/common/pkgs/distlock"
"gitlink.org.cn/cloudream/common/pkgs/task"
"gitlink.org.cn/cloudream/storage/common/pkgs/accessstat"
"gitlink.org.cn/cloudream/storage/common/pkgs/connectivity"
"gitlink.org.cn/cloudream/storage/common/pkgs/downloader"
packagestat "gitlink.org.cn/cloudream/storage/common/pkgs/package_stat"
)

type TaskContext struct {
distlock *distlock.Service
connectivity *connectivity.Collector
downloader *downloader.Downloader
packageStat *packagestat.PackageStat
accessStat *accessstat.AccessStat
}

// 需要在Task结束后主动调用,completing函数将在Manager加锁期间被调用,
@@ -27,11 +27,11 @@ type Task = task.Task[TaskContext]

type CompleteOption = task.CompleteOption

func NewManager(distlock *distlock.Service, connectivity *connectivity.Collector, downloader *downloader.Downloader, packageStat *packagestat.PackageStat) Manager {
func NewManager(distlock *distlock.Service, connectivity *connectivity.Collector, downloader *downloader.Downloader, accessStat *accessstat.AccessStat) Manager {
return task.NewManager(TaskContext{
distlock: distlock,
connectivity: connectivity,
downloader: downloader,
packageStat: packageStat,
accessStat: accessStat,
})
}

+ 9
- 9
agent/main.go View File

@@ -12,11 +12,11 @@ import (
"gitlink.org.cn/cloudream/storage/agent/internal/config"
"gitlink.org.cn/cloudream/storage/agent/internal/task"
stgglb "gitlink.org.cn/cloudream/storage/common/globals"
"gitlink.org.cn/cloudream/storage/common/pkgs/accessstat"
"gitlink.org.cn/cloudream/storage/common/pkgs/connectivity"
"gitlink.org.cn/cloudream/storage/common/pkgs/distlock"
"gitlink.org.cn/cloudream/storage/common/pkgs/downloader"
agtrpc "gitlink.org.cn/cloudream/storage/common/pkgs/grpc/agent"
packagestat "gitlink.org.cn/cloudream/storage/common/pkgs/package_stat"

"google.golang.org/grpc"

@@ -86,11 +86,11 @@ func main() {
})
conCol.CollectInPlace()

pkgStat := packagestat.NewPackageStat(packagestat.Config{
acStat := accessstat.NewAccessStat(accessstat.Config{
// TODO 考虑放到配置里
ReportInterval: time.Second * 10,
})
go servePackageStat(pkgStat)
go serveAccessStat(acStat)

distlock, err := distlock.NewService(&config.Cfg().DistLock)
if err != nil {
@@ -101,7 +101,7 @@ func main() {

dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol)

taskMgr := task.NewManager(distlock, &conCol, &dlder, pkgStat)
taskMgr := task.NewManager(distlock, &conCol, &dlder, acStat)

// 启动命令服务器
// TODO 需要设计AgentID持久化机制
@@ -175,25 +175,25 @@ func serveDistLock(svc *distlock.Service) {
os.Exit(1)
}

func servePackageStat(svc *packagestat.PackageStat) {
logger.Info("start serving package stat")
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("package stat stopped with error: %v", err)
logger.Errorf("access stat stopped with error: %v", err)
break
}

switch val := val.(type) {
case error:
logger.Errorf("package stat stopped with error: %v", val)
logger.Errorf("access stat stopped with error: %v", val)
break loop
}
}
logger.Info("package stat stopped")
logger.Info("access stat stopped")

// TODO 仅简单结束了程序
os.Exit(1)


+ 1
- 1
client/internal/cmdline/getp.go View File

@@ -119,7 +119,7 @@ func getpByID(cmdCtx *CommandContext, id cdssdk.PackageID, output string) {
}

if stgglb.Local.NodeID != nil {
cmdCtx.Cmdline.Svc.PackageStat.AddAccessCounter(id, *stgglb.Local.NodeID, 1)
cmdCtx.Cmdline.Svc.AccessStat.AddAccessCounter(objInfo.Object.ObjectID, id, *stgglb.Local.NodeID, 1)
}
return nil
}()


+ 1
- 1
client/internal/http/object.go View File

@@ -131,7 +131,7 @@ func (s *ObjectService) Download(ctx *gin.Context) {

// TODO 当client不在某个代理节点上时如何处理?
if stgglb.Local.NodeID != nil {
s.svc.PackageStat.AddAccessCounter(file.Object.PackageID, *stgglb.Local.NodeID, float64(sendSize)/float64(file.Object.Size))
s.svc.AccessStat.AddAccessCounter(file.Object.ObjectID, file.Object.PackageID, *stgglb.Local.NodeID, float64(sendSize)/float64(file.Object.Size))
}

if err != nil {


+ 10
- 10
client/internal/services/service.go View File

@@ -3,22 +3,22 @@ package services
import (
"gitlink.org.cn/cloudream/common/pkgs/distlock"
"gitlink.org.cn/cloudream/storage/client/internal/task"
"gitlink.org.cn/cloudream/storage/common/pkgs/accessstat"
"gitlink.org.cn/cloudream/storage/common/pkgs/downloader"
packagestat "gitlink.org.cn/cloudream/storage/common/pkgs/package_stat"
)

type Service struct {
DistLock *distlock.Service
TaskMgr *task.Manager
Downloader *downloader.Downloader
PackageStat *packagestat.PackageStat
DistLock *distlock.Service
TaskMgr *task.Manager
Downloader *downloader.Downloader
AccessStat *accessstat.AccessStat
}

func NewService(distlock *distlock.Service, taskMgr *task.Manager, downloader *downloader.Downloader, pkgStat *packagestat.PackageStat) (*Service, error) {
func NewService(distlock *distlock.Service, taskMgr *task.Manager, downloader *downloader.Downloader, accStat *accessstat.AccessStat) (*Service, error) {
return &Service{
DistLock: distlock,
TaskMgr: taskMgr,
Downloader: downloader,
PackageStat: pkgStat,
DistLock: distlock,
TaskMgr: taskMgr,
Downloader: downloader,
AccessStat: accStat,
}, nil
}

+ 9
- 9
client/main.go View File

@@ -14,11 +14,11 @@ import (
"gitlink.org.cn/cloudream/storage/client/internal/services"
"gitlink.org.cn/cloudream/storage/client/internal/task"
stgglb "gitlink.org.cn/cloudream/storage/common/globals"
"gitlink.org.cn/cloudream/storage/common/pkgs/accessstat"
"gitlink.org.cn/cloudream/storage/common/pkgs/connectivity"
"gitlink.org.cn/cloudream/storage/common/pkgs/distlock"
"gitlink.org.cn/cloudream/storage/common/pkgs/downloader"
coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
packagestat "gitlink.org.cn/cloudream/storage/common/pkgs/package_stat"
)

func main() {
@@ -84,17 +84,17 @@ func main() {
}
go serveDistLock(distlockSvc)

pkgStat := packagestat.NewPackageStat(packagestat.Config{
acStat := accessstat.NewAccessStat(accessstat.Config{
// TODO 考虑放到配置里
ReportInterval: time.Second * 10,
})
go servePackageStat(pkgStat)
go serveAccessStat(acStat)

taskMgr := task.NewManager(distlockSvc, &conCol)

dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol)

svc, err := services.NewService(distlockSvc, &taskMgr, &dlder, pkgStat)
svc, err := services.NewService(distlockSvc, &taskMgr, &dlder, acStat)
if err != nil {
logger.Warnf("new services failed, err: %s", err.Error())
os.Exit(1)
@@ -124,25 +124,25 @@ func serveDistLock(svc *distlock.Service) {
os.Exit(1)
}

func servePackageStat(svc *packagestat.PackageStat) {
logger.Info("start serving package stat")
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("package stat stopped with error: %v", err)
logger.Errorf("access stat stopped with error: %v", err)
break
}

switch val := val.(type) {
case error:
logger.Errorf("package stat stopped with error: %v", val)
logger.Errorf("access stat stopped with error: %v", val)
break loop
}
}
logger.Info("package stat stopped")
logger.Info("access stat stopped")

// TODO 仅简单结束了程序
os.Exit(1)


+ 9
- 1
common/assets/scripts/create_database.sql View File

@@ -176,4 +176,12 @@ create table Location (
insert into
Location (LocationID, Name)
values
(1, "Local");
(1, "Local");

create table ObjectAccessStat (
ObjectID int not null comment '对象ID',
NodeID int not null comment '节点ID',
Amount float not null comment '前一日流量的滑动平均值',
Counter float not null comment '本日的流量',
primary key(ObjectID, NodeID)
);

+ 72
- 0
common/pkgs/accessstat/access_stat.go View File

@@ -0,0 +1,72 @@
package accessstat

import (
"fmt"
"sync"
"time"

"gitlink.org.cn/cloudream/common/pkgs/logger"
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
"gitlink.org.cn/cloudream/common/utils/sync2"
stgglb "gitlink.org.cn/cloudream/storage/common/globals"
coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
)

type AccessStatEvent interface{}

type AccessStat struct {
cfg Config
stats []coormq.AddAccessStatEntry
lock sync.Mutex
}

func NewAccessStat(cfg Config) *AccessStat {
return &AccessStat{
cfg: cfg,
}
}

func (p *AccessStat) AddAccessCounter(objID cdssdk.ObjectID, pkgID cdssdk.PackageID, nodeID cdssdk.NodeID, value float64) {
p.lock.Lock()
defer p.lock.Unlock()

p.stats = append(p.stats, coormq.AddAccessStatEntry{
ObjectID: objID,
PackageID: pkgID,
NodeID: nodeID,
Counter: value,
})
}

func (p *AccessStat) Start() *sync2.UnboundChannel[AccessStatEvent] {
ch := sync2.NewUnboundChannel[AccessStatEvent]()

go func() {
coorCli, err := stgglb.CoordinatorMQPool.Acquire()
if err != nil {
ch.Send(fmt.Errorf("new coordinator client: %w", err))
}
defer stgglb.CoordinatorMQPool.Release(coorCli)

ticker := time.NewTicker(p.cfg.ReportInterval)
for {
<-ticker.C

p.lock.Lock()
st := p.stats
p.stats = nil
p.lock.Unlock()

err := coorCli.AddAccessStat(coormq.ReqAddAccessStat(st))
if err != nil {
logger.Errorf("add all package access stat counter: %v", err)

p.lock.Lock()
p.stats = append(p.stats, st...)
p.lock.Unlock()
continue
}
}
}()
return ch
}

common/pkgs/package_stat/config.go → common/pkgs/accessstat/config.go View File

@@ -1,4 +1,4 @@
package packagestat
package accessstat

import "time"


+ 7
- 0
common/pkgs/db/model/model.go View File

@@ -107,3 +107,10 @@ type PackageAccessStat struct {
Amount float64 `db:"Amount" json:"Amount"` // 前一日的读取量的滑动平均值
Counter float64 `db:"Counter" json:"counter"` // 当日的读取量
}

type ObjectAccessStat struct {
ObjectID cdssdk.ObjectID `db:"ObjectID" json:"objectID"`
NodeID cdssdk.NodeID `db:"NodeID" json:"nodeID"`
Amount float64 `db:"Amount" json:"Amount"` // 前一日的读取量的滑动平均值
Counter float64 `db:"Counter" json:"counter"` // 当日的读取量
}

+ 20
- 0
common/pkgs/db/object.go View File

@@ -28,6 +28,26 @@ func (db *ObjectDB) GetByID(ctx SQLContext, objectID cdssdk.ObjectID) (model.Obj
return ret.ToObject(), err
}

func (db *ObjectDB) BatchTestObjectID(ctx SQLContext, objectIDs []cdssdk.ObjectID) (map[cdssdk.ObjectID]bool, error) {
stmt, args, err := sqlx.In("select ObjectID from Object where ObjectID in (?)", lo.Uniq(objectIDs))
if err != nil {
return nil, err
}

var avaiIDs []cdssdk.ObjectID
err = sqlx.Select(ctx, &avaiIDs, stmt, args...)
if err != nil {
return nil, err
}

avaiIDMap := make(map[cdssdk.ObjectID]bool)
for _, pkgID := range avaiIDs {
avaiIDMap[pkgID] = true
}

return avaiIDMap, nil
}

func (db *ObjectDB) BatchGet(ctx SQLContext, objectIDs []cdssdk.ObjectID) ([]model.Object, error) {
if len(objectIDs) == 0 {
return nil, nil


+ 76
- 0
common/pkgs/db/object_access_stat.go View File

@@ -0,0 +1,76 @@
package db

import (
"github.com/jmoiron/sqlx"
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
"gitlink.org.cn/cloudream/storage/common/pkgs/db/model"
coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
)

type ObjectAccessStatDB struct {
*DB
}

func (db *DB) ObjectAccessStat() *ObjectAccessStatDB {
return &ObjectAccessStatDB{db}
}

func (*ObjectAccessStatDB) Get(ctx SQLContext, objID cdssdk.ObjectID, nodeID cdssdk.NodeID) (model.ObjectAccessStat, error) {
var ret model.ObjectAccessStat
err := sqlx.Get(ctx, &ret, "select * from ObjectAccessStat where ObjectID=? and NodeID=?", objID, nodeID)
return ret, err
}

func (*ObjectAccessStatDB) GetByObjectID(ctx SQLContext, objID cdssdk.ObjectID) ([]model.ObjectAccessStat, error) {
var ret []model.ObjectAccessStat
err := sqlx.Select(ctx, &ret, "select * from ObjectAccessStat where ObjectID=?", objID)
return ret, err
}

func (*ObjectAccessStatDB) BatchAddCounter(ctx SQLContext, entries []coormq.AddAccessStatEntry) error {
sql := "insert into ObjectAccessStat(ObjectID, NodeID, Counter, Amount) " +
"values(:ObjectID, :NodeID, :Counter, 0) as new" +
"on duplicate key update Counter=Counter+new.Counter"
err := BatchNamedExec(ctx, sql, 4, entries, nil)
return err
}

func (*ObjectAccessStatDB) BatchUpdateAmount(ctx SQLContext, objIDs []cdssdk.ObjectID, historyWeight float64) error {
stmt, args, err := sqlx.In("update ObjectAccessStat set Amount=Amount*?+Counter*(1-?), Counter = 0 where ObjectID in (?)", historyWeight, historyWeight, objIDs)
if err != nil {
return err
}

_, err = ctx.Exec(stmt, args...)
return err
}

func (*ObjectAccessStatDB) UpdateAllAmount(ctx SQLContext, historyWeight float64) error {
stmt, args, err := sqlx.In("update ObjectAccessStat set Amount=Amount*?+Counter*(1-?), Counter = 0", historyWeight, historyWeight)
if err != nil {
return err
}

_, err = ctx.Exec(stmt, args...)
return err
}

func (*ObjectAccessStatDB) DeleteByObjectID(ctx SQLContext, objID cdssdk.ObjectID) error {
_, err := ctx.Exec("delete from ObjectAccessStat where ObjectID=?", objID)
return err
}

func (*ObjectAccessStatDB) BatchDeleteByObjectID(ctx SQLContext, objIDs []cdssdk.ObjectID) error {
stmt, args, err := sqlx.In("delete from ObjectAccessStat where ObjectID in (?)", objIDs)
if err != nil {
return err
}

_, err = ctx.Exec(stmt, args...)
return err
}

func (*ObjectAccessStatDB) DeleteInPackage(ctx SQLContext, packageID cdssdk.PackageID) error {
_, err := ctx.Exec("delete ObjectAccessStat from ObjectAccessStat inner join Object on ObjectAccessStat.ObjectID = Object.ObjectID where PackageID = ?", packageID)
return err
}

+ 26
- 0
common/pkgs/db/package.go View File

@@ -6,6 +6,7 @@ import (
"fmt"

"github.com/jmoiron/sqlx"
"github.com/samber/lo"

cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
"gitlink.org.cn/cloudream/storage/common/pkgs/db/model"
@@ -31,6 +32,26 @@ func (db *PackageDB) GetByName(ctx SQLContext, bucketID cdssdk.BucketID, name st
return ret, err
}

func (db *PackageDB) BatchTestPackageID(ctx SQLContext, pkgIDs []cdssdk.PackageID) (map[cdssdk.PackageID]bool, error) {
stmt, args, err := sqlx.In("select PackageID from Package where PackageID in (?)", lo.Uniq(pkgIDs))
if err != nil {
return nil, err
}

var avaiIDs []cdssdk.PackageID
err = sqlx.Select(ctx, &avaiIDs, stmt, args...)
if err != nil {
return nil, err
}

avaiIDMap := make(map[cdssdk.PackageID]bool)
for _, pkgID := range avaiIDs {
avaiIDMap[pkgID] = true
}

return avaiIDMap, nil
}

func (*PackageDB) BatchGetAllPackageIDs(ctx SQLContext, start int, count int) ([]cdssdk.PackageID, error) {
var ret []cdssdk.PackageID
err := sqlx.Select(ctx, &ret, "select PackageID from Package limit ?, ?", start, count)
@@ -136,6 +157,11 @@ func (db *PackageDB) SoftDelete(ctx SQLContext, packageID cdssdk.PackageID) erro
return fmt.Errorf("change package state failed, err: %w", err)
}

err = db.ObjectAccessStat().DeleteInPackage(ctx, packageID)
if err != nil {
return fmt.Errorf("delete from object access stat: %w", err)
}

err = db.ObjectBlock().DeleteInPackage(ctx, packageID)
if err != nil {
return fmt.Errorf("delete from object rep failed, err: %w", err)


+ 4
- 4
common/pkgs/db/package_access_stat.go View File

@@ -27,10 +27,10 @@ func (*PackageAccessStatDB) GetByPackageID(ctx SQLContext, pkgID cdssdk.PackageI
return ret, err
}

func (*PackageAccessStatDB) BatchAddCounter(ctx SQLContext, entries []coormq.AddPackageAccessStatCounterEntry) error {
sql := "insert into PackageAccessStat(PackageID, NodeID, Counter, Amount) " +
"values(:PackageID, :NodeID, :Value, 0)" +
"on duplicate key update Counter=Counter+:Value"
func (*PackageAccessStatDB) BatchAddCounter(ctx SQLContext, entries []coormq.AddAccessStatEntry) error {
sql := "insert into PackageAccessStat(PackageID, NodeID, Counter, Amount)" +
" values(:PackageID, :NodeID, :Counter, 0) as new" +
" on duplicate key update Counter=Counter+new.Counter"
err := BatchNamedExec(ctx, sql, 4, entries, nil)
return err
}


+ 27
- 0
common/pkgs/mq/coordinator/object.go View File

@@ -24,6 +24,8 @@ type ObjectService interface {
DeleteObjects(msg *DeleteObjects) (*DeleteObjectsResp, *mq.CodeMessage)

GetDatabaseAll(msg *GetDatabaseAll) (*GetDatabaseAllResp, *mq.CodeMessage)

AddAccessStat(msg *AddAccessStat)
}

// 查询Package中的所有Object,返回的Objects会按照ObjectID升序
@@ -218,3 +220,28 @@ func RespDeleteObjects() *DeleteObjectsResp {
func (client *Client) DeleteObjects(msg *DeleteObjects) (*DeleteObjectsResp, error) {
return mq.Request(Service.DeleteObjects, client.rabbitCli, msg)
}

// 增加访问计数
var _ = RegisterNoReply(Service.AddAccessStat)

type AddAccessStat struct {
mq.MessageBodyBase
Entries []AddAccessStatEntry `json:"entries"`
}

type AddAccessStatEntry struct {
ObjectID cdssdk.ObjectID `json:"objectID" db:"ObjectID"`
PackageID cdssdk.PackageID `json:"packageID" db:"PackageID"`
NodeID cdssdk.NodeID `json:"nodeID" db:"NodeID"`
Counter float64 `json:"counter" db:"Counter"`
}

func ReqAddAccessStat(entries []AddAccessStatEntry) *AddAccessStat {
return &AddAccessStat{
Entries: entries,
}
}

func (client *Client) AddAccessStat(msg *AddAccessStat) error {
return mq.Send(Service.AddAccessStat, client.rabbitCli, msg)
}

+ 0
- 33
common/pkgs/mq/coordinator/package.go View File

@@ -23,8 +23,6 @@ type PackageService interface {
GetPackageCachedNodes(msg *GetPackageCachedNodes) (*GetPackageCachedNodesResp, *mq.CodeMessage)

GetPackageLoadedNodes(msg *GetPackageLoadedNodes) (*GetPackageLoadedNodesResp, *mq.CodeMessage)

AddPackageAccessStatCounter(msg *AddPackageAccessStatCounter) (*AddPackageAccessStatCounterResp, *mq.CodeMessage)
}

// 获取Package基本信息
@@ -256,34 +254,3 @@ func NewGetPackageLoadedNodesResp(nodeIDs []cdssdk.NodeID) *GetPackageLoadedNode
func (client *Client) GetPackageLoadedNodes(msg *GetPackageLoadedNodes) (*GetPackageLoadedNodesResp, error) {
return mq.Request(Service.GetPackageLoadedNodes, client.rabbitCli, msg)
}

// 更新Pacakge访问统计中的计数值
var _ = Register(Service.AddPackageAccessStatCounter)

type AddPackageAccessStatCounter struct {
mq.MessageBodyBase
Entries []AddPackageAccessStatCounterEntry `json:"entries"`
}
type AddPackageAccessStatCounterEntry struct {
PackageID cdssdk.PackageID `json:"packageID" db:"PackageID"`
NodeID cdssdk.NodeID `json:"nodeID" db:"NodeID"`
Value float64 `json:"value" db:"Value"`
}

type AddPackageAccessStatCounterResp struct {
mq.MessageBodyBase
}

func NewAddPackageAccessStatCounter(entries []AddPackageAccessStatCounterEntry) *AddPackageAccessStatCounter {
return &AddPackageAccessStatCounter{
Entries: entries,
}
}

func NewAddPackageAccessStatCounterResp() *AddPackageAccessStatCounterResp {
return &AddPackageAccessStatCounterResp{}
}

func (client *Client) AddPackageAccessStatCounter(msg *AddPackageAccessStatCounter) (*AddPackageAccessStatCounterResp, error) {
return mq.Request(Service.AddPackageAccessStatCounter, client.rabbitCli, msg)
}

+ 0
- 98
common/pkgs/package_stat/package_stat.go View File

@@ -1,98 +0,0 @@
package packagestat

import (
"fmt"
"sync"
"time"

"gitlink.org.cn/cloudream/common/pkgs/logger"
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
"gitlink.org.cn/cloudream/common/utils/sync2"
stgglb "gitlink.org.cn/cloudream/storage/common/globals"
coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
)

type PackageStatEvent interface{}

type amountKey struct {
PackageID cdssdk.PackageID
NodeID cdssdk.NodeID
}

type amount struct {
Counter float64
}

type PackageStat struct {
cfg Config
amounts map[amountKey]*amount
lock sync.Mutex
}

func NewPackageStat(cfg Config) *PackageStat {
return &PackageStat{
cfg: cfg,
amounts: make(map[amountKey]*amount),
}
}

func (p *PackageStat) AddAccessCounter(pkgID cdssdk.PackageID, nodeID cdssdk.NodeID, value float64) {
p.lock.Lock()
defer p.lock.Unlock()

key := amountKey{
PackageID: pkgID,
NodeID: nodeID,
}
if _, ok := p.amounts[key]; !ok {
p.amounts[key] = &amount{}
}
p.amounts[key].Counter += value
}

func (p *PackageStat) Start() *sync2.UnboundChannel[PackageStatEvent] {
ch := sync2.NewUnboundChannel[PackageStatEvent]()

go func() {
coorCli, err := stgglb.CoordinatorMQPool.Acquire()
if err != nil {
ch.Send(fmt.Errorf("new coordinator client: %w", err))
}
defer stgglb.CoordinatorMQPool.Release(coorCli)

ticker := time.NewTicker(p.cfg.ReportInterval)
for {
<-ticker.C

p.lock.Lock()
amts := p.amounts
p.amounts = make(map[amountKey]*amount)

var addEntries []coormq.AddPackageAccessStatCounterEntry
for key, amount := range amts {
addEntries = append(addEntries, coormq.AddPackageAccessStatCounterEntry{
PackageID: key.PackageID,
NodeID: key.NodeID,
Value: amount.Counter,
})
}
p.lock.Unlock()

_, err := coorCli.AddPackageAccessStatCounter(coormq.NewAddPackageAccessStatCounter(addEntries))
if err != nil {
logger.Errorf("add all package access stat counter: %v", err)

p.lock.Lock()
for key, a := range amts {
if _, ok := p.amounts[key]; !ok {
p.amounts[key] = &amount{}
}
p.amounts[key].Counter += a.Counter
}
p.lock.Unlock()
continue
}
}
}()
return ch
}

+ 5
- 0
coordinator/internal/mq/object.go View File

@@ -429,6 +429,11 @@ func (svc *Service) DeleteObjects(msg *coormq.DeleteObjects) (*coormq.DeleteObje
return fmt.Errorf("batch deleting pinned objects: %w", err)
}

err = svc.db.ObjectAccessStat().BatchDeleteByObjectID(tx, msg.ObjectIDs)
if err != nil {
return fmt.Errorf("batch deleting object access stats: %w", err)
}

return nil
})
if err != nil {


+ 42
- 7
coordinator/internal/mq/package.go View File

@@ -221,13 +221,48 @@ func (svc *Service) GetPackageLoadedNodes(msg *coormq.GetPackageLoadedNodes) (*c
return mq.ReplyOK(coormq.NewGetPackageLoadedNodesResp(nodeIDs))
}

func (svc *Service) AddPackageAccessStatCounter(msg *coormq.AddPackageAccessStatCounter) (*coormq.AddPackageAccessStatCounterResp, *mq.CodeMessage) {
err := svc.db.PackageAccessStat().BatchAddCounter(svc.db.SQLCtx(), msg.Entries)
if err != nil {
errMsg := fmt.Sprintf("batch add package access stat counter: %s", err.Error())
logger.Error(errMsg)
return nil, mq.Failed(errorcode.OperationFailed, errMsg)
func (svc *Service) AddAccessStat(msg *coormq.AddAccessStat) {
pkgIDs := make([]cdssdk.PackageID, len(msg.Entries))
objIDs := make([]cdssdk.ObjectID, len(msg.Entries))
for i, e := range msg.Entries {
pkgIDs[i] = e.PackageID
objIDs[i] = e.ObjectID
}

return mq.ReplyOK(coormq.NewAddPackageAccessStatCounterResp())
err := svc.db.DoTx(sql.LevelSerializable, func(tx *sqlx.Tx) error {
avaiPkgIDs, err := svc.db.Package().BatchTestPackageID(tx, pkgIDs)
if err != nil {
return fmt.Errorf("batch test package id: %w", err)
}

avaiObjIDs, err := svc.db.Object().BatchTestObjectID(tx, objIDs)
if err != nil {
return fmt.Errorf("batch test object id: %w", err)
}

var willAdds []coormq.AddAccessStatEntry
for _, e := range msg.Entries {
if avaiPkgIDs[e.PackageID] && avaiObjIDs[e.ObjectID] {
willAdds = append(willAdds, e)
}
}

if len(willAdds) > 0 {
err := svc.db.PackageAccessStat().BatchAddCounter(tx, willAdds)
if err != nil {
return fmt.Errorf("batch add package access stat counter: %w", err)
}

err = svc.db.ObjectAccessStat().BatchAddCounter(tx, willAdds)
if err != nil {
return fmt.Errorf("batch add object access stat counter: %w", err)
}
}

return nil
})

if err != nil {
logger.Warn(err.Error())
}
}

Loading…
Cancel
Save