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.

plan_builder.go 4.3 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package plans
  2. import (
  3. "fmt"
  4. "github.com/google/uuid"
  5. "gitlink.org.cn/cloudream/storage/common/pkgs/db/model"
  6. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch"
  7. "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/ops"
  8. )
  9. type StreamInfo struct {
  10. ID ioswitch.StreamID
  11. }
  12. type PlanBuilder struct {
  13. streams []*StreamInfo
  14. agentPlans map[int64]*AgentPlanBuilder
  15. }
  16. func (b *PlanBuilder) Build() (*ComposedPlan, error) {
  17. planID := uuid.NewString()
  18. var agentPlans []AgentPlan
  19. for _, b := range b.agentPlans {
  20. plan, err := b.Build(ioswitch.PlanID(planID))
  21. if err != nil {
  22. return nil, err
  23. }
  24. agentPlans = append(agentPlans, plan)
  25. }
  26. return &ComposedPlan{
  27. ID: ioswitch.PlanID(planID),
  28. AgentPlans: agentPlans,
  29. }, nil
  30. }
  31. func (b *PlanBuilder) newStream() *StreamInfo {
  32. str := &StreamInfo{
  33. ID: ioswitch.StreamID(fmt.Sprintf("%d", len(b.streams)+1)),
  34. }
  35. b.streams = append(b.streams, str)
  36. return str
  37. }
  38. func NewPlanBuilder() PlanBuilder {
  39. return PlanBuilder{
  40. agentPlans: make(map[int64]*AgentPlanBuilder),
  41. }
  42. }
  43. func (b *PlanBuilder) FromExecutor() *FromExecutorStream {
  44. return &FromExecutorStream{
  45. owner: b,
  46. info: b.newStream(),
  47. }
  48. }
  49. func (b *PlanBuilder) AtAgent(node model.Node) *AgentPlanBuilder {
  50. agtPlan, ok := b.agentPlans[node.NodeID]
  51. if !ok {
  52. agtPlan = &AgentPlanBuilder{
  53. owner: b,
  54. node: node,
  55. }
  56. b.agentPlans[node.NodeID] = agtPlan
  57. }
  58. return agtPlan
  59. }
  60. type FromExecutorStream struct {
  61. owner *PlanBuilder
  62. info *StreamInfo
  63. toNode *model.Node
  64. }
  65. func (s *FromExecutorStream) ToNode(node model.Node) *AgentStream {
  66. s.toNode = &node
  67. return &AgentStream{
  68. owner: s.owner.AtAgent(node),
  69. info: s.info,
  70. }
  71. }
  72. type ToExecutorStream struct {
  73. info *StreamInfo
  74. fromNode *model.Node
  75. }
  76. type AgentStream struct {
  77. owner *AgentPlanBuilder
  78. info *StreamInfo
  79. }
  80. func (s *AgentStream) IPFSWrite(resultKey string) {
  81. s.owner.ops = append(s.owner.ops, &ops.IPFSWrite{
  82. Input: s.info.ID,
  83. ResultKey: resultKey,
  84. })
  85. }
  86. func (b *AgentStream) ChunkSplit(chunkSize int, streamCount int, paddingZeros bool) *MultiStream {
  87. mstr := &MultiStream{}
  88. var outputStrIDs []ioswitch.StreamID
  89. for i := 0; i < streamCount; i++ {
  90. info := b.owner.owner.newStream()
  91. mstr.Streams = append(mstr.Streams, &AgentStream{
  92. owner: b.owner,
  93. info: info,
  94. })
  95. outputStrIDs = append(outputStrIDs, info.ID)
  96. }
  97. b.owner.ops = append(b.owner.ops, &ops.ChunkedSplit{
  98. InputID: b.info.ID,
  99. OutputIDs: outputStrIDs,
  100. ChunkSize: chunkSize,
  101. StreamCount: streamCount,
  102. PaddingZeros: paddingZeros,
  103. })
  104. return mstr
  105. }
  106. func (s *AgentStream) ToExecutor() *ToExecutorStream {
  107. return &ToExecutorStream{
  108. info: s.info,
  109. fromNode: &s.owner.node,
  110. }
  111. }
  112. type AgentPlanBuilder struct {
  113. owner *PlanBuilder
  114. node model.Node
  115. ops []ioswitch.Op
  116. }
  117. func (b *AgentPlanBuilder) IPFSRead(fileHash string) *AgentStream {
  118. agtStr := &AgentStream{
  119. owner: b,
  120. info: b.owner.newStream(),
  121. }
  122. b.ops = append(b.ops, &ops.IPFSRead{
  123. Output: agtStr.info.ID,
  124. FileHash: fileHash,
  125. })
  126. return agtStr
  127. }
  128. func (b *AgentPlanBuilder) Join(length int64, streams ...*AgentStream) *AgentStream {
  129. agtStr := &AgentStream{
  130. owner: b,
  131. info: b.owner.newStream(),
  132. }
  133. var inputStrIDs []ioswitch.StreamID
  134. for _, str := range streams {
  135. inputStrIDs = append(inputStrIDs, str.info.ID)
  136. }
  137. b.ops = append(b.ops, &ops.Join{
  138. InputIDs: inputStrIDs,
  139. OutputID: agtStr.info.ID,
  140. Length: length,
  141. })
  142. return agtStr
  143. }
  144. func (b *AgentPlanBuilder) ChunkJoin(chunkSize int, streams ...*AgentStream) *AgentStream {
  145. agtStr := &AgentStream{
  146. owner: b,
  147. info: b.owner.newStream(),
  148. }
  149. var inputStrIDs []ioswitch.StreamID
  150. for _, str := range streams {
  151. inputStrIDs = append(inputStrIDs, str.info.ID)
  152. }
  153. b.ops = append(b.ops, &ops.ChunkedJoin{
  154. InputIDs: inputStrIDs,
  155. OutputID: agtStr.info.ID,
  156. ChunkSize: chunkSize,
  157. })
  158. return agtStr
  159. }
  160. func (b *AgentPlanBuilder) Build(planID ioswitch.PlanID) (AgentPlan, error) {
  161. plan := ioswitch.Plan{
  162. ID: planID,
  163. Ops: b.ops,
  164. }
  165. return AgentPlan{
  166. Plan: plan,
  167. Node: b.node,
  168. }, nil
  169. }
  170. type MultiStream struct {
  171. Streams []*AgentStream
  172. }
  173. func (m *MultiStream) Count() int {
  174. return len(m.Streams)
  175. }
  176. func (m *MultiStream) Stream(index int) *AgentStream {
  177. return m.Streams[index]
  178. }

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