|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- package ops2
-
- import (
- "fmt"
- "io"
-
- "gitlink.org.cn/cloudream/common/pkgs/future"
- "gitlink.org.cn/cloudream/common/utils/io2"
- "gitlink.org.cn/cloudream/common/utils/sync2"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ec"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch/dag"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch/exec"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/ioswitch/utils"
- "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/pool"
- stgtypes "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
- jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types"
- )
-
- func init() {
- exec.UseOp[*ECMultiply]()
-
- exec.UseOp[*CallECMultiplier]()
- }
-
- type ECMultiply struct {
- Coef [][]byte `json:"coef"`
- Inputs []exec.VarID `json:"inputs"`
- Outputs []exec.VarID `json:"outputs"`
- ChunkSize int `json:"chunkSize"`
- }
-
- func (o *ECMultiply) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
- inputs, err := exec.BindArray[*exec.StreamValue](e, ctx.Context, o.Inputs)
- if err != nil {
- return err
- }
- defer func() {
- for _, s := range inputs {
- s.Stream.Close()
- }
- }()
-
- outputWrs := make([]*io.PipeWriter, len(o.Outputs))
- outputVars := make([]*exec.StreamValue, len(o.Outputs))
-
- for i := range o.Outputs {
- rd, wr := io.Pipe()
- outputVars[i] = &exec.StreamValue{Stream: rd}
- outputWrs[i] = wr
- }
-
- /// !!! 缓冲区大小必须是ChunkSize大小,因为Chunk数据很有可能来自于一个被Split的完整文件,此时必须保证按顺序读取每一个Chunk的数据 !!!
-
- inputChunks := make([][]byte, len(o.Inputs))
- for i := range o.Inputs {
- inputChunks[i] = make([]byte, o.ChunkSize)
- }
-
- // 输出用两个缓冲轮换
- outputBufPool := sync2.NewBucketPool[[][]byte]()
- for i := 0; i < 2; i++ {
- outputChunks := make([][]byte, len(o.Outputs))
- for i := range o.Outputs {
- outputChunks[i] = make([]byte, o.ChunkSize)
- }
- outputBufPool.PutEmpty(outputChunks)
- }
-
- fut := future.NewSetVoid()
- go func() {
- mul := ec.GaloisMultiplier().BuildGalois()
- defer outputBufPool.Close()
- for {
- err := sync2.ParallelDo(inputs, func(s *exec.StreamValue, i int) error {
- _, err := io.ReadFull(s.Stream, inputChunks[i])
- return err
- })
- if err == io.EOF {
- return
- }
- if err != nil {
- fut.SetError(err)
- return
- }
-
- outputBuf, ok := outputBufPool.GetEmpty()
- if !ok {
- return
- }
-
- err = mul.Multiply(o.Coef, inputChunks, outputBuf)
- if err != nil {
- fut.SetError(err)
- return
- }
-
- outputBufPool.PutFilled(outputBuf)
- }
- }()
-
- go func() {
- defer outputBufPool.Close()
-
- for {
- outputChunks, ok := outputBufPool.GetFilled()
- if !ok {
- fut.SetVoid()
- return
- }
-
- for i := range o.Outputs {
- err := io2.WriteAll(outputWrs[i], outputChunks[i])
- if err != nil {
- fut.SetError(err)
- return
- }
- }
-
- outputBufPool.PutEmpty(outputChunks)
- }
- }()
-
- exec.PutArray(e, o.Outputs, outputVars)
-
- err = fut.Wait(ctx.Context)
- if err != nil {
- for _, wr := range outputWrs {
- wr.CloseWithError(err)
- }
- return err
- }
-
- for _, wr := range outputWrs {
- wr.Close()
- }
- return nil
- }
-
- func (o *ECMultiply) String() string {
- return fmt.Sprintf(
- "ECMultiply(coef=%v) (%v) -> (%v)",
- o.Coef,
- utils.FormatVarIDs(o.Inputs),
- utils.FormatVarIDs(o.Outputs),
- )
- }
-
- type CallECMultiplier struct {
- UserSpace jcstypes.UserSpaceDetail
- Coef [][]byte
- Inputs []exec.VarID
- Outputs []exec.VarID
- ChunkSize int
- }
-
- func (o *CallECMultiplier) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
- stgPool, err := exec.GetValueByType[*pool.Pool](ctx)
- if err != nil {
- return fmt.Errorf("getting storage pool: %w", err)
- }
-
- ecMul, err := stgPool.GetECMultiplier(&o.UserSpace)
- if err != nil {
- return err
- }
- defer ecMul.Close()
-
- inputs, err := exec.BindArray[*HTTPRequestValue](e, ctx.Context, o.Inputs)
- if err != nil {
- return err
- }
-
- reqs := make([]stgtypes.HTTPRequest, 0, len(inputs))
- for _, input := range inputs {
- reqs = append(reqs, input.HTTPRequest)
- }
-
- outputs, err := ecMul.Multiply(o.Coef, reqs, o.ChunkSize)
- if err != nil {
- return err
- }
-
- outputVals := make([]*FileInfoValue, 0, len(outputs))
- for _, output := range outputs {
- outputVals = append(outputVals, &FileInfoValue{
- FileInfo: output,
- })
- }
- exec.PutArray(e, o.Outputs, outputVals)
-
- return nil
- }
-
- func (o *CallECMultiplier) String() string {
- return fmt.Sprintf(
- "CallECMultiplier(userSpace=%v, coef=%v) (%v) -> (%v)",
- o.Coef,
- o.UserSpace,
- utils.FormatVarIDs(o.Inputs),
- utils.FormatVarIDs(o.Outputs),
- )
- }
-
- type ECMultiplyNode struct {
- dag.NodeBase
- EC jcstypes.ECRedundancy
- InputIndexes []int
- OutputIndexes []int
- }
-
- func (b *GraphNodeBuilder) NewECMultiply(ec jcstypes.ECRedundancy) *ECMultiplyNode {
- node := &ECMultiplyNode{
- EC: ec,
- }
- b.AddNode(node)
- return node
- }
-
- func (t *ECMultiplyNode) AddInput(str *dag.StreamVar, dataIndex int) {
- t.InputIndexes = append(t.InputIndexes, dataIndex)
- idx := t.InputStreams().EnlargeOne()
- str.To(t, idx)
- }
-
- func (t *ECMultiplyNode) RemoveAllInputs() {
- t.InputStreams().ClearAllInput(t)
- t.InputStreams().Slots.Resize(0)
- t.InputIndexes = nil
- }
-
- func (t *ECMultiplyNode) NewOutput(dataIndex int) *dag.StreamVar {
- t.OutputIndexes = append(t.OutputIndexes, dataIndex)
- return t.OutputStreams().AppendNew(t).Var()
- }
-
- func (t *ECMultiplyNode) GenerateOp() (exec.Op, error) {
- rs, err := ec.NewRs(t.EC.K, t.EC.N)
- if err != nil {
- return nil, err
- }
- coef, err := rs.GenerateMatrix(t.InputIndexes, t.OutputIndexes)
- if err != nil {
- return nil, err
- }
-
- return &ECMultiply{
- Coef: coef,
- Inputs: t.InputStreams().GetVarIDs(),
- Outputs: t.OutputStreams().GetVarIDs(),
- ChunkSize: t.EC.ChunkSize,
- }, nil
- }
-
- // func (t *MultiplyType) String() string {
- // return fmt.Sprintf("Multiply[]%v%v", formatStreamIO(node), formatValueIO(node))
- // }
-
- type CallECMultiplierNode struct {
- dag.NodeBase
- UserSpace jcstypes.UserSpaceDetail
- EC jcstypes.ECRedundancy
- InputIndexes []int
- OutputIndexes []int
- }
-
- func (b *GraphNodeBuilder) NewCallECMultiplier(userSpace jcstypes.UserSpaceDetail) *CallECMultiplierNode {
- node := &CallECMultiplierNode{
- UserSpace: userSpace,
- }
- b.AddNode(node)
- return node
- }
-
- func (t *CallECMultiplierNode) InitFrom(node *ECMultiplyNode) {
- t.EC = node.EC
- t.InputIndexes = node.InputIndexes
- t.OutputIndexes = node.OutputIndexes
-
- t.InputValues().Init(len(t.InputIndexes))
- t.OutputValues().Init(t, len(t.OutputIndexes))
- }
-
- func (t *CallECMultiplierNode) HTTPRequestSlot(idx int) dag.ValueInputSlot {
- return dag.ValueInputSlot{
- Node: t,
- Index: idx,
- }
- }
-
- func (t *CallECMultiplierNode) FileInfoVar(idx int) dag.ValueOutputSlot {
- return dag.ValueOutputSlot{
- Node: t,
- Index: idx,
- }
- }
-
- func (t *CallECMultiplierNode) GenerateOp() (exec.Op, error) {
- rs, err := ec.NewRs(t.EC.K, t.EC.N)
- if err != nil {
- return nil, err
- }
- coef, err := rs.GenerateMatrix(t.InputIndexes, t.OutputIndexes)
- if err != nil {
- return nil, err
- }
-
- return &CallECMultiplier{
- UserSpace: t.UserSpace,
- Coef: coef,
- Inputs: t.InputValues().GetVarIDs(),
- Outputs: t.OutputValues().GetVarIDs(),
- ChunkSize: t.EC.ChunkSize,
- }, nil
- }
|