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.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package uploader
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "sync"
  7. "time"
  8. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  9. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  10. stgglb "gitlink.org.cn/cloudream/storage/common/globals"
  11. stgmod "gitlink.org.cn/cloudream/storage/common/models"
  12. "gitlink.org.cn/cloudream/storage/common/pkgs/distlock"
  13. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch2"
  14. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch2/ops2"
  15. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch2/parser"
  16. coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
  17. "gitlink.org.cn/cloudream/storage/common/pkgs/storage/utils"
  18. )
  19. type CreateLoadUploader struct {
  20. pkg cdssdk.Package
  21. userID cdssdk.UserID
  22. targetStgs []stgmod.StorageDetail
  23. uploader *Uploader
  24. distlock *distlock.Mutex
  25. successes []coormq.AddObjectEntry
  26. lock sync.Mutex
  27. commited bool
  28. }
  29. type CreateLoadResult struct {
  30. Package cdssdk.Package
  31. Objects map[string]cdssdk.Object
  32. LoadedDirs []string
  33. }
  34. func (u *CreateLoadUploader) Upload(path string, size int64, stream io.Reader) error {
  35. uploadTime := time.Now()
  36. ft := ioswitch2.NewFromTo()
  37. fromExec, hd := ioswitch2.NewFromDriver(-1)
  38. ft.AddFrom(fromExec)
  39. for _, stg := range u.targetStgs {
  40. ft.AddTo(ioswitch2.NewToShardStore(*stg.MasterHub, stg.Storage, -1, "fileHash"))
  41. ft.AddTo(ioswitch2.NewLoadToShared(*stg.MasterHub, stg.Storage, u.userID, u.pkg.PackageID, path))
  42. }
  43. plans := exec.NewPlanBuilder()
  44. err := parser.Parse(ft, plans, cdssdk.DefaultECRedundancy)
  45. if err != nil {
  46. return fmt.Errorf("parsing plan: %w", err)
  47. }
  48. exeCtx := exec.NewExecContext()
  49. exec.SetValueByType(exeCtx, u.uploader.stgMgr)
  50. exec := plans.Execute(exeCtx)
  51. exec.BeginWrite(io.NopCloser(stream), hd)
  52. ret, err := exec.Wait(context.TODO())
  53. if err != nil {
  54. return fmt.Errorf("executing plan: %w", err)
  55. }
  56. u.lock.Lock()
  57. defer u.lock.Unlock()
  58. // 记录上传结果
  59. fileHash := ret["fileHash"].(*ops2.FileHashValue).Hash
  60. for _, stg := range u.targetStgs {
  61. u.successes = append(u.successes, coormq.AddObjectEntry{
  62. Path: path,
  63. Size: size,
  64. FileHash: fileHash,
  65. UploadTime: uploadTime,
  66. StorageID: stg.Storage.StorageID,
  67. })
  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, nil))
  85. if err != nil {
  86. return CreateLoadResult{}, fmt.Errorf("updating package: %w", err)
  87. }
  88. ret := CreateLoadResult{
  89. Objects: make(map[string]cdssdk.Object),
  90. }
  91. for _, entry := range updateResp.Added {
  92. ret.Objects[entry.Path] = entry
  93. }
  94. for _, stg := range u.targetStgs {
  95. _, err := coorCli.StoragePackageLoaded(coormq.NewStoragePackageLoaded(u.userID, stg.Storage.StorageID, u.pkg.PackageID, nil))
  96. if err != nil {
  97. return CreateLoadResult{}, fmt.Errorf("notifying storage package loaded: %w", err)
  98. }
  99. // TODO 考虑让SharedStore来生成Load目录路径
  100. ret.LoadedDirs = append(ret.LoadedDirs, utils.MakeLoadedPackagePath(u.userID, u.pkg.PackageID))
  101. }
  102. return ret, nil
  103. }
  104. func (u *CreateLoadUploader) Abort() {
  105. u.lock.Lock()
  106. defer u.lock.Unlock()
  107. if u.commited {
  108. return
  109. }
  110. u.commited = true
  111. u.distlock.Unlock()
  112. // TODO 可以考虑删除PackageID
  113. }

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