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

7 months ago
5 months ago
7 months ago
7 months ago
7 months ago
5 months ago
6 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
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package uploader
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "sync"
  7. "time"
  8. "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
  9. "gitlink.org.cn/cloudream/jcs-pub/client/types"
  10. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch/exec"
  11. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2"
  12. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2"
  13. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser"
  14. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/publock"
  15. )
  16. type CreateUploader struct {
  17. pkg types.Package
  18. targetSpaces []types.UserSpaceDetail
  19. copyRoots []types.JPath
  20. uploader *Uploader
  21. pubLock *publock.Mutex
  22. successes []db.AddObjectEntry
  23. lock sync.Mutex
  24. commited bool
  25. }
  26. type CreateUploadResult struct {
  27. Package types.Package
  28. Objects map[string]types.Object
  29. }
  30. func (u *CreateUploader) Upload(pa types.JPath, stream io.Reader, opts ...UploadOption) error {
  31. opt := UploadOption{}
  32. if len(opts) > 0 {
  33. opt = opts[0]
  34. }
  35. if opt.CreateTime.IsZero() {
  36. opt.CreateTime = time.Now()
  37. }
  38. spaceIDs := make([]types.UserSpaceID, 0, len(u.targetSpaces))
  39. ft := ioswitch2.FromTo{}
  40. fromExec, hd := ioswitch2.NewFromDriver(ioswitch2.RawStream())
  41. ft.AddFrom(fromExec)
  42. for i, space := range u.targetSpaces {
  43. space2 := space
  44. space2.RecommendHub = nil
  45. ft.AddTo(ioswitch2.NewToShardStore(space2, ioswitch2.RawStream(), "shardInfo"))
  46. ft.AddTo(ioswitch2.NewToBaseStore(space2, u.copyRoots[i].ConcatNew(pa)))
  47. spaceIDs = append(spaceIDs, space2.UserSpace.UserSpaceID)
  48. }
  49. plans := exec.NewPlanBuilder()
  50. err := parser.Parse(ft, plans)
  51. if err != nil {
  52. return fmt.Errorf("parsing plan: %w", err)
  53. }
  54. exeCtx := exec.NewExecContext()
  55. exec.SetValueByType(exeCtx, u.uploader.stgPool)
  56. exec := plans.Execute(exeCtx)
  57. exec.BeginWrite(io.NopCloser(stream), hd)
  58. ret, err := exec.Wait(context.TODO())
  59. if err != nil {
  60. return fmt.Errorf("executing plan: %w", err)
  61. }
  62. u.lock.Lock()
  63. defer u.lock.Unlock()
  64. // 记录上传结果
  65. shardInfo := ret.Get("fileHash").(*ops2.FileInfoValue)
  66. u.successes = append(u.successes, db.AddObjectEntry{
  67. Path: pa.String(),
  68. Size: shardInfo.Size,
  69. FileHash: shardInfo.Hash,
  70. CreateTime: opt.CreateTime,
  71. UserSpaceIDs: spaceIDs,
  72. })
  73. return nil
  74. }
  75. func (u *CreateUploader) Commit() (CreateUploadResult, error) {
  76. u.lock.Lock()
  77. defer u.lock.Unlock()
  78. if u.commited {
  79. return CreateUploadResult{}, fmt.Errorf("package already commited")
  80. }
  81. u.commited = true
  82. defer u.pubLock.Unlock()
  83. var addedObjs []types.Object
  84. err := u.uploader.db.DoTx(func(tx db.SQLContext) error {
  85. var err error
  86. addedObjs, err = u.uploader.db.Object().BatchAdd(tx, u.pkg.PackageID, u.successes)
  87. return err
  88. })
  89. if err != nil {
  90. return CreateUploadResult{}, fmt.Errorf("adding objects: %w", err)
  91. }
  92. ret := CreateUploadResult{
  93. Package: u.pkg,
  94. Objects: make(map[string]types.Object),
  95. }
  96. for _, entry := range addedObjs {
  97. ret.Objects[entry.Path] = entry
  98. }
  99. return ret, nil
  100. }
  101. func (u *CreateUploader) Abort() {
  102. u.lock.Lock()
  103. defer u.lock.Unlock()
  104. if u.commited {
  105. return
  106. }
  107. u.commited = true
  108. u.pubLock.Unlock()
  109. db2 := u.uploader.db
  110. db.DoTx10(db2, db2.Package().DeleteComplete, u.pkg.PackageID)
  111. }

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