Browse Source

调整判断存储系统组件是否实现某个特性的方法

feature_gxh
Sydonian 6 months ago
parent
commit
7ed8450e9c
14 changed files with 128 additions and 115 deletions
  1. +8
    -2
      common/pkgs/ioswitch2/parser/opt/ec.go
  2. +1
    -1
      common/pkgs/ioswitch2/parser/opt/multipart.go
  3. +4
    -24
      common/pkgs/ioswitch2/parser/opt/s2s.go
  4. +5
    -1
      common/pkgs/storage/efile/efile.go
  5. +21
    -8
      common/pkgs/storage/local/local.go
  6. +2
    -2
      common/pkgs/storage/local/s2s.go
  7. +21
    -11
      common/pkgs/storage/obs/obs.go
  8. +27
    -27
      common/pkgs/storage/obs/s2s.go
  9. +5
    -5
      common/pkgs/storage/pool/pool.go
  10. +16
    -10
      common/pkgs/storage/s3/s3.go
  11. +5
    -5
      common/pkgs/storage/types/empty_builder.go
  12. +2
    -2
      common/pkgs/storage/types/s2s.go
  13. +2
    -0
      common/pkgs/storage/types/s3_client.go
  14. +9
    -17
      common/pkgs/storage/types/types.go

+ 8
- 2
common/pkgs/ioswitch2/parser/opt/ec.go View File

@@ -7,6 +7,7 @@ import (
"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/storage/factory"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
)

@@ -79,7 +80,7 @@ func UseECMultiplier(ctx *state.GenerateState) {
}
bwNodes = append(bwNodes, swNode)
}
_, err := factory.GetBuilder(&to.Space).CreateECMultiplier()
_, err := factory.GetBuilder(&to.Space).CreateECMultiplier(true)
if err != nil {
return true
}
@@ -98,7 +99,12 @@ func UseECMultiplier(ctx *state.GenerateState) {
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
}



+ 1
- 1
common/pkgs/ioswitch2/parser/opt/multipart.go View File

@@ -34,7 +34,7 @@ func UseMultipartUploadToShardStore(ctx *state.GenerateState) {
}

// Join的目的地必须支持MultipartUpload功能才能替换成分片上传
multiUpload, err := factory.GetBuilder(&bwNode.UserSpace).CreateMultiparter()
multiUpload, err := factory.GetBuilder(&bwNode.UserSpace).CreateMultiparter(true)
if err != nil {
return true
}


+ 4
- 24
common/pkgs/ioswitch2/parser/opt/s2s.go View File

@@ -26,11 +26,7 @@ func UseS2STransfer(ctx *state.GenerateState) {

func s2sFromShardStore(ctx *state.GenerateState, fromShard *ioswitch2.FromShardStore, frNode ops2.FromNode) {
fromStgBld := factory.GetBuilder(&fromShard.UserSpace)
if !fromStgBld.FeatureDesc().HasBypassShardRead {
return
}

s2s, err := fromStgBld.CreateS2STransfer()
s2s, err := fromStgBld.CreateS2STransfer(true)
if err != nil {
return
}
@@ -50,13 +46,7 @@ loop:

switch dstNode := dstNode.(type) {
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
break
}
@@ -99,11 +89,7 @@ loop:

func s2sFromBaseStore(ctx *state.GenerateState, fromBase *ioswitch2.FromBaseStore, frNode ops2.FromNode) {
fromStgBld := factory.GetBuilder(&fromBase.UserSpace)
if !fromStgBld.FeatureDesc().HasBypassBaseRead {
return
}

s2s, err := fromStgBld.CreateS2STransfer()
s2s, err := fromStgBld.CreateS2STransfer(true)
if err != nil {
return
}
@@ -123,13 +109,7 @@ loop:

switch dstNode := dstNode.(type) {
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
break
}


+ 5
- 1
common/pkgs/storage/efile/efile.go View File

@@ -91,7 +91,11 @@ func (b *builder) getToken() (string, error) {
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)
if feat == nil {
return nil, fmt.Errorf("feature ECMultiplier not found")


+ 21
- 8
common/pkgs/storage/local/local.go View File

@@ -24,13 +24,14 @@ type builder struct {
}

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)
if !ok {
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)
}

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)
if !ok {
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)
}

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)
if feat == nil {
return nil, fmt.Errorf("feature %T not found", cortypes.MultipartUploadFeature{})
@@ -59,7 +68,11 @@ func (b *builder) CreateMultiparter() (types.Multiparter, error) {
}, 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)
if feat == nil {
return nil, fmt.Errorf("feature %T not found", cortypes.S2STransferFeature{})


+ 2
- 2
common/pkgs/storage/local/s2s.go View File

@@ -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)
if !ok {
return false
}

