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_ec_package.go 3.5 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package cmd
  2. import (
  3. "fmt"
  4. "github.com/samber/lo"
  5. stgsdk "gitlink.org.cn/cloudream/common/sdks/storage"
  6. stgglb "gitlink.org.cn/cloudream/storage/common/globals"
  7. "gitlink.org.cn/cloudream/storage/common/pkgs/db/model"
  8. "gitlink.org.cn/cloudream/storage/common/pkgs/distlock/reqbuilder"
  9. "gitlink.org.cn/cloudream/storage/common/pkgs/iterator"
  10. coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
  11. )
  12. type UpdateECPackage struct {
  13. userID int64
  14. packageID int64
  15. objectIter iterator.UploadingObjectIterator
  16. }
  17. type UpdateECPackageResult struct {
  18. ObjectResults []ECObjectUploadResult
  19. }
  20. func NewUpdateECPackage(userID int64, packageID int64, objIter iterator.UploadingObjectIterator) *UpdateECPackage {
  21. return &UpdateECPackage{
  22. userID: userID,
  23. packageID: packageID,
  24. objectIter: objIter,
  25. }
  26. }
  27. func (t *UpdateECPackage) Execute(ctx *UpdatePackageContext) (*UpdateECPackageResult, error) {
  28. defer t.objectIter.Close()
  29. coorCli, err := stgglb.CoordinatorMQPool.Acquire()
  30. if err != nil {
  31. return nil, fmt.Errorf("new coordinator client: %w", err)
  32. }
  33. mutex, err := reqbuilder.NewBuilder().
  34. Metadata().
  35. // 用于查询可用的上传节点
  36. Node().ReadAny().
  37. // 用于创建包信息
  38. Package().WriteOne(t.packageID).
  39. // 用于创建包中的文件的信息
  40. Object().CreateAny().
  41. // 用于设置EC配置
  42. ObjectBlock().CreateAny().
  43. // 用于创建Cache记录
  44. Cache().CreateAny().
  45. MutexLock(ctx.Distlock)
  46. if err != nil {
  47. return nil, fmt.Errorf("acquire locks failed, err: %w", err)
  48. }
  49. defer mutex.Unlock()
  50. getPkgResp, err := coorCli.GetPackage(coormq.NewGetPackage(t.userID, t.packageID))
  51. if err != nil {
  52. return nil, fmt.Errorf("getting package: %w", err)
  53. }
  54. getUserNodesResp, err := coorCli.GetUserNodes(coormq.NewGetUserNodes(t.userID))
  55. if err != nil {
  56. return nil, fmt.Errorf("getting user nodes: %w", err)
  57. }
  58. findCliLocResp, err := coorCli.FindClientLocation(coormq.NewFindClientLocation(stgglb.Local.ExternalIP))
  59. if err != nil {
  60. return nil, fmt.Errorf("finding client location: %w", err)
  61. }
  62. nodeInfos := lo.Map(getUserNodesResp.Nodes, func(node model.Node, index int) UploadNodeInfo {
  63. return UploadNodeInfo{
  64. Node: node,
  65. IsSameLocation: node.LocationID == findCliLocResp.Location.LocationID,
  66. }
  67. })
  68. var ecInfo stgsdk.ECRedundancyInfo
  69. if ecInfo, err = getPkgResp.Package.Redundancy.ToECInfo(); err != nil {
  70. return nil, fmt.Errorf("get ec redundancy info: %w", err)
  71. }
  72. getECResp, err := coorCli.GetECConfig(coormq.NewGetECConfig(ecInfo.ECName))
  73. if err != nil {
  74. return nil, fmt.Errorf("getting ec: %w", err)
  75. }
  76. // 给上传节点的IPFS加锁
  77. ipfsReqBlder := reqbuilder.NewBuilder()
  78. // 如果本地的IPFS也是存储系统的一个节点,那么从本地上传时,需要加锁
  79. if stgglb.Local.NodeID != nil {
  80. ipfsReqBlder.IPFS().CreateAnyRep(*stgglb.Local.NodeID)
  81. }
  82. for _, node := range nodeInfos {
  83. if stgglb.Local.NodeID != nil && node.Node.NodeID == *stgglb.Local.NodeID {
  84. continue
  85. }
  86. ipfsReqBlder.IPFS().CreateAnyRep(node.Node.NodeID)
  87. }
  88. // 防止上传的副本被清除
  89. ipfsMutex, err := ipfsReqBlder.MutexLock(ctx.Distlock)
  90. if err != nil {
  91. return nil, fmt.Errorf("acquire locks failed, err: %w", err)
  92. }
  93. defer ipfsMutex.Unlock()
  94. rets, err := uploadAndUpdateECPackage(t.packageID, t.objectIter, nodeInfos, ecInfo, getECResp.Config)
  95. if err != nil {
  96. return nil, err
  97. }
  98. return &UpdateECPackageResult{
  99. ObjectResults: rets,
  100. }, nil
  101. }

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