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.

ec.go 4.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package opt
  2. import (
  3. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/dag"
  4. "gitlink.org.cn/cloudream/common/utils/lo2"
  5. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2"
  6. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/ops2"
  7. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch2/parser/state"
  8. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/factory"
  9. "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
  10. cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
  11. )
  12. // 减少未使用的Multiply指令的输出流。如果减少到0,则删除该指令
  13. func RemoveUnusedMultiplyOutput(ctx *state.GenerateState) bool {
  14. changed := false
  15. dag.WalkOnlyType[*ops2.ECMultiplyNode](ctx.DAG.Graph, func(node *ops2.ECMultiplyNode) bool {
  16. outArr := node.OutputStreams().Slots.RawArray()
  17. for i2, out := range outArr {
  18. if out.Dst.Len() > 0 {
  19. continue
  20. }
  21. outArr[i2] = nil
  22. node.OutputIndexes[i2] = -2
  23. changed = true
  24. }
  25. node.OutputStreams().Slots.SetRawArray(lo2.RemoveAllDefault(outArr))
  26. node.OutputIndexes = lo2.RemoveAll(node.OutputIndexes, -2)
  27. // 如果所有输出流都被删除,则删除该指令
  28. if node.OutputStreams().Len() == 0 {
  29. node.RemoveAllInputs()
  30. ctx.DAG.RemoveNode(node)
  31. changed = true
  32. }
  33. return true
  34. })
  35. return changed
  36. }
  37. // 替换ECMultiply指令
  38. func UseECMultiplier(ctx *state.GenerateState) {
  39. dag.WalkOnlyType[*ops2.ECMultiplyNode](ctx.DAG.Graph, func(mulNode *ops2.ECMultiplyNode) bool {
  40. if mulNode.OutputStreams().Len() == 0 {
  41. return true
  42. }
  43. // 暂不支持编解码流的一部分
  44. if ctx.StreamRange.Offset != 0 || ctx.StreamRange.Length != nil {
  45. return true
  46. }
  47. var to *ioswitch2.ToShardStore
  48. var bwNodes []*ops2.BaseWriteNode
  49. // 所有的输出流必须有且只有一个相同的目的地
  50. // 暂时只支持分片存储
  51. for i := 0; i < mulNode.OutputStreams().Len(); i++ {
  52. if mulNode.OutputStreams().Get(i).Dst.Len() != 1 {
  53. return true
  54. }
  55. dstNode := mulNode.OutputStreams().Get(i).Dst.Get(0)
  56. swNode, ok := dstNode.(*ops2.BaseWriteNode)
  57. if !ok {
  58. return true
  59. }
  60. toShard, ok := swNode.To.(*ioswitch2.ToShardStore)
  61. if !ok {
  62. return true
  63. }
  64. if to == nil {
  65. to = toShard
  66. } else if to.Space.UserSpace.UserSpaceID != swNode.UserSpace.UserSpace.UserSpaceID {
  67. return true
  68. }
  69. bwNodes = append(bwNodes, swNode)
  70. }
  71. _, err := factory.GetBuilder(&to.Space).CreateECMultiplier(true)
  72. if err != nil {
  73. return true
  74. }
  75. // 每一个输入流都必须直接来自于存储服务,而且要支持通过HTTP读取文件
  76. var brNodes []*ops2.BaseReadDynNode
  77. var fromShards []*ioswitch2.FromShardStore
  78. for i := 0; i < mulNode.InputStreams().Len(); i++ {
  79. inNode := mulNode.InputStreams().Get(i).Src
  80. brNode, ok := inNode.(*ops2.BaseReadDynNode)
  81. if !ok {
  82. return true
  83. }
  84. fromShard, ok := brNode.From.(*ioswitch2.FromShardStore)
  85. if !ok {
  86. return true
  87. }
  88. store, err := factory.GetBuilder(&brNode.UserSpace).CreateShardStore(true)
  89. if err != nil {
  90. return true
  91. }
  92. _, ok = store.(types.HTTPShardRead)
  93. if !ok {
  94. return true
  95. }
  96. brNodes = append(brNodes, brNode)
  97. fromShards = append(fromShards, fromShard)
  98. }
  99. // 检查满足条件后,替换ECMultiply指令
  100. callMul := ctx.DAG.NewCallECMultiplier(to.Space)
  101. switch addr := to.Space.RecommendHub.Address.(type) {
  102. case *cortypes.HttpAddressInfo:
  103. callMul.Env().ToEnvWorker(&ioswitch2.HttpHubWorker{Hub: to.Space.RecommendHub})
  104. callMul.Env().Pinned = true
  105. case *cortypes.GRPCAddressInfo:
  106. callMul.Env().ToEnvWorker(&ioswitch2.HubWorker{Hub: to.Space.RecommendHub, Address: *addr})
  107. callMul.Env().Pinned = true
  108. default:
  109. return true
  110. }
  111. callMul.InitFrom(mulNode)
  112. for i, brNode := range brNodes {
  113. brNode.Output().Var().NotTo(mulNode)
  114. // 只有完全没有输出的ShardReadNode才可以被删除
  115. if brNode.Output().Var().Dst.Len() == 0 {
  116. ctx.DAG.RemoveNode(brNode)
  117. delete(ctx.FromNodes, brNode.From)
  118. }
  119. hbr := ctx.DAG.NewGetShardHTTPRequest(brNode.UserSpace, fromShards[i].FileHash)
  120. hbr.Env().CopyFrom(brNode.Env())
  121. hbr.HTTPRequestVar().ToSlot(callMul.HTTPRequestSlot(i))
  122. }
  123. for i, bwNode := range bwNodes {
  124. ctx.DAG.RemoveNode(bwNode)
  125. delete(ctx.ToNodes, bwNode.To)
  126. for _, dstSlot := range bwNode.FileInfoVar().ListDstSlots() {
  127. callMul.FileInfoVar(i).ToSlot(dstSlot)
  128. }
  129. }
  130. ctx.DAG.RemoveNode(mulNode)
  131. return true
  132. })
  133. }

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