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_rep_package.go 3.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package cmd
  2. import (
  3. "fmt"
  4. "github.com/samber/lo"
  5. "gitlink.org.cn/cloudream/common/pkgs/distlock/reqbuilder"
  6. mysort "gitlink.org.cn/cloudream/common/utils/sort"
  7. "gitlink.org.cn/cloudream/storage-common/globals"
  8. "gitlink.org.cn/cloudream/storage-common/pkgs/db/model"
  9. "gitlink.org.cn/cloudream/storage-common/pkgs/iterator"
  10. coormq "gitlink.org.cn/cloudream/storage-common/pkgs/mq/coordinator"
  11. )
  12. type UpdateRepPackage struct {
  13. userID int64
  14. packageID int64
  15. objectIter iterator.UploadingObjectIterator
  16. }
  17. type UpdateNodeInfo struct {
  18. UploadNodeInfo
  19. HasOldObject bool
  20. }
  21. type UpdateRepPackageResult struct {
  22. ObjectResults []RepObjectUploadResult
  23. }
  24. func NewUpdateRepPackage(userID int64, packageID int64, objectIter iterator.UploadingObjectIterator) *UpdateRepPackage {
  25. return &UpdateRepPackage{
  26. userID: userID,
  27. packageID: packageID,
  28. objectIter: objectIter,
  29. }
  30. }
  31. func (t *UpdateRepPackage) Execute(ctx *UpdatePackageContext) (*UpdateRepPackageResult, error) {
  32. defer t.objectIter.Close()
  33. coorCli, err := globals.CoordinatorMQPool.Acquire()
  34. if err != nil {
  35. return nil, fmt.Errorf("new coordinator client: %w", err)
  36. }
  37. /*
  38. TODO2
  39. reqBlder := reqbuilder.NewBuilder()
  40. // 如果本地的IPFS也是存储系统的一个节点,那么从本地上传时,需要加锁
  41. if t.uploadConfig.LocalNodeID != nil {
  42. reqBlder.IPFS().CreateAnyRep(*t.uploadConfig.LocalNodeID)
  43. }
  44. // TODO2
  45. mutex, err := reqBlder.
  46. Metadata().
  47. // 用于判断用户是否有对象的权限
  48. UserBucket().ReadAny().
  49. // 用于读取、修改对象信息
  50. Object().WriteOne(t.objectID).
  51. // 用于更新Rep配置
  52. ObjectRep().WriteOne(t.objectID).
  53. // 用于查询可用的上传节点
  54. Node().ReadAny().
  55. // 用于创建Cache记录
  56. Cache().CreateAny().
  57. // 用于修改Move此Object的记录的状态
  58. StorageObject().WriteAny().
  59. MutexLock(ctx.DistLock())
  60. if err != nil {
  61. return fmt.Errorf("acquire locks failed, err: %w", err)
  62. }
  63. defer mutex.Unlock()
  64. */
  65. getUserNodesResp, err := coorCli.GetUserNodes(coormq.NewGetUserNodes(t.userID))
  66. if err != nil {
  67. return nil, fmt.Errorf("getting user nodes: %w", err)
  68. }
  69. findCliLocResp, err := coorCli.FindClientLocation(coormq.NewFindClientLocation(globals.Local.ExternalIP))
  70. if err != nil {
  71. return nil, fmt.Errorf("finding client location: %w", err)
  72. }
  73. nodeInfos := lo.Map(getUserNodesResp.Nodes, func(node model.Node, index int) UpdateNodeInfo {
  74. return UpdateNodeInfo{
  75. UploadNodeInfo: UploadNodeInfo{
  76. Node: node,
  77. IsSameLocation: node.LocationID == findCliLocResp.Location.LocationID,
  78. },
  79. }
  80. })
  81. // 上传文件的方式优先级:
  82. // 1. 本地IPFS
  83. // 2. 包含了旧文件,且与客户端在同地域的节点
  84. // 3. 不在同地域,但包含了旧文件的节点
  85. // 4. 同地域节点
  86. // TODO 需要考虑在多文件的情况下的规则
  87. uploadNode := t.chooseUploadNode(nodeInfos)
  88. // 防止上传的副本被清除
  89. mutex2, err := reqbuilder.NewBuilder().
  90. IPFS().CreateAnyRep(uploadNode.Node.NodeID).
  91. MutexLock(ctx.Distlock)
  92. if err != nil {
  93. return nil, fmt.Errorf("acquire locks failed, err: %w", err)
  94. }
  95. defer mutex2.Unlock()
  96. rets, err := uploadAndUpdateRepPackage(t.packageID, t.objectIter, uploadNode.UploadNodeInfo)
  97. if err != nil {
  98. return nil, err
  99. }
  100. return &UpdateRepPackageResult{
  101. ObjectResults: rets,
  102. }, nil
  103. }
  104. // chooseUploadNode 选择一个上传文件的节点
  105. // 1. 从与当前客户端相同地域的节点中随机选一个
  106. // 2. 没有用的话从所有节点中随机选一个
  107. func (t *UpdateRepPackage) chooseUploadNode(nodes []UpdateNodeInfo) UpdateNodeInfo {
  108. mysort.Sort(nodes, func(left, right UpdateNodeInfo) int {
  109. v := -mysort.CmpBool(left.HasOldObject, right.HasOldObject)
  110. if v != 0 {
  111. return v
  112. }
  113. return -mysort.CmpBool(left.IsSameLocation, right.IsSameLocation)
  114. })
  115. return nodes[0]
  116. }

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