| @@ -7,6 +7,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser/state" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser/state" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/factory" | "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/factory" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types" | |||||
| cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" | cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" | ||||
| ) | ) | ||||
| @@ -79,7 +80,7 @@ func UseECMultiplier(ctx *state.GenerateState) { | |||||
| } | } | ||||
| bwNodes = append(bwNodes, swNode) | bwNodes = append(bwNodes, swNode) | ||||
| } | } | ||||
| _, err := factory.GetBuilder(&to.Space).CreateECMultiplier() | |||||
| _, err := factory.GetBuilder(&to.Space).CreateECMultiplier(true) | |||||
| if err != nil { | if err != nil { | ||||
| return true | return true | ||||
| } | } | ||||
| @@ -98,7 +99,12 @@ func UseECMultiplier(ctx *state.GenerateState) { | |||||
| return true | return true | ||||
| } | } | ||||
| if !factory.GetBuilder(&brNode.UserSpace).FeatureDesc().HasBypassHTTPRead { | |||||
| store, err := factory.GetBuilder(&brNode.UserSpace).CreateShardStore(true) | |||||
| if err != nil { | |||||
| return true | |||||
| } | |||||
| _, ok = store.(types.HTTPShardRead) | |||||
| if !ok { | |||||
| return true | return true | ||||
| } | } | ||||
| @@ -34,7 +34,7 @@ func UseMultipartUploadToShardStore(ctx *state.GenerateState) { | |||||
| } | } | ||||
| // Join的目的地必须支持MultipartUpload功能才能替换成分片上传 | // Join的目的地必须支持MultipartUpload功能才能替换成分片上传 | ||||
| multiUpload, err := factory.GetBuilder(&bwNode.UserSpace).CreateMultiparter() | |||||
| multiUpload, err := factory.GetBuilder(&bwNode.UserSpace).CreateMultiparter(true) | |||||
| if err != nil { | if err != nil { | ||||
| return true | return true | ||||
| } | } | ||||
| @@ -26,11 +26,7 @@ func UseS2STransfer(ctx *state.GenerateState) { | |||||
| func s2sFromShardStore(ctx *state.GenerateState, fromShard *ioswitch2.FromShardStore, frNode ops2.FromNode) { | func s2sFromShardStore(ctx *state.GenerateState, fromShard *ioswitch2.FromShardStore, frNode ops2.FromNode) { | ||||
| fromStgBld := factory.GetBuilder(&fromShard.UserSpace) | fromStgBld := factory.GetBuilder(&fromShard.UserSpace) | ||||
| if !fromStgBld.FeatureDesc().HasBypassShardRead { | |||||
| return | |||||
| } | |||||
| s2s, err := fromStgBld.CreateS2STransfer() | |||||
| s2s, err := fromStgBld.CreateS2STransfer(true) | |||||
| if err != nil { | if err != nil { | ||||
| return | return | ||||
| } | } | ||||
| @@ -50,13 +46,7 @@ loop: | |||||
| switch dstNode := dstNode.(type) { | switch dstNode := dstNode.(type) { | ||||
| case *ops2.BaseWriteNode: | case *ops2.BaseWriteNode: | ||||
| dstStgBld := factory.GetBuilder(&dstNode.UserSpace) | |||||
| if !dstStgBld.FeatureDesc().HasBypassBaseWrite { | |||||
| failed = true | |||||
| break | |||||
| } | |||||
| if !s2s.CanTransfer(&dstNode.UserSpace) { | |||||
| if !s2s.CanTransfer(&fromShard.UserSpace, &dstNode.UserSpace) { | |||||
| failed = true | failed = true | ||||
| break | break | ||||
| } | } | ||||
| @@ -99,11 +89,7 @@ loop: | |||||
| func s2sFromBaseStore(ctx *state.GenerateState, fromBase *ioswitch2.FromBaseStore, frNode ops2.FromNode) { | func s2sFromBaseStore(ctx *state.GenerateState, fromBase *ioswitch2.FromBaseStore, frNode ops2.FromNode) { | ||||
| fromStgBld := factory.GetBuilder(&fromBase.UserSpace) | fromStgBld := factory.GetBuilder(&fromBase.UserSpace) | ||||
| if !fromStgBld.FeatureDesc().HasBypassBaseRead { | |||||
| return | |||||
| } | |||||
| s2s, err := fromStgBld.CreateS2STransfer() | |||||
| s2s, err := fromStgBld.CreateS2STransfer(true) | |||||
| if err != nil { | if err != nil { | ||||
| return | return | ||||
| } | } | ||||
| @@ -123,13 +109,7 @@ loop: | |||||
| switch dstNode := dstNode.(type) { | switch dstNode := dstNode.(type) { | ||||
| case *ops2.BaseWriteNode: | case *ops2.BaseWriteNode: | ||||
| dstStgBld := factory.GetBuilder(&dstNode.UserSpace) | |||||
| if !dstStgBld.FeatureDesc().HasBypassBaseWrite { | |||||
| failed = true | |||||
| break | |||||
| } | |||||
| if !s2s.CanTransfer(&dstNode.UserSpace) { | |||||
| if !s2s.CanTransfer(&fromBase.UserSpace, &dstNode.UserSpace) { | |||||
| failed = true | failed = true | ||||
| break | break | ||||
| } | } | ||||
| @@ -91,7 +91,11 @@ func (b *builder) getToken() (string, error) { | |||||
| return "", fmt.Errorf("clusterID %s not found", stgType.ClusterID) | return "", fmt.Errorf("clusterID %s not found", stgType.ClusterID) | ||||
| } | } | ||||
| func (b *builder) CreateECMultiplier() (types.ECMultiplier, error) { | |||||
| func (b *builder) CreateECMultiplier(typeOnly bool) (types.ECMultiplier, error) { | |||||
| if typeOnly { | |||||
| return (*ECMultiplier)(nil), nil | |||||
| } | |||||
| feat := utils.FindFeature[*cortypes.ECMultiplierFeature](b.detail) | feat := utils.FindFeature[*cortypes.ECMultiplierFeature](b.detail) | ||||
| if feat == nil { | if feat == nil { | ||||
| return nil, fmt.Errorf("feature ECMultiplier not found") | return nil, fmt.Errorf("feature ECMultiplier not found") | ||||
| @@ -24,13 +24,14 @@ type builder struct { | |||||
| } | } | ||||
| func (b *builder) FeatureDesc() types.FeatureDesc { | func (b *builder) FeatureDesc() types.FeatureDesc { | ||||
| return types.FeatureDesc{ | |||||
| HasBypassShardWrite: true, | |||||
| HasBypassShardRead: true, | |||||
| } | |||||
| return types.FeatureDesc{} | |||||
| } | } | ||||
| func (b *builder) CreateShardStore() (types.ShardStore, error) { | |||||
| func (b *builder) CreateShardStore(typeOnly bool) (types.ShardStore, error) { | |||||
| if typeOnly { | |||||
| return (*ShardStore)(nil), nil | |||||
| } | |||||
| cred, ok := b.detail.UserSpace.Credential.(*cortypes.LocalCred) | cred, ok := b.detail.UserSpace.Credential.(*cortypes.LocalCred) | ||||
| if !ok { | if !ok { | ||||
| return nil, fmt.Errorf("invalid storage credential type %T for local storage", b.detail.UserSpace.Credential) | return nil, fmt.Errorf("invalid storage credential type %T for local storage", b.detail.UserSpace.Credential) | ||||
| @@ -39,7 +40,11 @@ func (b *builder) CreateShardStore() (types.ShardStore, error) { | |||||
| return NewShardStore(cred.RootDir, b.detail) | return NewShardStore(cred.RootDir, b.detail) | ||||
| } | } | ||||
| func (b *builder) CreateBaseStore() (types.BaseStore, error) { | |||||
| func (b *builder) CreateBaseStore(typeOnly bool) (types.BaseStore, error) { | |||||
| if typeOnly { | |||||
| return (*BaseStore)(nil), nil | |||||
| } | |||||
| cred, ok := b.detail.UserSpace.Credential.(*cortypes.LocalCred) | cred, ok := b.detail.UserSpace.Credential.(*cortypes.LocalCred) | ||||
| if !ok { | if !ok { | ||||
| return nil, fmt.Errorf("invalid storage credential type %T for local storage", b.detail.UserSpace.Credential) | return nil, fmt.Errorf("invalid storage credential type %T for local storage", b.detail.UserSpace.Credential) | ||||
| @@ -48,7 +53,11 @@ func (b *builder) CreateBaseStore() (types.BaseStore, error) { | |||||
| return NewBaseStore(cred.RootDir, b.detail) | return NewBaseStore(cred.RootDir, b.detail) | ||||
| } | } | ||||
| func (b *builder) CreateMultiparter() (types.Multiparter, error) { | |||||
| func (b *builder) CreateMultiparter(typeOnly bool) (types.Multiparter, error) { | |||||
| if typeOnly { | |||||
| return (*Multiparter)(nil), nil | |||||
| } | |||||
| feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail) | feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail) | ||||
| if feat == nil { | if feat == nil { | ||||
| return nil, fmt.Errorf("feature %T not found", cortypes.MultipartUploadFeature{}) | return nil, fmt.Errorf("feature %T not found", cortypes.MultipartUploadFeature{}) | ||||
| @@ -59,7 +68,11 @@ func (b *builder) CreateMultiparter() (types.Multiparter, error) { | |||||
| }, nil | }, nil | ||||
| } | } | ||||
| func (b *builder) CreateS2STransfer() (types.S2STransfer, error) { | |||||
| func (b *builder) CreateS2STransfer(typeOnly bool) (types.S2STransfer, error) { | |||||
| if typeOnly { | |||||
| return (*S2STransfer)(nil), nil | |||||
| } | |||||
| feat := utils.FindFeature[*cortypes.S2STransferFeature](b.detail) | feat := utils.FindFeature[*cortypes.S2STransferFeature](b.detail) | ||||
| if feat == nil { | if feat == nil { | ||||
| return nil, fmt.Errorf("feature %T not found", cortypes.S2STransferFeature{}) | return nil, fmt.Errorf("feature %T not found", cortypes.S2STransferFeature{}) | ||||
| @@ -17,13 +17,13 @@ type S2STransfer struct { | |||||
| } | } | ||||
| // 只有同一个机器的存储之间才可以进行数据直传 | // 只有同一个机器的存储之间才可以进行数据直传 | ||||
| func (s *S2STransfer) CanTransfer(src *clitypes.UserSpaceDetail) bool { | |||||
| func (*S2STransfer) CanTransfer(src, dst *clitypes.UserSpaceDetail) bool { | |||||
| _, ok := src.UserSpace.Storage.(*cortypes.LocalType) | _, ok := src.UserSpace.Storage.(*cortypes.LocalType) | ||||
| if !ok { | if !ok { | ||||
| return false | return false | ||||
| } | } | ||||
| if src.RecommendHub != s.detail.RecommendHub { | |||||
| if src.RecommendHub.HubID != dst.RecommendHub.HubID { | |||||
| return false | return false | ||||
| } | } | ||||
| @@ -30,16 +30,14 @@ func newBuilder(detail *clitypes.UserSpaceDetail) types.StorageBuilder { | |||||
| } | } | ||||
| func (b *builder) FeatureDesc() types.FeatureDesc { | func (b *builder) FeatureDesc() types.FeatureDesc { | ||||
| return types.FeatureDesc{ | |||||
| HasBypassShardWrite: true, | |||||
| HasBypassBaseWrite: true, | |||||
| HasBypassShardRead: true, | |||||
| HasBypassBaseRead: true, | |||||
| HasBypassHTTPRead: true, | |||||
| } | |||||
| return types.FeatureDesc{} | |||||
| } | } | ||||
| func (b *builder) CreateShardStore() (types.ShardStore, error) { | |||||
| func (b *builder) CreateShardStore(typeOnly bool) (types.ShardStore, error) { | |||||
| if typeOnly { | |||||
| return (*ShardStore)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | ||||
| cred, ok := b.detail.UserSpace.Credential.(*cortypes.OBSCred) | cred, ok := b.detail.UserSpace.Credential.(*cortypes.OBSCred) | ||||
| if !ok { | if !ok { | ||||
| @@ -54,7 +52,11 @@ func (b *builder) CreateShardStore() (types.ShardStore, error) { | |||||
| return NewShardStore(b.detail, stgType, cred, cli, bucket) | return NewShardStore(b.detail, stgType, cred, cli, bucket) | ||||
| } | } | ||||
| func (b *builder) CreateBaseStore() (types.BaseStore, error) { | |||||
| func (b *builder) CreateBaseStore(typeOnly bool) (types.BaseStore, error) { | |||||
| if typeOnly { | |||||
| return (*s3stg.BaseStore)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | ||||
| cred, ok := b.detail.UserSpace.Credential.(*cortypes.OBSCred) | cred, ok := b.detail.UserSpace.Credential.(*cortypes.OBSCred) | ||||
| if !ok { | if !ok { | ||||
| @@ -88,7 +90,11 @@ func createClient(stgType *cortypes.OBSType, cred *cortypes.OBSCred) (*s3.Client | |||||
| return cli, stgType.Bucket, nil | return cli, stgType.Bucket, nil | ||||
| } | } | ||||
| func (b *builder) CreateMultiparter() (types.Multiparter, error) { | |||||
| func (b *builder) CreateMultiparter(typeOnly bool) (types.Multiparter, error) { | |||||
| if typeOnly { | |||||
| return (*s3stg.Multiparter)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | ||||
| feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail) | feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail) | ||||
| if feat == nil { | if feat == nil { | ||||
| @@ -113,7 +119,11 @@ func (b *builder) CreateMultiparter() (types.Multiparter, error) { | |||||
| ), nil | ), nil | ||||
| } | } | ||||
| func (b *builder) CreateS2STransfer() (types.S2STransfer, error) { | |||||
| func (b *builder) CreateS2STransfer(typeOnly bool) (types.S2STransfer, error) { | |||||
| if typeOnly { | |||||
| return (*S2STransfer)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | stgType := b.detail.UserSpace.Storage.(*cortypes.OBSType) | ||||
| feat := utils.FindFeature[*cortypes.S2STransferFeature](b.detail) | feat := utils.FindFeature[*cortypes.S2STransferFeature](b.detail) | ||||
| if feat == nil { | if feat == nil { | ||||
| @@ -36,14 +36,14 @@ func NewS2STransfer(stgType *cortypes.OBSType, cred *cortypes.OBSCred, feat *cor | |||||
| } | } | ||||
| // 判断是否能从指定的源存储中直传到当前存储的目的路径 | // 判断是否能从指定的源存储中直传到当前存储的目的路径 | ||||
| func (s *S2STransfer) CanTransfer(src *clitypes.UserSpaceDetail) bool { | |||||
| req := s.makeRequest(src, "") | |||||
| func (*S2STransfer) CanTransfer(src, dst *clitypes.UserSpaceDetail) bool { | |||||
| req := makeRequest(src, "") | |||||
| return req != nil | return req != nil | ||||
| } | } | ||||
| // 执行数据直传。返回传输后的文件路径 | // 执行数据直传。返回传输后的文件路径 | ||||
| func (s *S2STransfer) Transfer(ctx context.Context, src *clitypes.UserSpaceDetail, srcPath string, dstPath string) (types.FileInfo, error) { | func (s *S2STransfer) Transfer(ctx context.Context, src *clitypes.UserSpaceDetail, srcPath string, dstPath string) (types.FileInfo, error) { | ||||
| req := s.makeRequest(src, srcPath) | |||||
| req := makeRequest(src, srcPath) | |||||
| if req == nil { | if req == nil { | ||||
| return types.FileInfo{}, fmt.Errorf("unsupported source storage type: %T", src.UserSpace.Storage) | return types.FileInfo{}, fmt.Errorf("unsupported source storage type: %T", src.UserSpace.Storage) | ||||
| } | } | ||||
| @@ -122,30 +122,6 @@ func (s *S2STransfer) Transfer(ctx context.Context, src *clitypes.UserSpaceDetai | |||||
| }, nil | }, nil | ||||
| } | } | ||||
| func (s *S2STransfer) makeRequest(srcStg *clitypes.UserSpaceDetail, srcPath string) *model.SrcNodeReq { | |||||
| switch srcType := srcStg.UserSpace.Storage.(type) { | |||||
| case *cortypes.OBSType: | |||||
| cloudType := "HuaweiCloud" | |||||
| cred, ok := srcStg.UserSpace.Credential.(*cortypes.OBSCred) | |||||
| if !ok { | |||||
| return nil | |||||
| } | |||||
| return &model.SrcNodeReq{ | |||||
| CloudType: &cloudType, | |||||
| Region: &srcType.Region, | |||||
| Ak: &cred.AK, | |||||
| Sk: &cred.SK, | |||||
| Bucket: &srcType.Bucket, | |||||
| ObjectKey: &[]string{srcPath}, | |||||
| } | |||||
| default: | |||||
| return nil | |||||
| } | |||||
| } | |||||
| func (s *S2STransfer) waitTask(ctx context.Context, taskId int64) (int64, error) { | func (s *S2STransfer) waitTask(ctx context.Context, taskId int64) (int64, error) { | ||||
| ticker := time.NewTicker(time.Second * 5) | ticker := time.NewTicker(time.Second * 5) | ||||
| defer ticker.Stop() | defer ticker.Stop() | ||||
| @@ -198,3 +174,27 @@ func (s *S2STransfer) Close() { | |||||
| }) | }) | ||||
| } | } | ||||
| } | } | ||||
| func makeRequest(srcStg *clitypes.UserSpaceDetail, srcPath string) *model.SrcNodeReq { | |||||
| switch srcType := srcStg.UserSpace.Storage.(type) { | |||||
| case *cortypes.OBSType: | |||||
| cloudType := "HuaweiCloud" | |||||
| cred, ok := srcStg.UserSpace.Credential.(*cortypes.OBSCred) | |||||
| if !ok { | |||||
| return nil | |||||
| } | |||||
| return &model.SrcNodeReq{ | |||||
| CloudType: &cloudType, | |||||
| Region: &srcType.Region, | |||||
| Ak: &cred.AK, | |||||
| Sk: &cred.SK, | |||||
| Bucket: &srcType.Bucket, | |||||
| ObjectKey: &[]string{srcPath}, | |||||
| } | |||||
| default: | |||||
| return nil | |||||
| } | |||||
| } | |||||
| @@ -64,7 +64,7 @@ func (p *Pool) GetShardStore(spaceDetail *clitypes.UserSpaceDetail) (types.Shard | |||||
| if space.store == nil { | if space.store == nil { | ||||
| bld := factory.GetBuilder(spaceDetail) | bld := factory.GetBuilder(spaceDetail) | ||||
| store, err := bld.CreateShardStore() | |||||
| store, err := bld.CreateShardStore(false) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -76,17 +76,17 @@ func (p *Pool) GetShardStore(spaceDetail *clitypes.UserSpaceDetail) (types.Shard | |||||
| } | } | ||||
| func (p *Pool) GetBaseStore(spaceDetail *clitypes.UserSpaceDetail) (types.BaseStore, error) { | func (p *Pool) GetBaseStore(spaceDetail *clitypes.UserSpaceDetail) (types.BaseStore, error) { | ||||
| return factory.GetBuilder(spaceDetail).CreateBaseStore() | |||||
| return factory.GetBuilder(spaceDetail).CreateBaseStore(false) | |||||
| } | } | ||||
| func (p *Pool) GetMultiparter(spaceDetail *clitypes.UserSpaceDetail) (types.Multiparter, error) { | func (p *Pool) GetMultiparter(spaceDetail *clitypes.UserSpaceDetail) (types.Multiparter, error) { | ||||
| return factory.GetBuilder(spaceDetail).CreateMultiparter() | |||||
| return factory.GetBuilder(spaceDetail).CreateMultiparter(false) | |||||
| } | } | ||||
| func (p *Pool) GetS2STransfer(spaceDetail *clitypes.UserSpaceDetail) (types.S2STransfer, error) { | func (p *Pool) GetS2STransfer(spaceDetail *clitypes.UserSpaceDetail) (types.S2STransfer, error) { | ||||
| return factory.GetBuilder(spaceDetail).CreateS2STransfer() | |||||
| return factory.GetBuilder(spaceDetail).CreateS2STransfer(false) | |||||
| } | } | ||||
| func (p *Pool) GetECMultiplier(spaceDetail *clitypes.UserSpaceDetail) (types.ECMultiplier, error) { | func (p *Pool) GetECMultiplier(spaceDetail *clitypes.UserSpaceDetail) (types.ECMultiplier, error) { | ||||
| return factory.GetBuilder(spaceDetail).CreateECMultiplier() | |||||
| return factory.GetBuilder(spaceDetail).CreateECMultiplier(false) | |||||
| } | } | ||||
| @@ -29,16 +29,14 @@ func newBuilder(detail *clitypes.UserSpaceDetail) types.StorageBuilder { | |||||
| } | } | ||||
| func (b *builder) FeatureDesc() types.FeatureDesc { | func (b *builder) FeatureDesc() types.FeatureDesc { | ||||
| return types.FeatureDesc{ | |||||
| HasBypassShardWrite: true, | |||||
| HasBypassBaseWrite: true, | |||||
| HasBypassShardRead: true, | |||||
| HasBypassBaseRead: true, | |||||
| HasBypassHTTPRead: false, | |||||
| } | |||||
| return types.FeatureDesc{} | |||||
| } | } | ||||
| func (b *builder) CreateShardStore() (types.ShardStore, error) { | |||||
| func (b *builder) CreateShardStore(typeOnly bool) (types.ShardStore, error) { | |||||
| if typeOnly { | |||||
| return (*ShardStore)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type) | stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type) | ||||
| s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred) | s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred) | ||||
| if !ok { | if !ok { | ||||
| @@ -53,7 +51,11 @@ func (b *builder) CreateShardStore() (types.ShardStore, error) { | |||||
| return NewShardStore(b.detail, cli, bkt, ShardStoreOption{UseAWSSha256: true}) | return NewShardStore(b.detail, cli, bkt, ShardStoreOption{UseAWSSha256: true}) | ||||
| } | } | ||||
| func (b *builder) CreateBaseStore() (types.BaseStore, error) { | |||||
| func (b *builder) CreateBaseStore(typeOnly bool) (types.BaseStore, error) { | |||||
| if typeOnly { | |||||
| return (*BaseStore)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type) | stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type) | ||||
| s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred) | s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred) | ||||
| if !ok { | if !ok { | ||||
| @@ -89,7 +91,11 @@ func createClient(stgType *cortypes.S3Type, cred *cortypes.S3Cred) (*s3.Client, | |||||
| return cli, stgType.Bucket, nil | return cli, stgType.Bucket, nil | ||||
| } | } | ||||
| func (b *builder) CreateMultiparter() (types.Multiparter, error) { | |||||
| func (b *builder) CreateMultiparter(typeOnly bool) (types.Multiparter, error) { | |||||
| if typeOnly { | |||||
| return (*Multiparter)(nil), nil | |||||
| } | |||||
| stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type) | stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type) | ||||
| feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail) | feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail) | ||||
| if feat == nil { | if feat == nil { | ||||
| @@ -14,22 +14,22 @@ func (b *EmptyBuilder) FeatureDesc() FeatureDesc { | |||||
| return FeatureDesc{} | return FeatureDesc{} | ||||
| } | } | ||||
| func (b *EmptyBuilder) CreateShardStore() (ShardStore, error) { | |||||
| func (b *EmptyBuilder) CreateShardStore(typeOnly bool) (ShardStore, error) { | |||||
| return nil, fmt.Errorf("create shard store for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | return nil, fmt.Errorf("create shard store for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | ||||
| } | } | ||||
| func (b *EmptyBuilder) CreateBaseStore() (BaseStore, error) { | |||||
| func (b *EmptyBuilder) CreateBaseStore(typeOnly bool) (BaseStore, error) { | |||||
| return nil, fmt.Errorf("create base store for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | return nil, fmt.Errorf("create base store for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | ||||
| } | } | ||||
| func (b *EmptyBuilder) CreateMultiparter() (Multiparter, error) { | |||||
| func (b *EmptyBuilder) CreateMultiparter(typeOnly bool) (Multiparter, error) { | |||||
| return nil, fmt.Errorf("create multipart initiator for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | return nil, fmt.Errorf("create multipart initiator for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | ||||
| } | } | ||||
| func (b *EmptyBuilder) CreateS2STransfer() (S2STransfer, error) { | |||||
| func (b *EmptyBuilder) CreateS2STransfer(typeOnly bool) (S2STransfer, error) { | |||||
| return nil, fmt.Errorf("create s2s transfer for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | return nil, fmt.Errorf("create s2s transfer for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | ||||
| } | } | ||||
| func (b *EmptyBuilder) CreateECMultiplier() (ECMultiplier, error) { | |||||
| func (b *EmptyBuilder) CreateECMultiplier(typeOnly bool) (ECMultiplier, error) { | |||||
| return nil, fmt.Errorf("create ec multiplier for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | return nil, fmt.Errorf("create ec multiplier for %T: %w", b.Detail.UserSpace.Storage, ErrUnsupported) | ||||
| } | } | ||||
| @@ -7,8 +7,8 @@ import ( | |||||
| ) | ) | ||||
| type S2STransfer interface { | type S2STransfer interface { | ||||
| // 判断是否能从指定的源存储中直传到当前存储的目的路径。仅在生成计划时使用 | |||||
| CanTransfer(src *clitypes.UserSpaceDetail) bool | |||||
| // 【静态方法】判断是否能从指定的源存储中直传到当前存储的目的路径。仅在生成计划时使用 | |||||
| CanTransfer(src, dst *clitypes.UserSpaceDetail) bool | |||||
| // 从远端获取文件并保存到本地路径 | // 从远端获取文件并保存到本地路径 | ||||
| Transfer(ctx context.Context, src *clitypes.UserSpaceDetail, srcPath string, dstPath string) (FileInfo, error) | Transfer(ctx context.Context, src *clitypes.UserSpaceDetail, srcPath string, dstPath string) (FileInfo, error) | ||||
| Close() | Close() | ||||
| @@ -6,7 +6,9 @@ import ( | |||||
| ) | ) | ||||
| type Multiparter interface { | type Multiparter interface { | ||||
| // 【静态方法】 | |||||
| MaxPartSize() int64 | MaxPartSize() int64 | ||||
| // 【静态方法】 | |||||
| MinPartSize() int64 | MinPartSize() int64 | ||||
| // 启动一个分片上传 | // 启动一个分片上传 | ||||
| Initiate(ctx context.Context) (MultipartTask, error) | Initiate(ctx context.Context) (MultipartTask, error) | ||||
| @@ -18,32 +18,24 @@ type StorageEvent interface{} | |||||
| type StorageEventChan = async.UnboundChannel[StorageEvent] | type StorageEventChan = async.UnboundChannel[StorageEvent] | ||||
| // 创建存储系统各种组件。 | |||||
| // | |||||
| // typeOnly参数为true时仅创建组件类型(带类型的nil值),不创建组件实例。 | |||||
| type StorageBuilder interface { | type StorageBuilder interface { | ||||
| // 关于此存储系统特性功能的描述 | // 关于此存储系统特性功能的描述 | ||||
| FeatureDesc() FeatureDesc | FeatureDesc() FeatureDesc | ||||
| // 创建一个提供基础读写存储服务能力的组件 | // 创建一个提供基础读写存储服务能力的组件 | ||||
| CreateBaseStore() (BaseStore, error) | |||||
| CreateBaseStore(typeOnly bool) (BaseStore, error) | |||||
| // 创建一个分片存储组件 | // 创建一个分片存储组件 | ||||
| CreateShardStore() (ShardStore, error) | |||||
| CreateShardStore(typeOnly bool) (ShardStore, error) | |||||
| // 创建一个分片上传组件 | // 创建一个分片上传组件 | ||||
| CreateMultiparter() (Multiparter, error) | |||||
| CreateMultiparter(typeOnly bool) (Multiparter, error) | |||||
| // 创建一个存储服务直传组件 | // 创建一个存储服务直传组件 | ||||
| CreateS2STransfer() (S2STransfer, error) | |||||
| CreateECMultiplier() (ECMultiplier, error) | |||||
| CreateS2STransfer(typeOnly bool) (S2STransfer, error) | |||||
| CreateECMultiplier(typeOnly bool) (ECMultiplier, error) | |||||
| } | } | ||||
| type FeatureDesc struct { | |||||
| // 是否能旁路上传分片 | |||||
| HasBypassShardWrite bool | |||||
| // 是否能旁路上传公共存储 | |||||
| HasBypassBaseWrite bool | |||||
| // 是否能旁路读取分片 | |||||
| HasBypassShardRead bool | |||||
| // 公共存储是否支持旁路读取 | |||||
| HasBypassBaseRead bool | |||||
| // 是否能通过HTTP读取 | |||||
| HasBypassHTTPRead bool | |||||
| } | |||||
| type FeatureDesc struct{} | |||||
| type FileInfo struct { | type FileInfo struct { | ||||
| // 分片在存储系统中的路径,可以通过BaseStore读取的 | // 分片在存储系统中的路径,可以通过BaseStore读取的 | ||||