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.0 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
7 months ago
7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. "gitlink.org.cn/cloudream/storage2/client/internal/db"
  11. "gitlink.org.cn/cloudream/storage2/client/types"
  12. "gitlink.org.cn/cloudream/storage2/common/pkgs/distlock"
  13. "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2"
  14. "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2/ops2"
  15. "gitlink.org.cn/cloudream/storage2/common/pkgs/ioswitch2/parser"
  16. )
  17. type CreateLoadUploader struct {
  18. pkg types.Package
  19. targetSpaces []types.UserSpaceDetail
  20. loadRoots []string
  21. uploader *Uploader
  22. distlock *distlock.Mutex
  23. successes []db.AddObjectEntry
  24. lock sync.Mutex
  25. commited bool
  26. }
  27. type CreateLoadResult struct {
  28. Package types.Package
  29. Objects map[string]types.Object
  30. }
  31. func (u *CreateLoadUploader) Upload(pa string, size int64, stream io.Reader) error {
  32. uploadTime := time.Now()
  33. spaceIDs := make([]types.UserSpaceID, 0, len(u.targetSpaces))
  34. ft := ioswitch2.FromTo{}
  35. fromExec, hd := ioswitch2.NewFromDriver(ioswitch2.RawStream())
  36. ft.AddFrom(fromExec)
  37. for i, space := range u.targetSpaces {
  38. ft.AddTo(ioswitch2.NewToShardStore(*space.MasterHub, space, ioswitch2.RawStream(), "fileHash"))
  39. ft.AddTo(ioswitch2.NewLoadToPublic(*space.MasterHub, space, path.Join(u.loadRoots[i], pa)))
  40. spaceIDs = append(spaceIDs, space.UserSpace.UserSpaceID)
  41. }
  42. plans := exec.NewPlanBuilder()
  43. err := parser.Parse(ft, plans)
  44. if err != nil {
  45. return fmt.Errorf("parsing plan: %w", err)
  46. }
  47. exeCtx := exec.NewExecContext()
  48. exec.SetValueByType(exeCtx, u.uploader.stgPool)
  49. exec := plans.Execute(exeCtx)
  50. exec.BeginWrite(io.NopCloser(stream), hd)
  51. ret, err := exec.Wait(context.TODO())
  52. if err != nil {
  53. return fmt.Errorf("executing plan: %w", err)
  54. }
  55. u.lock.Lock()
  56. defer u.lock.Unlock()
  57. // 记录上传结果
  58. fileHash := ret["fileHash"].(*ops2.ShardInfoValue).Hash
  59. u.successes = append(u.successes, db.AddObjectEntry{
  60. Path: pa,
  61. Size: size,
  62. FileHash: fileHash,
  63. UploadTime: uploadTime,
  64. UserSpaceIDs: spaceIDs,
  65. })
  66. return nil
  67. }
  68. func (u *CreateLoadUploader) Commit() (CreateLoadResult, error) {
  69. u.lock.Lock()
  70. defer u.lock.Unlock()
  71. if u.commited {
  72. return CreateLoadResult{}, fmt.Errorf("package already commited")
  73. }
  74. u.commited = true
  75. defer u.distlock.Unlock()
  76. var addedObjs []types.Object
  77. err := u.uploader.db.DoTx(func(tx db.SQLContext) error {
  78. var err error
  79. addedObjs, err = u.uploader.db.Object().BatchAdd(tx, u.pkg.PackageID, u.successes)
  80. return err
  81. })
  82. if err != nil {
  83. return CreateLoadResult{}, fmt.Errorf("adding objects: %w", err)
  84. }
  85. ret := CreateLoadResult{
  86. Package: u.pkg,
  87. Objects: make(map[string]types.Object),
  88. }
  89. for _, entry := range addedObjs {
  90. ret.Objects[entry.Path] = entry
  91. }
  92. return ret, nil
  93. }
  94. func (u *CreateLoadUploader) Abort() {
  95. u.lock.Lock()
  96. defer u.lock.Unlock()
  97. if u.commited {
  98. return
  99. }
  100. u.commited = true
  101. u.distlock.Unlock()
  102. // TODO 可以考虑删除PackageID
  103. }

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