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.

chunked.go 3.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package ops
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "github.com/samber/lo"
  7. "gitlink.org.cn/cloudream/common/pkgs/future"
  8. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/dag"
  9. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  10. "gitlink.org.cn/cloudream/common/utils/io2"
  11. "golang.org/x/sync/semaphore"
  12. )
  13. func init() {
  14. OpUnion.AddT((*ChunkedSplit)(nil))
  15. OpUnion.AddT((*ChunkedJoin)(nil))
  16. }
  17. type ChunkedSplit struct {
  18. Input *exec.StreamVar `json:"input"`
  19. Outputs []*exec.StreamVar `json:"outputs"`
  20. ChunkSize int `json:"chunkSize"`
  21. PaddingZeros bool `json:"paddingZeros"`
  22. }
  23. func (o *ChunkedSplit) Execute(ctx context.Context, e *exec.Executor) error {
  24. err := e.BindVars(ctx, o.Input)
  25. if err != nil {
  26. return err
  27. }
  28. defer o.Input.Stream.Close()
  29. outputs := io2.ChunkedSplit(o.Input.Stream, o.ChunkSize, len(o.Outputs), io2.ChunkedSplitOption{
  30. PaddingZeros: o.PaddingZeros,
  31. })
  32. sem := semaphore.NewWeighted(int64(len(outputs)))
  33. for i := range outputs {
  34. sem.Acquire(ctx, 1)
  35. o.Outputs[i].Stream = io2.AfterReadClosedOnce(outputs[i], func(closer io.ReadCloser) {
  36. sem.Release(1)
  37. })
  38. }
  39. exec.PutArrayVars(e, o.Outputs)
  40. return sem.Acquire(ctx, int64(len(outputs)))
  41. }
  42. type ChunkedJoin struct {
  43. Inputs []*exec.StreamVar `json:"inputs"`
  44. Output *exec.StreamVar `json:"output"`
  45. ChunkSize int `json:"chunkSize"`
  46. }
  47. func (o *ChunkedJoin) Execute(ctx context.Context, e *exec.Executor) error {
  48. err := exec.BindArrayVars(e, ctx, o.Inputs)
  49. if err != nil {
  50. return err
  51. }
  52. var strReaders []io.Reader
  53. for _, s := range o.Inputs {
  54. strReaders = append(strReaders, s.Stream)
  55. }
  56. defer func() {
  57. for _, str := range o.Inputs {
  58. str.Stream.Close()
  59. }
  60. }()
  61. fut := future.NewSetVoid()
  62. o.Output.Stream = io2.AfterReadClosedOnce(io2.BufferedChunkedJoin(strReaders, o.ChunkSize), func(closer io.ReadCloser) {
  63. fut.SetVoid()
  64. })
  65. e.PutVars(o.Output)
  66. return fut.Wait(ctx)
  67. }
  68. type ChunkedSplitType struct {
  69. OutputCount int
  70. ChunkSize int
  71. }
  72. func (t *ChunkedSplitType) InitNode(node *Node) {
  73. dag.NodeDeclareInputStream(node, 1)
  74. for i := 0; i < t.OutputCount; i++ {
  75. dag.NodeNewOutputStream(node, VarProps{})
  76. }
  77. }
  78. func (t *ChunkedSplitType) GenerateOp(op *Node, blder *exec.PlanBuilder) error {
  79. addOpByEnv(&ChunkedSplit{
  80. Input: op.InputStreams[0].Props.Var.(*exec.StreamVar),
  81. Outputs: lo.Map(op.OutputStreams, func(v *StreamVar, idx int) *exec.StreamVar {
  82. return v.Props.Var.(*exec.StreamVar)
  83. }),
  84. ChunkSize: t.ChunkSize,
  85. PaddingZeros: true,
  86. }, op.Env, blder)
  87. return nil
  88. }
  89. func (t *ChunkedSplitType) String(node *Node) string {
  90. return fmt.Sprintf("ChunkedSplit[%v]", t.ChunkSize, formatStreamIO(node), formatValueIO(node))
  91. }
  92. type ChunkedJoinType struct {
  93. InputCount int
  94. ChunkSize int
  95. }
  96. func (t *ChunkedJoinType) InitNode(node *Node) {
  97. dag.NodeDeclareInputStream(node, t.InputCount)
  98. dag.NodeNewOutputStream(node, VarProps{})
  99. }
  100. func (t *ChunkedJoinType) GenerateOp(op *Node, blder *exec.PlanBuilder) error {
  101. addOpByEnv(&ChunkedJoin{
  102. Inputs: lo.Map(op.InputStreams, func(v *StreamVar, idx int) *exec.StreamVar {
  103. return v.Props.Var.(*exec.StreamVar)
  104. }),
  105. Output: op.OutputStreams[0].Props.Var.(*exec.StreamVar),
  106. ChunkSize: t.ChunkSize,
  107. }, op.Env, blder)
  108. return nil
  109. }
  110. func (t *ChunkedJoinType) String(node *Node) string {
  111. return fmt.Sprintf("ChunkedJoin[%v]", t.ChunkSize, formatStreamIO(node), formatValueIO(node))
  112. }

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