| @@ -19,7 +19,7 @@ func (svc *Service) PinObject(msg *agtmq.PinObject) (*agtmq.PinObjectResp, *mq.C | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "pin object failed") | return nil, mq.Failed(errorcode.OperationFailed, "pin object failed") | ||||
| } | } | ||||
| if msg.Async { | |||||
| if msg.IsBackground { | |||||
| return mq.ReplyOK(agtmq.RespPinObject()) | return mq.ReplyOK(agtmq.RespPinObject()) | ||||
| } | } | ||||
| @@ -111,11 +111,13 @@ func (db *BucketDB) Delete(ctx SQLContext, bucketID cdssdk.BucketID) error { | |||||
| } | } | ||||
| for _, pkgID := range pkgIDs { | for _, pkgID := range pkgIDs { | ||||
| // TODO 不一定所有的错误都要中断后续过程 | |||||
| err = db.Package().SoftDelete(ctx, pkgID) | err = db.Package().SoftDelete(ctx, pkgID) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("set package seleted failed, err: %w", err) | return fmt.Errorf("set package seleted failed, err: %w", err) | ||||
| } | } | ||||
| // 失败也没关系,会有定时任务再次尝试 | |||||
| db.Package().DeleteUnused(ctx, pkgID) | |||||
| } | } | ||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -107,9 +107,14 @@ func (db *ObjectDB) BatchAdd(ctx SQLContext, packageID cdssdk.PackageID, objs [] | |||||
| if !isCreate { | if !isCreate { | ||||
| // 删除原本所有的编码块记录,重新添加 | // 删除原本所有的编码块记录,重新添加 | ||||
| if err = db.ObjectBlock().DeleteObjectAll(ctx, objID); err != nil { | |||||
| if err = db.ObjectBlock().DeleteByObjectID(ctx, objID); err != nil { | |||||
| return nil, fmt.Errorf("deleting all object block: %w", err) | return nil, fmt.Errorf("deleting all object block: %w", err) | ||||
| } | } | ||||
| // 删除原本Pin住的Object。暂不考虑FileHash没有变化的情况 | |||||
| if err = db.PinnedObject().DeleteByObjectID(ctx, objID); err != nil { | |||||
| return nil, fmt.Errorf("deleting all pinned object: %w", err) | |||||
| } | |||||
| } | } | ||||
| // 首次上传默认使用不分块的none模式 | // 首次上传默认使用不分块的none模式 | ||||
| @@ -136,10 +141,15 @@ func (db *ObjectDB) BatchUpdateRedundancy(ctx SQLContext, objs []coormq.ChangeOb | |||||
| } | } | ||||
| // 删除原本所有的编码块记录,重新添加 | // 删除原本所有的编码块记录,重新添加 | ||||
| if err = db.ObjectBlock().DeleteObjectAll(ctx, obj.ObjectID); err != nil { | |||||
| if err = db.ObjectBlock().DeleteByObjectID(ctx, obj.ObjectID); err != nil { | |||||
| return fmt.Errorf("deleting all object block: %w", err) | return fmt.Errorf("deleting all object block: %w", err) | ||||
| } | } | ||||
| // 删除原本Pin住的Object。暂不考虑FileHash没有变化的情况 | |||||
| if err = db.PinnedObject().DeleteByObjectID(ctx, obj.ObjectID); err != nil { | |||||
| return fmt.Errorf("deleting all pinned object: %w", err) | |||||
| } | |||||
| for _, block := range obj.Blocks { | for _, block := range obj.Blocks { | ||||
| // 首次上传默认使用不分块的rep模式 | // 首次上传默认使用不分块的rep模式 | ||||
| err = db.ObjectBlock().Create(ctx, obj.ObjectID, block.Index, block.NodeID, block.FileHash) | err = db.ObjectBlock().Create(ctx, obj.ObjectID, block.Index, block.NodeID, block.FileHash) | ||||
| @@ -31,7 +31,7 @@ func (db *ObjectBlockDB) Create(ctx SQLContext, objectID cdssdk.ObjectID, index | |||||
| return err | return err | ||||
| } | } | ||||
| func (db *ObjectBlockDB) DeleteObjectAll(ctx SQLContext, objectID cdssdk.ObjectID) error { | |||||
| func (db *ObjectBlockDB) DeleteByObjectID(ctx SQLContext, objectID cdssdk.ObjectID) error { | |||||
| _, err := ctx.Exec("delete from ObjectBlock where ObjectID = ?", objectID) | _, err := ctx.Exec("delete from ObjectBlock where ObjectID = ?", objectID) | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -127,6 +127,10 @@ func (db *PackageDB) SoftDelete(ctx SQLContext, packageID cdssdk.PackageID) erro | |||||
| return fmt.Errorf("delete from object rep failed, err: %w", err) | return fmt.Errorf("delete from object rep failed, err: %w", err) | ||||
| } | } | ||||
| if err := db.PinnedObject().DeleteInPackage(ctx, packageID); err != nil { | |||||
| return fmt.Errorf("deleting pinned objects in package: %w", err) | |||||
| } | |||||
| if err := db.Object().DeleteInPackage(ctx, packageID); err != nil { | if err := db.Object().DeleteInPackage(ctx, packageID); err != nil { | ||||
| return fmt.Errorf("deleting objects in package: %w", err) | return fmt.Errorf("deleting objects in package: %w", err) | ||||
| } | } | ||||
| @@ -47,6 +47,16 @@ func (*PinnedObjectDB) Delete(ctx SQLContext, nodeID cdssdk.NodeID, objectID cds | |||||
| return err | return err | ||||
| } | } | ||||
| func (*PinnedObjectDB) DeleteByObjectID(ctx SQLContext, objectID cdssdk.ObjectID) error { | |||||
| _, err := ctx.Exec("delete from PinnedObject where and ObjectID = ?") | |||||
| return err | |||||
| } | |||||
| func (*PinnedObjectDB) DeleteInPackage(ctx SQLContext, packageID cdssdk.PackageID) error { | |||||
| _, err := ctx.Exec("delete PinnedObject from PinnedObject inner join Object on PinnedObject.ObjectID = Object.ObjectID where PackageID = ?", packageID) | |||||
| return err | |||||
| } | |||||
| func (*PinnedObjectDB) NodeBatchDelete(ctx SQLContext, nodeID cdssdk.NodeID, objectIDs []cdssdk.ObjectID) error { | func (*PinnedObjectDB) NodeBatchDelete(ctx SQLContext, nodeID cdssdk.NodeID, objectIDs []cdssdk.ObjectID) error { | ||||
| _, err := ctx.Exec("delete from PinnedObject where NodeID = ? and ObjectID in (?)", objectIDs) | _, err := ctx.Exec("delete from PinnedObject where NodeID = ? and ObjectID in (?)", objectIDs) | ||||
| return err | return err | ||||
| @@ -0,0 +1,21 @@ | |||||
| package db | |||||
| import ( | |||||
| "github.com/jmoiron/sqlx" | |||||
| cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | |||||
| ) | |||||
| type UserDB struct { | |||||
| *DB | |||||
| } | |||||
| func (db *DB) User() *UserDB { | |||||
| return &UserDB{DB: db} | |||||
| } | |||||
| func (db *UserDB) GetByID(ctx SQLContext, userID cdssdk.UserID) (model.User, error) { | |||||
| var ret model.User | |||||
| err := sqlx.Get(ctx, &ret, "select * from User where UserID = ?", userID) | |||||
| return ret, err | |||||
| } | |||||
| @@ -11,17 +11,17 @@ var _ = Register(Service.PinObject) | |||||
| type PinObject struct { | type PinObject struct { | ||||
| mq.MessageBodyBase | mq.MessageBodyBase | ||||
| FileHash string `json:"fileHash"` | |||||
| Async bool `json:"async"` | |||||
| FileHash string `json:"fileHash"` | |||||
| IsBackground bool `json:"isBackground"` | |||||
| } | } | ||||
| type PinObjectResp struct { | type PinObjectResp struct { | ||||
| mq.MessageBodyBase | mq.MessageBodyBase | ||||
| } | } | ||||
| func ReqPinObject(fileHash string, async bool) *PinObject { | |||||
| func ReqPinObject(fileHash string, isBackground bool) *PinObject { | |||||
| return &PinObject{ | return &PinObject{ | ||||
| FileHash: fileHash, | |||||
| Async: async, | |||||
| FileHash: fileHash, | |||||
| IsBackground: isBackground, | |||||
| } | } | ||||
| } | } | ||||
| func RespPinObject() *PinObjectResp { | func RespPinObject() *PinObjectResp { | ||||
| @@ -2,6 +2,7 @@ package services | |||||
| import ( | import ( | ||||
| "database/sql" | "database/sql" | ||||
| "fmt" | |||||
| "github.com/jmoiron/sqlx" | "github.com/jmoiron/sqlx" | ||||
| "gitlink.org.cn/cloudream/common/consts/errorcode" | "gitlink.org.cn/cloudream/common/consts/errorcode" | ||||
| @@ -44,16 +45,23 @@ func (svc *Service) GetBucketPackages(msg *coormq.GetBucketPackages) (*coormq.Ge | |||||
| func (svc *Service) CreateBucket(msg *coormq.CreateBucket) (*coormq.CreateBucketResp, *mq.CodeMessage) { | func (svc *Service) CreateBucket(msg *coormq.CreateBucket) (*coormq.CreateBucketResp, *mq.CodeMessage) { | ||||
| var bucketID cdssdk.BucketID | var bucketID cdssdk.BucketID | ||||
| var err error | |||||
| svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error { | |||||
| // 这里用的是外部的err | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| _, err := svc.db.User().GetByID(tx, msg.UserID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting user by id: %w", err) | |||||
| } | |||||
| bucketID, err = svc.db.Bucket().Create(tx, msg.UserID, msg.BucketName) | bucketID, err = svc.db.Bucket().Create(tx, msg.UserID, msg.BucketName) | ||||
| return err | |||||
| if err != nil { | |||||
| return fmt.Errorf("creating bucket: %w", err) | |||||
| } | |||||
| return nil | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| logger.WithField("UserID", msg.UserID). | logger.WithField("UserID", msg.UserID). | ||||
| WithField("BucketName", msg.BucketName). | WithField("BucketName", msg.BucketName). | ||||
| Warnf("create bucket failed, err: %s", err.Error()) | |||||
| Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "create bucket failed") | return nil, mq.Failed(errorcode.OperationFailed, "create bucket failed") | ||||
| } | } | ||||
| @@ -61,13 +69,23 @@ func (svc *Service) CreateBucket(msg *coormq.CreateBucket) (*coormq.CreateBucket | |||||
| } | } | ||||
| func (svc *Service) DeleteBucket(msg *coormq.DeleteBucket) (*coormq.DeleteBucketResp, *mq.CodeMessage) { | func (svc *Service) DeleteBucket(msg *coormq.DeleteBucket) (*coormq.DeleteBucketResp, *mq.CodeMessage) { | ||||
| err := svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error { | |||||
| return svc.db.Bucket().Delete(tx, msg.BucketID) | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| isAvai, _ := svc.db.Bucket().IsAvailable(tx, msg.BucketID, msg.UserID) | |||||
| if !isAvai { | |||||
| return fmt.Errorf("bucket is not avaiable to the user") | |||||
| } | |||||
| err := svc.db.Bucket().Delete(tx, msg.BucketID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("deleting bucket: %w", err) | |||||
| } | |||||
| return nil | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| logger.WithField("UserID", msg.UserID). | logger.WithField("UserID", msg.UserID). | ||||
| WithField("BucketID", msg.BucketID). | WithField("BucketID", msg.BucketID). | ||||
| Warnf("delete bucket failed, err: %s", err.Error()) | |||||
| Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "delete bucket failed") | return nil, mq.Failed(errorcode.OperationFailed, "delete bucket failed") | ||||
| } | } | ||||
| @@ -1,6 +1,10 @@ | |||||
| package services | package services | ||||
| import ( | import ( | ||||
| "database/sql" | |||||
| "fmt" | |||||
| "github.com/jmoiron/sqlx" | |||||
| "gitlink.org.cn/cloudream/common/consts/errorcode" | "gitlink.org.cn/cloudream/common/consts/errorcode" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/logger" | "gitlink.org.cn/cloudream/common/pkgs/logger" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/mq" | "gitlink.org.cn/cloudream/common/pkgs/mq" | ||||
| @@ -8,8 +12,26 @@ import ( | |||||
| ) | ) | ||||
| func (svc *Service) CachePackageMoved(msg *coormq.CachePackageMoved) (*coormq.CachePackageMovedResp, *mq.CodeMessage) { | func (svc *Service) CachePackageMoved(msg *coormq.CachePackageMoved) (*coormq.CachePackageMovedResp, *mq.CodeMessage) { | ||||
| if err := svc.db.PinnedObject().CreateFromPackage(svc.db.SQLCtx(), msg.PackageID, msg.NodeID); err != nil { | |||||
| logger.Warnf("create package pinned objects: %s", err.Error()) | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| _, err := svc.db.Package().GetByID(tx, msg.PackageID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting package by id: %w", err) | |||||
| } | |||||
| _, err = svc.db.Node().GetByID(tx, msg.NodeID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting node by id: %w", err) | |||||
| } | |||||
| err = svc.db.PinnedObject().CreateFromPackage(tx, msg.PackageID, msg.NodeID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("creating pinned objects from package: %w", err) | |||||
| } | |||||
| return nil | |||||
| }) | |||||
| if err != nil { | |||||
| logger.WithField("PackageID", msg.PackageID).WithField("NodeID", msg.NodeID).Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "create package pinned objects failed") | return nil, mq.Failed(errorcode.OperationFailed, "create package pinned objects failed") | ||||
| } | } | ||||
| @@ -31,6 +31,7 @@ func (svc *Service) GetNodes(msg *coormq.GetNodes) (*coormq.GetNodesResp, *mq.Co | |||||
| } | } | ||||
| } else { | } else { | ||||
| // 可以不用事务 | |||||
| for _, id := range msg.NodeIDs { | for _, id := range msg.NodeIDs { | ||||
| node, err := svc.db.Node().GetByID(svc.db.SQLCtx(), id) | node, err := svc.db.Node().GetByID(svc.db.SQLCtx(), id) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -1,9 +1,14 @@ | |||||
| package services | package services | ||||
| import ( | import ( | ||||
| "database/sql" | |||||
| "fmt" | |||||
| "github.com/jmoiron/sqlx" | |||||
| "gitlink.org.cn/cloudream/common/consts/errorcode" | "gitlink.org.cn/cloudream/common/consts/errorcode" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/logger" | "gitlink.org.cn/cloudream/common/pkgs/logger" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/mq" | "gitlink.org.cn/cloudream/common/pkgs/mq" | ||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | |||||
| coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator" | coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator" | ||||
| ) | ) | ||||
| @@ -21,22 +26,37 @@ func (svc *Service) GetPackageObjects(msg *coormq.GetPackageObjects) (*coormq.Ge | |||||
| } | } | ||||
| func (svc *Service) GetPackageObjectDetails(msg *coormq.GetPackageObjectDetails) (*coormq.GetPackageObjectDetailsResp, *mq.CodeMessage) { | func (svc *Service) GetPackageObjectDetails(msg *coormq.GetPackageObjectDetails) (*coormq.GetPackageObjectDetailsResp, *mq.CodeMessage) { | ||||
| data, err := svc.db.ObjectBlock().GetPackageBlockDetails(svc.db.SQLCtx(), msg.PackageID) | |||||
| if err != nil { | |||||
| logger.WithField("PackageID", msg.PackageID). | |||||
| Warnf("getting package block details: %s", err.Error()) | |||||
| var details []stgmod.ObjectDetail | |||||
| // 必须放在事务里进行,因为GetPackageBlockDetails是由多次数据库操作组成,必须保证数据的一致性 | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| var err error | |||||
| _, err = svc.db.Package().GetByID(tx, msg.PackageID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting package by id: %w", err) | |||||
| } | |||||
| details, err = svc.db.ObjectBlock().GetPackageBlockDetails(tx, msg.PackageID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting package block details: %w", err) | |||||
| } | |||||
| return nil | |||||
| }) | |||||
| if err != nil { | |||||
| logger.WithField("PackageID", msg.PackageID).Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "get package object block details failed") | return nil, mq.Failed(errorcode.OperationFailed, "get package object block details failed") | ||||
| } | } | ||||
| return mq.ReplyOK(coormq.NewGetPackageObjectDetailsResp(data)) | |||||
| return mq.ReplyOK(coormq.NewGetPackageObjectDetailsResp(details)) | |||||
| } | } | ||||
| func (svc *Service) ChangeObjectRedundancy(msg *coormq.ChangeObjectRedundancy) (*coormq.ChangeObjectRedundancyResp, *mq.CodeMessage) { | func (svc *Service) ChangeObjectRedundancy(msg *coormq.ChangeObjectRedundancy) (*coormq.ChangeObjectRedundancyResp, *mq.CodeMessage) { | ||||
| err := svc.db.Object().BatchUpdateRedundancy(svc.db.SQLCtx(), msg.Entries) | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| return svc.db.Object().BatchUpdateRedundancy(tx, msg.Entries) | |||||
| }) | |||||
| if err != nil { | if err != nil { | ||||
| logger.Warnf("batch updating redundancy: %s", err.Error()) | logger.Warnf("batch updating redundancy: %s", err.Error()) | ||||
| return nil, mq.Failed(errorcode.OperationFailed, "batch update redundancy failed") | return nil, mq.Failed(errorcode.OperationFailed, "batch update redundancy failed") | ||||
| } | } | ||||
| @@ -28,16 +28,25 @@ func (svc *Service) GetPackage(msg *coormq.GetPackage) (*coormq.GetPackageResp, | |||||
| func (svc *Service) CreatePackage(msg *coormq.CreatePackage) (*coormq.CreatePackageResp, *mq.CodeMessage) { | func (svc *Service) CreatePackage(msg *coormq.CreatePackage) (*coormq.CreatePackageResp, *mq.CodeMessage) { | ||||
| var pkgID cdssdk.PackageID | var pkgID cdssdk.PackageID | ||||
| err := svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error { | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| var err error | var err error | ||||
| pkgID, err = svc.db.Package().Create(svc.db.SQLCtx(), msg.BucketID, msg.Name) | |||||
| return err | |||||
| isAvai, _ := svc.db.Bucket().IsAvailable(tx, msg.BucketID, msg.UserID) | |||||
| if !isAvai { | |||||
| return fmt.Errorf("bucket is not avaiable to the user") | |||||
| } | |||||
| pkgID, err = svc.db.Package().Create(tx, msg.BucketID, msg.Name) | |||||
| if err != nil { | |||||
| return fmt.Errorf("creating package: %w", err) | |||||
| } | |||||
| return nil | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| logger.WithField("BucketID", msg.BucketID). | logger.WithField("BucketID", msg.BucketID). | ||||
| WithField("Name", msg.Name). | WithField("Name", msg.Name). | ||||
| Warnf("creating package: %s", err.Error()) | |||||
| Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "creating package failed") | return nil, mq.Failed(errorcode.OperationFailed, "creating package failed") | ||||
| } | } | ||||
| @@ -45,15 +54,12 @@ func (svc *Service) CreatePackage(msg *coormq.CreatePackage) (*coormq.CreatePack | |||||
| } | } | ||||
| func (svc *Service) UpdatePackage(msg *coormq.UpdatePackage) (*coormq.UpdatePackageResp, *mq.CodeMessage) { | func (svc *Service) UpdatePackage(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.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| _, err := svc.db.Package().GetByID(tx, msg.PackageID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting package by id: %w", err) | |||||
| } | |||||
| err = svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error { | |||||
| // 先执行删除操作 | // 先执行删除操作 | ||||
| if len(msg.Deletes) > 0 { | if len(msg.Deletes) > 0 { | ||||
| if err := svc.db.Object().BatchDelete(tx, msg.Deletes); err != nil { | if err := svc.db.Object().BatchDelete(tx, msg.Deletes); err != nil { | ||||
| @@ -71,7 +77,7 @@ func (svc *Service) UpdatePackage(msg *coormq.UpdatePackage) (*coormq.UpdatePack | |||||
| return nil | return nil | ||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| logger.Warn(err.Error()) | |||||
| logger.WithField("PackageID", msg.PackageID).Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "update package failed") | return nil, mq.Failed(errorcode.OperationFailed, "update package failed") | ||||
| } | } | ||||
| @@ -79,21 +85,12 @@ func (svc *Service) UpdatePackage(msg *coormq.UpdatePackage) (*coormq.UpdatePack | |||||
| } | } | ||||
| func (svc *Service) DeletePackage(msg *coormq.DeletePackage) (*coormq.DeletePackageResp, *mq.CodeMessage) { | 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.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| isAvai, _ := svc.db.Package().IsAvailable(tx, msg.UserID, msg.PackageID) | |||||
| if !isAvai { | |||||
| return fmt.Errorf("package is not available to the user") | |||||
| } | |||||
| err = svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error { | |||||
| err := svc.db.Package().SoftDelete(tx, msg.PackageID) | err := svc.db.Package().SoftDelete(tx, msg.PackageID) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("soft delete package: %w", err) | return fmt.Errorf("soft delete package: %w", err) | ||||
| @@ -111,8 +108,8 @@ func (svc *Service) DeletePackage(msg *coormq.DeletePackage) (*coormq.DeletePack | |||||
| if err != nil { | if err != nil { | ||||
| logger.WithField("UserID", msg.UserID). | logger.WithField("UserID", msg.UserID). | ||||
| WithField("PackageID", msg.PackageID). | WithField("PackageID", msg.PackageID). | ||||
| Warnf("set package deleted failed, err: %s", err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "set package deleted failed") | |||||
| Warnf(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "delete package failed") | |||||
| } | } | ||||
| return mq.ReplyOK(coormq.NewDeletePackageResp()) | return mq.ReplyOK(coormq.NewDeletePackageResp()) | ||||
| @@ -133,6 +130,7 @@ func (svc *Service) GetPackageCachedNodes(msg *coormq.GetPackageCachedNodes) (*c | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "package is not available to the user") | return nil, mq.Failed(errorcode.OperationFailed, "package is not available to the user") | ||||
| } | } | ||||
| // 这个函数只是统计哪些节点缓存了Package中的数据,不需要多么精确,所以可以不用事务 | |||||
| objDetails, err := svc.db.ObjectBlock().GetPackageBlockDetails(svc.db.SQLCtx(), msg.PackageID) | objDetails, err := svc.db.ObjectBlock().GetPackageBlockDetails(svc.db.SQLCtx(), msg.PackageID) | ||||
| if err != nil { | if err != nil { | ||||
| logger.WithField("PackageID", msg.PackageID). | logger.WithField("PackageID", msg.PackageID). | ||||
| @@ -24,8 +24,7 @@ func (svc *Service) GetStorageInfo(msg *coormq.GetStorageInfo) (*coormq.GetStora | |||||
| } | } | ||||
| func (svc *Service) StoragePackageLoaded(msg *coormq.StoragePackageLoaded) (*coormq.StoragePackageLoadedResp, *mq.CodeMessage) { | func (svc *Service) StoragePackageLoaded(msg *coormq.StoragePackageLoaded) (*coormq.StoragePackageLoadedResp, *mq.CodeMessage) { | ||||
| // TODO: 对于的storage中已经存在的文件,直接覆盖已有文件 | |||||
| err := svc.db.DoTx(sql.LevelDefault, func(tx *sqlx.Tx) error { | |||||
| err := svc.db.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | |||||
| err := svc.db.StoragePackage().Create(tx, msg.StorageID, msg.PackageID, msg.UserID) | err := svc.db.StoragePackage().Create(tx, msg.StorageID, msg.PackageID, msg.UserID) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("creating storage package: %w", err) | return fmt.Errorf("creating storage package: %w", err) | ||||
| @@ -42,7 +41,7 @@ func (svc *Service) StoragePackageLoaded(msg *coormq.StoragePackageLoaded) (*coo | |||||
| logger.WithField("UserID", msg.UserID). | logger.WithField("UserID", msg.UserID). | ||||
| WithField("StorageID", msg.StorageID). | WithField("StorageID", msg.StorageID). | ||||
| WithField("PackageID", msg.PackageID). | WithField("PackageID", msg.PackageID). | ||||
| Warnf("user load package to storage failed, err: %s", err.Error()) | |||||
| Warn(err.Error()) | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "user load package to storage failed") | return nil, mq.Failed(errorcode.OperationFailed, "user load package to storage failed") | ||||
| } | } | ||||
| @@ -89,7 +89,7 @@ func (t *AgentCheckStorage) Execute(execCtx ExecuteContext) { | |||||
| } | } | ||||
| execCtx.Args.DB.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | execCtx.Args.DB.DoTx(sql.LevelLinearizable, func(tx *sqlx.Tx) error { | ||||
| packages, err := execCtx.Args.DB.StoragePackage().GetAllByStorageID(execCtx.Args.DB.SQLCtx(), t.StorageID) | |||||
| packages, err := execCtx.Args.DB.StoragePackage().GetAllByStorageID(tx, t.StorageID) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("getting storage package: %s", err.Error()) | log.Warnf("getting storage package: %s", err.Error()) | ||||
| return nil | return nil | ||||
| @@ -11,6 +11,7 @@ import ( | |||||
| stgglb "gitlink.org.cn/cloudream/storage/common/globals" | stgglb "gitlink.org.cn/cloudream/storage/common/globals" | ||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | stgmod "gitlink.org.cn/cloudream/storage/common/models" | ||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | ||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/distlock/reqbuilder" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/plans" | "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/plans" | ||||
| agtmq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/agent" | agtmq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/agent" | ||||
| coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator" | coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator" | ||||
| @@ -112,6 +113,21 @@ func (t *CheckPackageRedundancy) Execute(execCtx ExecuteContext) { | |||||
| newRepNodes := t.chooseNewNodesForRep(&defRep, allNodes) | newRepNodes := t.chooseNewNodesForRep(&defRep, allNodes) | ||||
| newECNodes := t.chooseNewNodesForEC(&defEC, allNodes) | newECNodes := t.chooseNewNodesForEC(&defEC, allNodes) | ||||
| // 加锁 | |||||
| builder := reqbuilder.NewBuilder() | |||||
| for _, node := range newRepNodes { | |||||
| builder.IPFS().Buzy(node.Node.NodeID) | |||||
| } | |||||
| for _, node := range newECNodes { | |||||
| builder.IPFS().Buzy(node.Node.NodeID) | |||||
| } | |||||
| mutex, err := builder.MutexLock(execCtx.Args.DistLock) | |||||
| if err != nil { | |||||
| log.Warnf("acquiring dist lock: %s", err.Error()) | |||||
| return | |||||
| } | |||||
| defer mutex.Unlock() | |||||
| for _, obj := range getObjs.Objects { | for _, obj := range getObjs.Objects { | ||||
| var entry *coormq.ChangeObjectRedundancyEntry | var entry *coormq.ChangeObjectRedundancyEntry | ||||
| var err error | var err error | ||||