210 lines
7.1 KiB
Go
210 lines
7.1 KiB
Go
package services
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"sort"
|
||
|
||
"github.com/jmoiron/sqlx"
|
||
"gitlink.org.cn/cloudream/common/consts/errorcode"
|
||
"gitlink.org.cn/cloudream/common/pkgs/logger"
|
||
"gitlink.org.cn/cloudream/common/pkgs/mq"
|
||
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
|
||
coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
|
||
scmq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/scanner"
|
||
scevt "gitlink.org.cn/cloudream/storage/common/pkgs/mq/scanner/event"
|
||
)
|
||
|
||
func (svc *Service) GetPackage(msg *coormq.GetPackage) (*coormq.GetPackageResp, *mq.CodeMessage) {
|
||
pkg, err := svc.db.Package().GetByID(svc.db.SQLCtx(), msg.PackageID)
|
||
if err != nil {
|
||
logger.WithField("PackageID", msg.PackageID).
|
||
Warnf("get package: %s", err.Error())
|
||
|
||
return nil, mq.Failed(errorcode.OperationFailed, "get package failed")
|
||
}
|
||
|
||
return mq.ReplyOK(coormq.NewGetPackageResp(pkg))
|
||
}
|
||
|
||
func (svc *Service) CreatePackage(msg *coormq.CreatePackage) (*coormq.CreatePackageResp, *mq.CodeMessage) {
|
||
var pkgID cdssdk.PackageID
|
||
err := svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error {
|
||
var err error
|
||
pkgID, err = svc.db.Package().Create(svc.db.SQLCtx(), msg.BucketID, msg.Name)
|
||
return err
|
||
})
|
||
if err != nil {
|
||
logger.WithField("BucketID", msg.BucketID).
|
||
WithField("Name", msg.Name).
|
||
Warnf("creating package: %s", err.Error())
|
||
|
||
return nil, mq.Failed(errorcode.OperationFailed, "creating package failed")
|
||
}
|
||
|
||
return mq.ReplyOK(coormq.NewCreatePackageResp(pkgID))
|
||
}
|
||
|
||
func (svc *Service) UpdateECPackage(msg *coormq.UpdatePackage) (*coormq.UpdatePackageResp, *mq.CodeMessage) {
|
||
_, err := svc.db.Package().GetByID(svc.db.SQLCtx(), msg.PackageID)
|
||
if err != nil {
|
||
logger.WithField("PackageID", msg.PackageID).
|
||
Warnf("get package: %s", err.Error())
|
||
|
||
return nil, mq.Failed(errorcode.OperationFailed, "get package failed")
|
||
}
|
||
|
||
err = svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error {
|
||
// 先执行删除操作
|
||
if len(msg.Deletes) > 0 {
|
||
if err := svc.db.Object().BatchDelete(tx, msg.Deletes); err != nil {
|
||
return fmt.Errorf("deleting objects: %w", err)
|
||
}
|
||
}
|
||
|
||
// 再执行添加操作
|
||
if len(msg.Adds) > 0 {
|
||
if _, err := svc.db.Object().BatchAdd(tx, msg.PackageID, msg.Adds); err != nil {
|
||
return fmt.Errorf("adding objects: %w", err)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
})
|
||
if err != nil {
|
||
logger.Warn(err.Error())
|
||
return nil, mq.Failed(errorcode.OperationFailed, "update ec package failed")
|
||
}
|
||
|
||
return mq.ReplyOK(coormq.NewUpdatePackageResp())
|
||
}
|
||
|
||
func (svc *Service) DeletePackage(msg *coormq.DeletePackage) (*coormq.DeletePackageResp, *mq.CodeMessage) {
|
||
isAva, err := svc.db.Package().IsAvailable(svc.db.SQLCtx(), msg.UserID, msg.PackageID)
|
||
if err != nil {
|
||
logger.WithField("UserID", msg.UserID).
|
||
WithField("PackageID", msg.PackageID).
|
||
Warnf("check package available failed, err: %s", err.Error())
|
||
return nil, mq.Failed(errorcode.OperationFailed, "check package available failed")
|
||
}
|
||
if !isAva {
|
||
logger.WithField("UserID", msg.UserID).
|
||
WithField("PackageID", msg.PackageID).
|
||
Warnf("package is not available to the user")
|
||
return nil, mq.Failed(errorcode.OperationFailed, "package is not available to the user")
|
||
}
|
||
|
||
err = svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error {
|
||
return svc.db.Package().SoftDelete(tx, msg.PackageID)
|
||
})
|
||
if err != nil {
|
||
logger.WithField("UserID", msg.UserID).
|
||
WithField("PackageID", msg.PackageID).
|
||
Warnf("set package deleted failed, err: %s", err.Error())
|
||
return nil, mq.Failed(errorcode.OperationFailed, "set package deleted failed")
|
||
}
|
||
|
||
stgs, err := svc.db.StoragePackage().FindPackageStorages(svc.db.SQLCtx(), msg.PackageID)
|
||
if err != nil {
|
||
logger.Warnf("find package storages failed, but this will not affect the deleting, err: %s", err.Error())
|
||
return mq.ReplyOK(coormq.NewDeletePackageResp())
|
||
}
|
||
|
||
// 不追求及时、准确
|
||
if len(stgs) == 0 {
|
||
// 如果没有被引用,直接投递CheckPackage的任务
|
||
err := svc.scanner.PostEvent(scmq.NewPostEvent(scevt.NewCheckPackage([]cdssdk.PackageID{msg.PackageID}), false, false))
|
||
if err != nil {
|
||
logger.Warnf("post event to scanner failed, but this will not affect deleting, err: %s", err.Error())
|
||
}
|
||
logger.Debugf("post check package event")
|
||
|
||
} else {
|
||
// 有引用则让Agent去检查StoragePackage
|
||
for _, stg := range stgs {
|
||
err := svc.scanner.PostEvent(scmq.NewPostEvent(scevt.NewAgentCheckStorage(stg.StorageID, []cdssdk.PackageID{msg.PackageID}), false, false))
|
||
if err != nil {
|
||
logger.Warnf("post event to scanner failed, but this will not affect deleting, err: %s", err.Error())
|
||
}
|
||
}
|
||
logger.Debugf("post agent check storage event")
|
||
}
|
||
|
||
return mq.ReplyOK(coormq.NewDeletePackageResp())
|
||
}
|
||
|
||
func (svc *Service) GetPackageCachedNodes(msg *coormq.GetPackageCachedNodes) (*coormq.GetPackageCachedNodesResp, *mq.CodeMessage) {
|
||
isAva, err := svc.db.Package().IsAvailable(svc.db.SQLCtx(), msg.UserID, msg.PackageID)
|
||
if err != nil {
|
||
logger.WithField("UserID", msg.UserID).
|
||
WithField("PackageID", msg.PackageID).
|
||
Warnf("check package available failed, err: %s", err.Error())
|
||
return nil, mq.Failed(errorcode.OperationFailed, "check package available failed")
|
||
}
|
||
if !isAva {
|
||
logger.WithField("UserID", msg.UserID).
|
||
WithField("PackageID", msg.PackageID).
|
||
Warnf("package is not available to the user")
|
||
return nil, mq.Failed(errorcode.OperationFailed, "package is not available to the user")
|
||
}
|
||
|
||
objDetails, err := svc.db.ObjectBlock().GetPackageBlockDetails(svc.db.SQLCtx(), msg.PackageID)
|
||
if err != nil {
|
||
logger.WithField("PackageID", msg.PackageID).
|
||
Warnf("get package block details: %s", err.Error())
|
||
|
||
return nil, mq.Failed(errorcode.OperationFailed, "get package block details failed")
|
||
}
|
||
|
||
var packageSize int64
|
||
nodeInfoMap := make(map[cdssdk.NodeID]*cdssdk.NodePackageCachingInfo)
|
||
for _, obj := range objDetails {
|
||
// 只要存了文件的一个块,就认为此节点存了整个文件
|
||
for _, block := range obj.Blocks {
|
||
for _, nodeID := range block.CachedNodeIDs {
|
||
info, ok := nodeInfoMap[nodeID]
|
||
if !ok {
|
||
info = &cdssdk.NodePackageCachingInfo{
|
||
NodeID: nodeID,
|
||
}
|
||
nodeInfoMap[nodeID] = info
|
||
|
||
}
|
||
|
||
info.FileSize += obj.Object.Size
|
||
info.ObjectCount++
|
||
}
|
||
}
|
||
}
|
||
|
||
var nodeInfos []cdssdk.NodePackageCachingInfo
|
||
for _, nodeInfo := range nodeInfoMap {
|
||
nodeInfos = append(nodeInfos, *nodeInfo)
|
||
}
|
||
|
||
sort.Slice(nodeInfos, func(i, j int) bool {
|
||
return nodeInfos[i].NodeID < nodeInfos[j].NodeID
|
||
})
|
||
return mq.ReplyOK(coormq.NewGetPackageCachedNodesResp(nodeInfos, packageSize))
|
||
}
|
||
|
||
func (svc *Service) GetPackageLoadedNodes(msg *coormq.GetPackageLoadedNodes) (*coormq.GetPackageLoadedNodesResp, *mq.CodeMessage) {
|
||
storages, err := svc.db.StoragePackage().FindPackageStorages(svc.db.SQLCtx(), msg.PackageID)
|
||
if err != nil {
|
||
logger.WithField("PackageID", msg.PackageID).
|
||
Warnf("get storages by packageID failed, err: %s", err.Error())
|
||
return nil, mq.Failed(errorcode.OperationFailed, "get storages by packageID failed")
|
||
}
|
||
|
||
uniqueNodeIDs := make(map[cdssdk.NodeID]bool)
|
||
var nodeIDs []cdssdk.NodeID
|
||
for _, stg := range storages {
|
||
if !uniqueNodeIDs[stg.NodeID] {
|
||
uniqueNodeIDs[stg.NodeID] = true
|
||
nodeIDs = append(nodeIDs, stg.NodeID)
|
||
}
|
||
}
|
||
|
||
return mq.ReplyOK(coormq.NewGetPackageLoadedNodesResp(nodeIDs))
|
||
}
|