You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

storage.go 5.2 kB

7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package services
  2. import (
  3. "context"
  4. "fmt"
  5. "path"
  6. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  7. clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
  8. "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
  9. "gitlink.org.cn/cloudream/jcs-pub/client/internal/downloader/strategy"
  10. "gitlink.org.cn/cloudream/jcs-pub/client/types"
  11. stgglb "gitlink.org.cn/cloudream/jcs-pub/common/globals"
  12. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2"
  13. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser"
  14. )
  15. type UserSpaceService struct {
  16. *Service
  17. }
  18. func (svc *Service) UserSpaceSvc() *UserSpaceService {
  19. return &UserSpaceService{Service: svc}
  20. }
  21. func (svc *UserSpaceService) Get(userspaceID clitypes.UserSpaceID) (types.UserSpace, error) {
  22. return svc.DB.UserSpace().GetByID(svc.DB.DefCtx(), userspaceID)
  23. }
  24. func (svc *UserSpaceService) GetByName(name string) (types.UserSpace, error) {
  25. return svc.DB.UserSpace().GetByName(svc.DB.DefCtx(), name)
  26. }
  27. func (svc *UserSpaceService) LoadPackage(packageID clitypes.PackageID, userspaceID clitypes.UserSpaceID, rootPath string) error {
  28. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  29. if err != nil {
  30. return fmt.Errorf("new coordinator client: %w", err)
  31. }
  32. defer stgglb.CoordinatorMQPool.Release(coorCli)
  33. destStg := svc.UserSpaceMeta.Get(userspaceID)
  34. if destStg == nil {
  35. return fmt.Errorf("userspace not found: %d", userspaceID)
  36. }
  37. if destStg.MasterHub == nil {
  38. return fmt.Errorf("userspace %v has no master hub", userspaceID)
  39. }
  40. details, err := db.DoTx11(svc.DB, svc.DB.Object().GetPackageObjectDetails, packageID)
  41. if err != nil {
  42. return err
  43. }
  44. var pinned []clitypes.ObjectID
  45. plans := exec.NewPlanBuilder()
  46. for _, obj := range details {
  47. strg, err := svc.StrategySelector.Select(strategy.Request{
  48. Detail: obj,
  49. DestHub: destStg.MasterHub.HubID,
  50. })
  51. if err != nil {
  52. return fmt.Errorf("select download strategy: %w", err)
  53. }
  54. ft := ioswitch2.NewFromTo()
  55. switch strg := strg.(type) {
  56. case *strategy.DirectStrategy:
  57. ft.AddFrom(ioswitch2.NewFromShardstore(strg.Detail.Object.FileHash, *strg.UserSpace.MasterHub, strg.UserSpace, ioswitch2.RawStream()))
  58. case *strategy.ECReconstructStrategy:
  59. for i, b := range strg.Blocks {
  60. ft.AddFrom(ioswitch2.NewFromShardstore(b.FileHash, *strg.UserSpaces[i].MasterHub, strg.UserSpaces[i], ioswitch2.ECStream(b.Index)))
  61. ft.ECParam = &strg.Redundancy
  62. }
  63. default:
  64. return fmt.Errorf("unsupported download strategy: %T", strg)
  65. }
  66. ft.AddTo(ioswitch2.NewLoadToPublic(*destStg.MasterHub, *destStg, path.Join(rootPath, obj.Object.Path)))
  67. // 顺便保存到同存储服务的分片存储中
  68. if destStg.UserSpace.ShardStore != nil {
  69. ft.AddTo(ioswitch2.NewToShardStore(*destStg.MasterHub, *destStg, ioswitch2.RawStream(), ""))
  70. pinned = append(pinned, obj.Object.ObjectID)
  71. }
  72. err = parser.Parse(ft, plans)
  73. if err != nil {
  74. return fmt.Errorf("parse plan: %w", err)
  75. }
  76. }
  77. // TODO2 加锁
  78. // mutex, err := reqbuilder.NewBuilder().
  79. // // 保护在userspace目录中下载的文件
  80. // UserSpace().Buzy(userspaceID).
  81. // // 保护下载文件时同时保存到IPFS的文件
  82. // Shard().Buzy(userspaceID).
  83. // MutexLock(svc.DistLock)
  84. // if err != nil {
  85. // return fmt.Errorf("acquire locks failed, err: %w", err)
  86. // }
  87. // defer mutex.Unlock()
  88. // 记录访问统计
  89. for _, obj := range details {
  90. svc.AccessStat.AddAccessCounter(obj.Object.ObjectID, packageID, userspaceID, 1)
  91. }
  92. drv := plans.Execute(exec.NewExecContext())
  93. _, err = drv.Wait(context.Background())
  94. if err != nil {
  95. return err
  96. }
  97. return nil
  98. }
  99. // 请求节点启动从UserSpace中上传文件的任务。会返回节点ID和任务ID
  100. func (svc *UserSpaceService) UserSpaceCreatePackage(bucketID clitypes.BucketID, name string, userspaceID clitypes.UserSpaceID, path string, userspaceAffinity clitypes.UserSpaceID) (clitypes.Package, error) {
  101. // coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  102. // if err != nil {
  103. // return cdssdk.Package{}, fmt.Errorf("new coordinator client: %w", err)
  104. // }
  105. // defer stgglb.CoordinatorMQPool.Release(coorCli)
  106. // stgResp, err := coorCli.GetUserSpaceDetails(coormq.ReqGetUserSpaceDetails([]cdssdk.UserSpaceID{userspaceID}))
  107. // if err != nil {
  108. // return cdssdk.Package{}, fmt.Errorf("getting userspace info: %w", err)
  109. // }
  110. // spaceDetail := svc.UserSpaceMeta.Get(userspaceID)
  111. // if spaceDetail == nil {
  112. // return cdssdk.Package{}, fmt.Errorf("userspace not found: %d", userspaceID)
  113. // }
  114. // if spaceDetail.UserSpace.ShardStore == nil {
  115. // return cdssdk.Package{}, fmt.Errorf("shard userspace is not enabled")
  116. // }
  117. // hubCli, err := stgglb.HubMQPool.Acquire(spaceDetail.MasterHub.HubID)
  118. // if err != nil {
  119. // return cdssdk.Package{}, fmt.Errorf("new hub client: %w", err)
  120. // }
  121. // defer stgglb.HubMQPool.Release(hubCli)
  122. // createResp, err := hubCli.UserSpaceCreatePackage(hubmq.ReqUserSpaceCreatePackage(bucketID, name, userspaceID, path, userspaceAffinity))
  123. // if err != nil {
  124. // return cdssdk.Package{}, err
  125. // }
  126. // return createResp.Package, nil
  127. // TODO 待实现
  128. return clitypes.Package{}, fmt.Errorf("not implemented")
  129. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。