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.

download_package.go 4.3 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package cmd
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  8. "gitlink.org.cn/cloudream/common/pkgs/distlock"
  9. stgglb "gitlink.org.cn/cloudream/storage/common/globals"
  10. "gitlink.org.cn/cloudream/storage/common/pkgs/db/model"
  11. "gitlink.org.cn/cloudream/storage/common/pkgs/iterator"
  12. coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
  13. )
  14. type DownloadPackage struct {
  15. userID int64
  16. packageID int64
  17. outputPath string
  18. }
  19. type DownloadPackageContext struct {
  20. Distlock *distlock.Service
  21. }
  22. func NewDownloadPackage(userID int64, packageID int64, outputPath string) *DownloadPackage {
  23. return &DownloadPackage{
  24. userID: userID,
  25. packageID: packageID,
  26. outputPath: outputPath,
  27. }
  28. }
  29. func (t *DownloadPackage) Execute(ctx *DownloadPackageContext) error {
  30. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  31. if err != nil {
  32. return fmt.Errorf("new coordinator client: %w", err)
  33. }
  34. defer stgglb.CoordinatorMQPool.Release(coorCli)
  35. getPkgResp, err := coorCli.GetPackage(coormq.NewGetPackage(t.userID, t.packageID))
  36. if err != nil {
  37. return fmt.Errorf("getting package: %w", err)
  38. }
  39. var objIter iterator.DownloadingObjectIterator
  40. if getPkgResp.Redundancy.IsRepInfo() {
  41. objIter, err = t.downloadRep(ctx)
  42. } else {
  43. objIter, err = t.downloadEC(ctx, getPkgResp.Package)
  44. }
  45. if err != nil {
  46. return err
  47. }
  48. defer objIter.Close()
  49. return t.writeObject(objIter)
  50. }
  51. func (t *DownloadPackage) downloadRep(ctx *DownloadPackageContext) (iterator.DownloadingObjectIterator, error) {
  52. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  53. if err != nil {
  54. return nil, fmt.Errorf("new coordinator client: %w", err)
  55. }
  56. defer stgglb.CoordinatorMQPool.Release(coorCli)
  57. getObjsResp, err := coorCli.GetPackageObjects(coormq.NewGetPackageObjects(t.userID, t.packageID))
  58. if err != nil {
  59. return nil, fmt.Errorf("getting package objects: %w", err)
  60. }
  61. getObjRepDataResp, err := coorCli.GetPackageObjectRepData(coormq.NewGetPackageObjectRepData(t.packageID))
  62. if err != nil {
  63. return nil, fmt.Errorf("getting package object rep data: %w", err)
  64. }
  65. iter := iterator.NewRepObjectIterator(getObjsResp.Objects, getObjRepDataResp.Data, &iterator.DownloadContext{
  66. Distlock: ctx.Distlock,
  67. })
  68. return iter, nil
  69. }
  70. func (t *DownloadPackage) downloadEC(ctx *DownloadPackageContext, pkg model.Package) (iterator.DownloadingObjectIterator, error) {
  71. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  72. if err != nil {
  73. return nil, fmt.Errorf("new coordinator client: %w", err)
  74. }
  75. defer stgglb.CoordinatorMQPool.Release(coorCli)
  76. getObjsResp, err := coorCli.GetPackageObjects(coormq.NewGetPackageObjects(t.userID, t.packageID))
  77. if err != nil {
  78. return nil, fmt.Errorf("getting package objects: %w", err)
  79. }
  80. getObjECDataResp, err := coorCli.GetPackageObjectECData(coormq.NewGetPackageObjectECData(t.packageID))
  81. if err != nil {
  82. return nil, fmt.Errorf("getting package object ec data: %w", err)
  83. }
  84. var ecInfo cdssdk.ECRedundancyInfo
  85. if ecInfo, err = pkg.Redundancy.ToECInfo(); err != nil {
  86. return nil, fmt.Errorf("get ec redundancy info: %w", err)
  87. }
  88. getECResp, err := coorCli.GetECConfig(coormq.NewGetECConfig(ecInfo.ECName))
  89. if err != nil {
  90. return nil, fmt.Errorf("getting ec: %w", err)
  91. }
  92. iter := iterator.NewECObjectIterator(getObjsResp.Objects, getObjECDataResp.Data, ecInfo, getECResp.Config, &iterator.DownloadContext{
  93. Distlock: ctx.Distlock,
  94. })
  95. return iter, nil
  96. }
  97. func (t *DownloadPackage) writeObject(objIter iterator.DownloadingObjectIterator) error {
  98. for {
  99. objInfo, err := objIter.MoveNext()
  100. if err == iterator.ErrNoMoreItem {
  101. break
  102. }
  103. if err != nil {
  104. return err
  105. }
  106. err = func() error {
  107. defer objInfo.File.Close()
  108. fullPath := filepath.Join(t.outputPath, objInfo.Object.Path)
  109. dirPath := filepath.Dir(fullPath)
  110. if err := os.MkdirAll(dirPath, 0755); err != nil {
  111. return fmt.Errorf("creating object dir: %w", err)
  112. }
  113. outputFile, err := os.Create(fullPath)
  114. if err != nil {
  115. return fmt.Errorf("creating object file: %w", err)
  116. }
  117. defer outputFile.Close()
  118. _, err = io.Copy(outputFile, objInfo.File)
  119. if err != nil {
  120. return fmt.Errorf("copy object data to local file failed, err: %w", err)
  121. }
  122. return nil
  123. }()
  124. if err != nil {
  125. return err
  126. }
  127. }
  128. return nil
  129. }

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