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.

create_load.go 3.5 kB

7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package uploader
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "path"
  7. "sync"
  8. "time"
  9. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  10. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  11. "gitlink.org.cn/cloudream/storage2/client/types"
  12. stgglb "gitlink.org.cn/cloudream/storage2/common/globals"
  13. "gitlink.org.cn/cloudream/storage2/common/pkgs/distlock"
  14. "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2"
  15. "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2/ops2"
  16. "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2/parser"
  17. coormq "gitlink.org.cn/cloudream/storage2/common/pkgs/mq/coordinator"
  18. )
  19. type CreateLoadUploader struct {
  20. pkg cdssdk.Package
  21. userID cdssdk.UserID
  22. targetSpaces []types.UserSpaceDetail
  23. loadRoots []string
  24. uploader *Uploader
  25. distlock *distlock.Mutex
  26. successes []coormq.AddObjectEntry
  27. lock sync.Mutex
  28. commited bool
  29. }
  30. type CreateLoadResult struct {
  31. Package cdssdk.Package
  32. Objects map[string]cdssdk.Object
  33. }
  34. func (u *CreateLoadUploader) Upload(pa string, size int64, stream io.Reader) error {
  35. uploadTime := time.Now()
  36. spaceIDs := make([]cdssdk.StorageID, 0, len(u.targetSpaces))
  37. ft := ioswitch2.FromTo{}
  38. fromExec, hd := ioswitch2.NewFromDriver(ioswitch2.RawStream())
  39. ft.AddFrom(fromExec)
  40. for i, space := range u.targetSpaces {
  41. ft.AddTo(ioswitch2.NewToShardStore(*space.MasterHub, space, ioswitch2.RawStream(), "fileHash"))
  42. ft.AddTo(ioswitch2.NewLoadToPublic(*space.MasterHub, space, path.Join(u.loadRoots[i], pa)))
  43. spaceIDs = append(spaceIDs, space.Storage.StorageID)
  44. }
  45. plans := exec.NewPlanBuilder()
  46. err := parser.Parse(ft, plans)
  47. if err != nil {
  48. return fmt.Errorf("parsing plan: %w", err)
  49. }
  50. exeCtx := exec.NewExecContext()
  51. exec.SetValueByType(exeCtx, u.uploader.stgAgts)
  52. exec := plans.Execute(exeCtx)
  53. exec.BeginWrite(io.NopCloser(stream), hd)
  54. ret, err := exec.Wait(context.TODO())
  55. if err != nil {
  56. return fmt.Errorf("executing plan: %w", err)
  57. }
  58. u.lock.Lock()
  59. defer u.lock.Unlock()
  60. // 记录上传结果
  61. fileHash := ret["fileHash"].(*ops2.ShardInfoValue).Hash
  62. u.successes = append(u.successes, coormq.AddObjectEntry{
  63. Path: pa,
  64. Size: size,
  65. FileHash: fileHash,
  66. UploadTime: uploadTime,
  67. StorageIDs: spaceIDs,
  68. })
  69. return nil
  70. }
  71. func (u *CreateLoadUploader) Commit() (CreateLoadResult, error) {
  72. u.lock.Lock()
  73. defer u.lock.Unlock()
  74. if u.commited {
  75. return CreateLoadResult{}, fmt.Errorf("package already commited")
  76. }
  77. u.commited = true
  78. defer u.distlock.Unlock()
  79. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  80. if err != nil {
  81. return CreateLoadResult{}, fmt.Errorf("new coordinator client: %w", err)
  82. }
  83. defer stgglb.CoordinatorMQPool.Release(coorCli)
  84. updateResp, err := coorCli.UpdatePackage(coormq.NewUpdatePackage(u.pkg.PackageID, u.successes))
  85. if err != nil {
  86. return CreateLoadResult{}, fmt.Errorf("updating package: %w", err)
  87. }
  88. ret := CreateLoadResult{
  89. Package: u.pkg,
  90. Objects: make(map[string]cdssdk.Object),
  91. }
  92. for _, entry := range updateResp.Added {
  93. ret.Objects[entry.Path] = entry
  94. }
  95. for i, stg := range u.targetSpaces {
  96. // 不关注是否成功
  97. coorCli.StoragePackageLoaded(coormq.ReqStoragePackageLoaded(u.userID, stg.Storage.StorageID, u.pkg.PackageID, u.loadRoots[i], nil))
  98. }
  99. return ret, nil
  100. }
  101. func (u *CreateLoadUploader) Abort() {
  102. u.lock.Lock()
  103. defer u.lock.Unlock()
  104. if u.commited {
  105. return
  106. }
  107. u.commited = true
  108. u.distlock.Unlock()
  109. // TODO 可以考虑删除PackageID
  110. }

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