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.

update.go 3.7 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
7 months ago
7 months ago
7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package uploader
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "path"
  7. "sync"
  8. "time"
  9. "github.com/samber/lo"
  10. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  11. "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
  12. "gitlink.org.cn/cloudream/jcs-pub/client/types"
  13. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2"
  14. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2"
  15. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser"
  16. )
  17. type UpdateUploader struct {
  18. uploader *Uploader
  19. pkgID types.PackageID
  20. targetSpace types.UserSpaceDetail
  21. // distMutex *distlock.Mutex
  22. loadToSpaces []types.UserSpaceDetail
  23. loadToPath []string
  24. successes []db.AddObjectEntry
  25. lock sync.Mutex
  26. commited bool
  27. }
  28. type UploadSpaceInfo struct {
  29. Space types.UserSpaceDetail
  30. Delay time.Duration
  31. IsSameLocation bool
  32. }
  33. type UpdateResult struct {
  34. // 上传成功的文件列表,Key为Path
  35. Objects map[string]types.Object
  36. }
  37. func (w *UpdateUploader) Upload(pat string, stream io.Reader) error {
  38. uploadTime := time.Now()
  39. ft := ioswitch2.NewFromTo()
  40. fromExec, hd := ioswitch2.NewFromDriver(ioswitch2.RawStream())
  41. ft.AddFrom(fromExec).
  42. AddTo(ioswitch2.NewToShardStore(*w.targetSpace.MasterHub, w.targetSpace, ioswitch2.RawStream(), "shardInfo"))
  43. for i, space := range w.loadToSpaces {
  44. ft.AddTo(ioswitch2.NewLoadToPublic(*space.MasterHub, space, path.Join(w.loadToPath[i], pat)))
  45. }
  46. plans := exec.NewPlanBuilder()
  47. err := parser.Parse(ft, plans)
  48. if err != nil {
  49. return fmt.Errorf("parsing plan: %w", err)
  50. }
  51. exeCtx := exec.NewExecContext()
  52. exec.SetValueByType(exeCtx, w.uploader.stgPool)
  53. exec := plans.Execute(exeCtx)
  54. exec.BeginWrite(io.NopCloser(stream), hd)
  55. ret, err := exec.Wait(context.TODO())
  56. if err != nil {
  57. return fmt.Errorf("executing plan: %w", err)
  58. }
  59. w.lock.Lock()
  60. defer w.lock.Unlock()
  61. // 记录上传结果
  62. shardInfo := ret["shardInfo"].(*ops2.ShardInfoValue)
  63. w.successes = append(w.successes, db.AddObjectEntry{
  64. Path: pat,
  65. Size: shardInfo.Size,
  66. FileHash: shardInfo.Hash,
  67. UploadTime: uploadTime,
  68. UserSpaceIDs: []types.UserSpaceID{w.targetSpace.UserSpace.UserSpaceID},
  69. })
  70. return nil
  71. }
  72. // 取消上传对象。必须在对象调用了Upload之后调用。
  73. func (w *UpdateUploader) CancelObject(path string) {
  74. w.lock.Lock()
  75. defer w.lock.Unlock()
  76. w.successes = lo.Reject(w.successes, func(e db.AddObjectEntry, i int) bool {
  77. return e.Path == path
  78. })
  79. }
  80. // 重命名对象。必须在对象调用了Upload之后调用。不会检查新路径是否已经存在,需由调用方去做保证。
  81. func (w *UpdateUploader) RenameObject(path string, newPath string) {
  82. w.lock.Lock()
  83. defer w.lock.Unlock()
  84. for i := range w.successes {
  85. if w.successes[i].Path == path {
  86. w.successes[i].Path = newPath
  87. break
  88. }
  89. }
  90. }
  91. func (w *UpdateUploader) Commit() (UpdateResult, error) {
  92. w.lock.Lock()
  93. defer w.lock.Unlock()
  94. if w.commited {
  95. return UpdateResult{}, fmt.Errorf("package already commited")
  96. }
  97. w.commited = true
  98. // defer w.distMutex.Unlock()
  99. var addedObjs []types.Object
  100. err := w.uploader.db.DoTx(func(tx db.SQLContext) error {
  101. var err error
  102. addedObjs, err = w.uploader.db.Object().BatchAdd(tx, w.pkgID, w.successes)
  103. return err
  104. })
  105. if err != nil {
  106. return UpdateResult{}, fmt.Errorf("adding objects: %w", err)
  107. }
  108. ret := UpdateResult{
  109. Objects: make(map[string]types.Object),
  110. }
  111. for _, entry := range addedObjs {
  112. ret.Objects[entry.Path] = entry
  113. }
  114. return ret, nil
  115. }
  116. func (w *UpdateUploader) Abort() {
  117. w.lock.Lock()
  118. defer w.lock.Unlock()
  119. if w.commited {
  120. return
  121. }
  122. w.commited = true
  123. // w.distMutex.Unlock()
  124. }

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