if src.RecommendHub != s.detail.RecommendHub {
if src.RecommendHub.HubID != dst.RecommendHub.HubID {
return false
}



+ 21
- 11
common/pkgs/storage/obs/obs.go View File

@@ -30,16 +30,14 @@ func newBuilder(detail *clitypes.UserSpaceDetail) types.StorageBuilder {
}

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)
cred, ok := b.detail.UserSpace.Credential.(*cortypes.OBSCred)
if !ok {
@@ -54,7 +52,11 @@ func (b *builder) CreateShardStore() (types.ShardStore, error) {
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)
cred, ok := b.detail.UserSpace.Credential.(*cortypes.OBSCred)
if !ok {
@@ -88,7 +90,11 @@ func createClient(stgType *cortypes.OBSType, cred *cortypes.OBSCred) (*s3.Client
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)
feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail)
if feat == nil {
@@ -113,7 +119,11 @@ func (b *builder) CreateMultiparter() (types.Multiparter, error) {
), 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)
feat := utils.FindFeature[*cortypes.S2STransferFeature](b.detail)
if feat == nil {


+ 27
- 27
common/pkgs/storage/obs/s2s.go View File

@@ -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
}

// 执行数据直传。返回传输后的文件路径
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 {
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
}

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) {
ticker := time.NewTicker(time.Second * 5)
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
}
}

+ 5
- 5
common/pkgs/storage/pool/pool.go View File

@@ -64,7 +64,7 @@ func (p *Pool) GetShardStore(spaceDetail *clitypes.UserSpaceDetail) (types.Shard

if space.store == nil {
bld := factory.GetBuilder(spaceDetail)
store, err := bld.CreateShardStore()
store, err := bld.CreateShardStore(false)
if err != nil {
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) {
return factory.GetBuilder(spaceDetail).CreateBaseStore()
return factory.GetBuilder(spaceDetail).CreateBaseStore(false)
}

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) {
return factory.GetBuilder(spaceDetail).CreateS2STransfer()
return factory.GetBuilder(spaceDetail).CreateS2STransfer(false)
}

func (p *Pool) GetECMultiplier(spaceDetail *clitypes.UserSpaceDetail) (types.ECMultiplier, error) {
return factory.GetBuilder(spaceDetail).CreateECMultiplier()
return factory.GetBuilder(spaceDetail).CreateECMultiplier(false)
}

+ 16
- 10
common/pkgs/storage/s3/s3.go View File

@@ -29,16 +29,14 @@ func newBuilder(detail *clitypes.UserSpaceDetail) types.StorageBuilder {
}

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)
s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred)
if !ok {
@@ -53,7 +51,11 @@ func (b *builder) CreateShardStore() (types.ShardStore, error) {
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)
s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred)
if !ok {
@@ -89,7 +91,11 @@ func createClient(stgType *cortypes.S3Type, cred *cortypes.S3Cred) (*s3.Client,
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)
feat := utils.FindFeature[*cortypes.MultipartUploadFeature](b.detail)
if feat == nil {


+ 5
- 5
common/pkgs/storage/types/empty_builder.go View File

@@ -14,22 +14,22 @@ func (b *EmptyBuilder) FeatureDesc() 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)
}

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)
}

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)
}

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)
}

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)
}

+ 2
- 2
common/pkgs/storage/types/s2s.go View File

@@ -7,8 +7,8 @@ import (
)

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)
Close()


+ 2
- 0
common/pkgs/storage/types/s3_client.go View File

@@ -6,7 +6,9 @@ import (
)

type Multiparter interface {
// 【静态方法】
MaxPartSize() int64
// 【静态方法】
MinPartSize() int64
// 启动一个分片上传
Initiate(ctx context.Context) (MultipartTask, error)


+ 9
- 17
common/pkgs/storage/types/types.go View File

@@ -18,32 +18,24 @@ type StorageEvent interface{}

type StorageEventChan = async.UnboundChannel[StorageEvent]

// 创建存储系统各种组件。
//
// typeOnly参数为true时仅创建组件类型(带类型的nil值),不创建组件实例。
type StorageBuilder interface {
// 关于此存储系统特性功能的描述
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 {
// 分片在存储系统中的路径,可以通过BaseStore读取的


Loading…
Cancel
Save