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 6.4 kB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package ops2
  2. import (
  3. "fmt"
  4. "io"
  5. "github.com/samber/lo"
  6. "gitlink.org.cn/cloudream/common/pkgs/future"
  7. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/dag"
  8. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  9. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/utils"
  10. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  11. "gitlink.org.cn/cloudream/common/utils/io2"
  12. "gitlink.org.cn/cloudream/common/utils/sync2"
  13. "gitlink.org.cn/cloudream/storage/common/pkgs/ec"
  14. )
  15. func init() {
  16. // exec.UseOp[*ECReconstructAny]()
  17. // exec.UseOp[*ECReconstruct]()
  18. exec.UseOp[*ECMultiply]()
  19. }
  20. /*
  21. type ECReconstructAny struct {
  22. EC cdssdk.ECRedundancy `json:"ec"`
  23. Inputs []exec.VarID `json:"inputs"`
  24. Outputs []exec.VarID `json:"outputs"`
  25. InputBlockIndexes []int `json:"inputBlockIndexes"`
  26. OutputBlockIndexes []int `json:"outputBlockIndexes"`
  27. }
  28. func (o *ECReconstructAny) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
  29. rs, err := ec.NewStreamRs(o.EC.K, o.EC.N, o.EC.ChunkSize)
  30. if err != nil {
  31. return fmt.Errorf("new ec: %w", err)
  32. }
  33. err = exec.BindArrayVars(e, ctx.Context, inputs)
  34. if err != nil {
  35. return err
  36. }
  37. defer func() {
  38. for _, s := range o.Inputs {
  39. s.Stream.Close()
  40. }
  41. }()
  42. var inputs []io.Reader
  43. for _, s := range o.Inputs {
  44. inputs = append(inputs, s.Stream)
  45. }
  46. outputs := rs.ReconstructAny(inputs, o.InputBlockIndexes, o.OutputBlockIndexes)
  47. sem := semaphore.NewWeighted(int64(len(o.Outputs)))
  48. for i := range o.Outputs {
  49. sem.Acquire(ctx.Context, 1)
  50. o.Outputs[i].Stream = io2.AfterReadClosedOnce(outputs[i], func(closer io.ReadCloser) {
  51. sem.Release(1)
  52. })
  53. }
  54. e.PutVar(o.Outputs)
  55. return sem.Acquire(ctx.Context, int64(len(o.Outputs)))
  56. }
  57. type ECReconstruct struct {
  58. EC cdssdk.ECRedundancy `json:"ec"`
  59. Inputs []exec.VarID `json:"inputs"`
  60. Outputs []exec.VarID `json:"outputs"`
  61. InputBlockIndexes []int `json:"inputBlockIndexes"`
  62. }
  63. func (o *ECReconstruct) Execute(ctx context.Context, e *exec.Executor) error {
  64. rs, err := ec.NewStreamRs(o.EC.K, o.EC.N, o.EC.ChunkSize)
  65. if err != nil {
  66. return fmt.Errorf("new ec: %w", err)
  67. }
  68. err = exec.BindArrayVars(e, ctx, o.Inputs)
  69. if err != nil {
  70. return err
  71. }
  72. defer func() {
  73. for _, s := range o.Inputs {
  74. s.Stream.Close()
  75. }
  76. }()
  77. var inputs []io.Reader
  78. for _, s := range o.Inputs {
  79. inputs = append(inputs, s.Stream)
  80. }
  81. outputs := rs.ReconstructData(inputs, o.InputBlockIndexes)
  82. sem := semaphore.NewWeighted(int64(len(o.Outputs)))
  83. for i := range o.Outputs {
  84. sem.Acquire(ctx, 1)
  85. o.Outputs[i].Stream = io2.AfterReadClosedOnce(outputs[i], func(closer io.ReadCloser) {
  86. sem.Release(1)
  87. })
  88. }
  89. e.PutVar(o.Outputs)
  90. return sem.Acquire(ctx, int64(len(o.Outputs)))
  91. }
  92. */
  93. type ECMultiply struct {
  94. Coef [][]byte `json:"coef"`
  95. Inputs []exec.VarID `json:"inputs"`
  96. Outputs []exec.VarID `json:"outputs"`
  97. ChunkSize int `json:"chunkSize"`
  98. }
  99. func (o *ECMultiply) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
  100. inputs, err := exec.BindArray[*exec.StreamValue](e, ctx.Context, o.Inputs)
  101. if err != nil {
  102. return err
  103. }
  104. defer func() {
  105. for _, s := range inputs {
  106. s.Stream.Close()
  107. }
  108. }()
  109. outputWrs := make([]*io.PipeWriter, len(o.Outputs))
  110. outputVars := make([]*exec.StreamValue, len(o.Outputs))
  111. for i := range o.Outputs {
  112. rd, wr := io.Pipe()
  113. outputVars[i].Stream = rd
  114. outputWrs[i] = wr
  115. }
  116. fut := future.NewSetVoid()
  117. go func() {
  118. mul := ec.GaloisMultiplier().BuildGalois()
  119. inputChunks := make([][]byte, len(o.Inputs))
  120. for i := range o.Inputs {
  121. inputChunks[i] = make([]byte, o.ChunkSize)
  122. }
  123. outputChunks := make([][]byte, len(o.Outputs))
  124. for i := range o.Outputs {
  125. outputChunks[i] = make([]byte, o.ChunkSize)
  126. }
  127. for {
  128. err := sync2.ParallelDo(inputs, func(s *exec.StreamValue, i int) error {
  129. _, err := io.ReadFull(s.Stream, inputChunks[i])
  130. return err
  131. })
  132. if err == io.EOF {
  133. fut.SetVoid()
  134. return
  135. }
  136. if err != nil {
  137. fut.SetError(err)
  138. return
  139. }
  140. err = mul.Multiply(o.Coef, inputChunks, outputChunks)
  141. if err != nil {
  142. fut.SetError(err)
  143. return
  144. }
  145. for i := range o.Outputs {
  146. err := io2.WriteAll(outputWrs[i], outputChunks[i])
  147. if err != nil {
  148. fut.SetError(err)
  149. return
  150. }
  151. }
  152. }
  153. }()
  154. exec.PutArray(e, o.Outputs, outputVars)
  155. err = fut.Wait(ctx.Context)
  156. if err != nil {
  157. for _, wr := range outputWrs {
  158. wr.CloseWithError(err)
  159. }
  160. return err
  161. }
  162. for _, wr := range outputWrs {
  163. wr.Close()
  164. }
  165. return nil
  166. }
  167. func (o *ECMultiply) String() string {
  168. return fmt.Sprintf(
  169. "ECMultiply(coef=%v) (%v) -> (%v)",
  170. o.Coef,
  171. utils.FormatVarIDs(o.Inputs),
  172. utils.FormatVarIDs(o.Outputs),
  173. )
  174. }
  175. type ECMultiplyNode struct {
  176. dag.NodeBase
  177. EC cdssdk.ECRedundancy
  178. InputIndexes []int
  179. OutputIndexes []int
  180. }
  181. func (b *GraphNodeBuilder) NewECMultiply(ec cdssdk.ECRedundancy) *ECMultiplyNode {
  182. node := &ECMultiplyNode{
  183. EC: ec,
  184. }
  185. b.AddNode(node)
  186. return node
  187. }
  188. func (t *ECMultiplyNode) AddInput(str *dag.Var, dataIndex int) {
  189. t.InputIndexes = append(t.InputIndexes, dataIndex)
  190. idx := t.InputStreams().EnlargeOne()
  191. str.Connect(t, idx)
  192. }
  193. func (t *ECMultiplyNode) RemoveAllInputs() {
  194. for i, in := range t.InputStreams().RawArray() {
  195. in.Disconnect(t, i)
  196. }
  197. t.InputStreams().Resize(0)
  198. t.InputIndexes = nil
  199. }
  200. func (t *ECMultiplyNode) NewOutput(dataIndex int) *dag.Var {
  201. t.OutputIndexes = append(t.OutputIndexes, dataIndex)
  202. output := t.Graph().NewVar()
  203. t.OutputStreams().SetupNew(t, output)
  204. return output
  205. }
  206. func (t *ECMultiplyNode) GenerateOp() (exec.Op, error) {
  207. rs, err := ec.NewRs(t.EC.K, t.EC.N)
  208. if err != nil {
  209. return nil, err
  210. }
  211. coef, err := rs.GenerateMatrix(t.InputIndexes, t.OutputIndexes)
  212. if err != nil {
  213. return nil, err
  214. }
  215. return &ECMultiply{
  216. Coef: coef,
  217. Inputs: lo.Map(t.InputStreams().RawArray(), func(v *dag.Var, idx int) exec.VarID { return v.VarID }),
  218. Outputs: lo.Map(t.OutputStreams().RawArray(), func(v *dag.Var, idx int) exec.VarID { return v.VarID }),
  219. ChunkSize: t.EC.ChunkSize,
  220. }, nil
  221. }
  222. // func (t *MultiplyType) String() string {
  223. // return fmt.Sprintf("Multiply[]%v%v", formatStreamIO(node), formatValueIO(node))
  224. // }

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