| @@ -1,6 +1,7 @@ | |||||
| package downloader | package downloader | ||||
| import ( | import ( | ||||
| "context" | |||||
| "fmt" | "fmt" | ||||
| "io" | "io" | ||||
| "math" | "math" | ||||
| @@ -21,6 +22,7 @@ import ( | |||||
| stgglb "gitlink.org.cn/cloudream/storage/common/globals" | stgglb "gitlink.org.cn/cloudream/storage/common/globals" | ||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | stgmod "gitlink.org.cn/cloudream/storage/common/models" | ||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/distlock" | "gitlink.org.cn/cloudream/storage/common/pkgs/distlock" | ||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/plans" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/iterator" | "gitlink.org.cn/cloudream/storage/common/pkgs/iterator" | ||||
| coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator" | coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator" | ||||
| ) | ) | ||||
| @@ -170,27 +172,45 @@ func (iter *DownloadObjectIterator) downloadNoneOrRepObject(obj downloadReqeust2 | |||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| var strHandle *plans.ExecutorReadStream | |||||
| ft := plans.FromTo{ | |||||
| Object: *obj.Detail, | |||||
| } | |||||
| bsc, blocks := iter.getMinReadingBlockSolution(allNodes, 1) | bsc, blocks := iter.getMinReadingBlockSolution(allNodes, 1) | ||||
| osc, node := iter.getMinReadingObjectSolution(allNodes, 1) | osc, node := iter.getMinReadingObjectSolution(allNodes, 1) | ||||
| if bsc < osc { | if bsc < osc { | ||||
| logger.Debugf("downloading object from node %v(%v)", blocks[0].Node.Name, blocks[0].Node.NodeID) | logger.Debugf("downloading object from node %v(%v)", blocks[0].Node.Name, blocks[0].Node.NodeID) | ||||
| return NewIPFSReaderWithRange(blocks[0].Node, blocks[0].Block.FileHash, ipfs.ReadOption{ | |||||
| Offset: obj.Raw.Offset, | |||||
| Length: obj.Raw.Length, | |||||
| }), nil | |||||
| } | |||||
| toExec, handle := plans.NewToExecutor(-1) | |||||
| ft.AddFrom(plans.NewFromNode(&blocks[0].Node, -1)).AddTo(toExec) | |||||
| strHandle = handle | |||||
| // bsc >= osc,如果osc是MaxFloat64,那么bsc也一定是,也就意味着没有足够块来恢复文件 | |||||
| if osc == math.MaxFloat64 { | |||||
| // TODO2 处理Offset和Length | |||||
| } else if osc == math.MaxFloat64 { | |||||
| // bsc >= osc,如果osc是MaxFloat64,那么bsc也一定是,也就意味着没有足够块来恢复文件 | |||||
| return nil, fmt.Errorf("no node has this object") | return nil, fmt.Errorf("no node has this object") | ||||
| } else { | |||||
| logger.Debugf("downloading object from node %v(%v)", node.Name, node.NodeID) | |||||
| toExec, handle := plans.NewToExecutor(-1) | |||||
| ft.AddFrom(plans.NewFromNode(node, -1)).AddTo(toExec) | |||||
| strHandle = handle | |||||
| // TODO2 处理Offset和Length | |||||
| } | } | ||||
| logger.Debugf("downloading object from node %v(%v)", node.Name, node.NodeID) | |||||
| return NewIPFSReaderWithRange(*node, obj.Detail.Object.FileHash, ipfs.ReadOption{ | |||||
| Offset: obj.Raw.Offset, | |||||
| Length: obj.Raw.Length, | |||||
| }), nil | |||||
| parser := plans.DefaultParser{ | |||||
| EC: cdssdk.DefaultECRedundancy, | |||||
| } | |||||
| plans := plans.NewPlanBuilder() | |||||
| if err := parser.Parse(ft, plans); err != nil { | |||||
| return nil, fmt.Errorf("parsing plan: %w", err) | |||||
| } | |||||
| exec := plans.Execute() | |||||
| go exec.Wait(context.TODO()) | |||||
| return exec.BeginRead(strHandle) | |||||
| } | } | ||||
| func (iter *DownloadObjectIterator) downloadECObject(req downloadReqeust2, ecRed *cdssdk.ECRedundancy) (io.ReadCloser, error) { | func (iter *DownloadObjectIterator) downloadECObject(req downloadReqeust2, ecRed *cdssdk.ECRedundancy) (io.ReadCloser, error) { | ||||
| @@ -42,3 +42,7 @@ func (r *Rs) ReconstructAny(blocks [][]byte, outBlockIdxes []int) error { | |||||
| } | } | ||||
| return r.encoder.ReconstructAny(blocks, required) | return r.encoder.ReconstructAny(blocks, required) | ||||
| } | } | ||||
| func (r *Rs) GenerateMatrix(inputIdxs []int, outputIdxs []int) ([][]byte, error) { | |||||
| return r.encoder.(reedsolomon.Extensions).GenerateMatrix(inputIdxs, outputIdxs) | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package ops | |||||
| import ( | |||||
| "context" | |||||
| "io" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| ) | |||||
| type DropStream struct { | |||||
| Input *ioswitch.StreamVar `json:"input"` | |||||
| } | |||||
| func (o *DropStream) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| err := sw.BindVars(ctx, o.Input) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| for { | |||||
| buf := make([]byte, 1024*8) | |||||
| _, err = o.Input.Stream.Read(buf) | |||||
| if err == io.EOF { | |||||
| return nil | |||||
| } | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| } | |||||
| } | |||||
| func init() { | |||||
| OpUnion.AddT((*DropStream)(nil)) | |||||
| } | |||||
| @@ -105,7 +105,7 @@ type ECMultiply struct { | |||||
| Coef [][]byte `json:"coef"` | Coef [][]byte `json:"coef"` | ||||
| Inputs []*ioswitch.StreamVar `json:"inputs"` | Inputs []*ioswitch.StreamVar `json:"inputs"` | ||||
| Outputs []*ioswitch.StreamVar `json:"outputs"` | Outputs []*ioswitch.StreamVar `json:"outputs"` | ||||
| ChunkSize int64 `json:"chunkSize"` | |||||
| ChunkSize int `json:"chunkSize"` | |||||
| } | } | ||||
| func (o *ECMultiply) Execute(ctx context.Context, sw *ioswitch.Switch) error { | func (o *ECMultiply) Execute(ctx context.Context, sw *ioswitch.Switch) error { | ||||
| @@ -14,16 +14,17 @@ import ( | |||||
| ) | ) | ||||
| type SendStream struct { | type SendStream struct { | ||||
| Stream *ioswitch.StreamVar `json:"stream"` | |||||
| Node cdssdk.Node `json:"node"` | |||||
| Input *ioswitch.StreamVar `json:"input"` | |||||
| Send *ioswitch.StreamVar `json:"send"` | |||||
| Node cdssdk.Node `json:"node"` | |||||
| } | } | ||||
| func (o *SendStream) Execute(ctx context.Context, sw *ioswitch.Switch) error { | func (o *SendStream) Execute(ctx context.Context, sw *ioswitch.Switch) error { | ||||
| err := sw.BindVars(ctx, o.Stream) | |||||
| err := sw.BindVars(ctx, o.Input) | |||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| defer o.Stream.Stream.Close() | |||||
| defer o.Input.Stream.Close() | |||||
| agtCli, err := stgglb.AgentRPCPool.Acquire(stgglb.SelectGRPCAddress(&o.Node)) | agtCli, err := stgglb.AgentRPCPool.Acquire(stgglb.SelectGRPCAddress(&o.Node)) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -31,9 +32,10 @@ func (o *SendStream) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| } | } | ||||
| defer stgglb.AgentRPCPool.Release(agtCli) | defer stgglb.AgentRPCPool.Release(agtCli) | ||||
| logger.Debugf("sending stream %v to node %v", o.Stream.ID, o.Node) | |||||
| logger.Debugf("sending stream %v as %v to node %v", o.Input.ID, o.Send.ID, o.Node) | |||||
| err = agtCli.SendStream(ctx, sw.Plan().ID, o.Stream.ID, o.Stream.Stream) | |||||
| // 发送后流的ID不同 | |||||
| err = agtCli.SendStream(ctx, sw.Plan().ID, o.Send.ID, o.Input.Stream) | |||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("sending stream: %w", err) | return fmt.Errorf("sending stream: %w", err) | ||||
| } | } | ||||
| @@ -42,7 +44,8 @@ func (o *SendStream) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| } | } | ||||
| type GetStream struct { | type GetStream struct { | ||||
| Stream *ioswitch.StreamVar `json:"stream"` | |||||
| Get *ioswitch.StreamVar `json:"get"` | |||||
| Output *ioswitch.StreamVar `json:"output"` | |||||
| Node cdssdk.Node `json:"node"` | Node cdssdk.Node `json:"node"` | ||||
| } | } | ||||
| @@ -53,29 +56,31 @@ func (o *GetStream) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| } | } | ||||
| defer stgglb.AgentRPCPool.Release(agtCli) | defer stgglb.AgentRPCPool.Release(agtCli) | ||||
| logger.Debugf("getting stream %v from node %v", o.Stream.ID, o.Node) | |||||
| logger.Debugf("getting stream %v as %v from node %v", o.Get.ID, o.Output.ID, o.Node) | |||||
| str, err := agtCli.GetStream(sw.Plan().ID, o.Stream.ID) | |||||
| str, err := agtCli.GetStream(sw.Plan().ID, o.Get.ID) | |||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("getting stream: %w", err) | return fmt.Errorf("getting stream: %w", err) | ||||
| } | } | ||||
| fut := future.NewSetVoid() | fut := future.NewSetVoid() | ||||
| o.Stream.Stream = io2.AfterReadClosedOnce(str, func(closer io.ReadCloser) { | |||||
| // 获取后送到本地的流ID是不同的 | |||||
| o.Output.Stream = io2.AfterReadClosedOnce(str, func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | fut.SetVoid() | ||||
| }) | }) | ||||
| sw.PutVars(o.Stream) | |||||
| sw.PutVars(o.Output) | |||||
| return fut.Wait(ctx) | return fut.Wait(ctx) | ||||
| } | } | ||||
| type SendVar struct { | type SendVar struct { | ||||
| Var ioswitch.Var `json:"var"` | |||||
| Node cdssdk.Node `json:"node"` | |||||
| Input ioswitch.Var `json:"input"` | |||||
| Send ioswitch.Var `json:"send"` | |||||
| Node cdssdk.Node `json:"node"` | |||||
| } | } | ||||
| func (o *SendVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | func (o *SendVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | ||||
| err := sw.BindVars(ctx, o.Var) | |||||
| err := sw.BindVars(ctx, o.Input) | |||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -86,9 +91,10 @@ func (o *SendVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| } | } | ||||
| defer stgglb.AgentRPCPool.Release(agtCli) | defer stgglb.AgentRPCPool.Release(agtCli) | ||||
| logger.Debugf("sending var %v to node %v", o.Var.GetID(), o.Node) | |||||
| logger.Debugf("sending var %v as %v to node %v", o.Input.GetID(), o.Send.GetID(), o.Node) | |||||
| err = agtCli.SendVar(ctx, sw.Plan().ID, o.Var) | |||||
| ioswitch.AssignVar(o.Input, o.Send) | |||||
| err = agtCli.SendVar(ctx, sw.Plan().ID, o.Send) | |||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("sending var: %w", err) | return fmt.Errorf("sending var: %w", err) | ||||
| } | } | ||||
| @@ -97,8 +103,9 @@ func (o *SendVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| } | } | ||||
| type GetVar struct { | type GetVar struct { | ||||
| Var ioswitch.Var `json:"var"` | |||||
| Node cdssdk.Node `json:"node"` | |||||
| Get ioswitch.Var `json:"get"` | |||||
| Output ioswitch.Var `json:"output"` | |||||
| Node cdssdk.Node `json:"node"` | |||||
| } | } | ||||
| func (o *GetVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | func (o *GetVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | ||||
| @@ -108,14 +115,14 @@ func (o *GetVar) Execute(ctx context.Context, sw *ioswitch.Switch) error { | |||||
| } | } | ||||
| defer stgglb.AgentRPCPool.Release(agtCli) | defer stgglb.AgentRPCPool.Release(agtCli) | ||||
| logger.Debugf("getting var %v from node %v", o.Var.GetID(), o.Node) | |||||
| logger.Debugf("getting var %v as %v from node %v", o.Get.GetID(), o.Output.GetID(), o.Node) | |||||
| v2, err := agtCli.GetVar(ctx, sw.Plan().ID, o.Var) | |||||
| v2, err := agtCli.GetVar(ctx, sw.Plan().ID, o.Get) | |||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("getting var: %w", err) | return fmt.Errorf("getting var: %w", err) | ||||
| } | } | ||||
| o.Var = v2 | |||||
| sw.PutVars(o.Var) | |||||
| ioswitch.AssignVar(v2, o.Output) | |||||
| sw.PutVars(o.Output) | |||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -20,22 +20,22 @@ type Executor struct { | |||||
| executorSw *ioswitch.Switch | executorSw *ioswitch.Switch | ||||
| } | } | ||||
| func (e *Executor) BeginWrite(str io.ReadCloser, target *ExecutorWriteStream) { | |||||
| target.stream.Stream = str | |||||
| e.executorSw.PutVars(target.stream) | |||||
| func (e *Executor) BeginWrite(str io.ReadCloser, handle *ExecutorWriteStream) { | |||||
| handle.Var.Stream = str | |||||
| e.executorSw.PutVars(handle.Var) | |||||
| } | } | ||||
| func (e *Executor) BeginRead(target *ExecutorReadStream) (io.ReadCloser, error) { | |||||
| err := e.executorSw.BindVars(e.ctx, target.stream) | |||||
| func (e *Executor) BeginRead(handle *ExecutorReadStream) (io.ReadCloser, error) { | |||||
| err := e.executorSw.BindVars(e.ctx, handle.Var) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, fmt.Errorf("bind vars: %w", err) | return nil, fmt.Errorf("bind vars: %w", err) | ||||
| } | } | ||||
| return target.stream.Stream, nil | |||||
| return handle.Var.Stream, nil | |||||
| } | } | ||||
| func (e *Executor) Signal(signal *ExecutorSignalVar) { | func (e *Executor) Signal(signal *ExecutorSignalVar) { | ||||
| e.executorSw.PutVars(signal.v) | |||||
| e.executorSw.PutVars(signal.Var) | |||||
| } | } | ||||
| func (e *Executor) Wait(ctx context.Context) (map[string]any, error) { | func (e *Executor) Wait(ctx context.Context) (map[string]any, error) { | ||||
| @@ -45,7 +45,7 @@ func (e *Executor) Wait(ctx context.Context) (map[string]any, error) { | |||||
| } | } | ||||
| ret := make(map[string]any) | ret := make(map[string]any) | ||||
| e.planBlder.StoreMap.Range(func(k, v any) bool { | |||||
| e.planBlder.ExecutorPlan.StoreMap.Range(func(k, v any) bool { | |||||
| ret[k.(string)] = v | ret[k.(string)] = v | ||||
| return true | return true | ||||
| }) | }) | ||||
| @@ -98,64 +98,14 @@ func (e *Executor) stopWith(err error) { | |||||
| e.cancel() | e.cancel() | ||||
| } | } | ||||
| // type ExecutorStreamVar struct { | |||||
| // blder *PlanBuilder | |||||
| // v *ioswitch.StreamVar | |||||
| // } | |||||
| type ExecutorWriteStream struct { | type ExecutorWriteStream struct { | ||||
| stream *ioswitch.StreamVar | |||||
| Var *ioswitch.StreamVar | |||||
| } | } | ||||
| // func (b *ExecutorPlanBuilder) WillWrite(str *ExecutorWriteStream) *ExecutorStreamVar { | |||||
| // stream := b.blder.NewStreamVar() | |||||
| // str.stream = stream | |||||
| // return &ExecutorStreamVar{blder: b.blder, v: stream} | |||||
| // } | |||||
| // func (b *ExecutorPlanBuilder) WillSignal() *ExecutorSignalVar { | |||||
| // s := b.blder.NewSignalVar() | |||||
| // return &ExecutorSignalVar{blder: b.blder, v: s} | |||||
| // } | |||||
| type ExecutorReadStream struct { | type ExecutorReadStream struct { | ||||
| stream *ioswitch.StreamVar | |||||
| } | |||||
| // func (v *ExecutorStreamVar) WillRead(str *ExecutorReadStream) { | |||||
| // str.stream = v.v | |||||
| // } | |||||
| /* | |||||
| func (s *ExecutorStreamVar) To(node cdssdk.Node) *AgentStreamVar { | |||||
| s.blder.ExecutorPlan.ops = append(s.blder.ExecutorPlan.ops, &ops.SendStream{Stream: s.v, Node: node}) | |||||
| return &AgentStreamVar{ | |||||
| owner: s.blder.AtAgent(node), | |||||
| v: s.v, | |||||
| } | |||||
| } | |||||
| type ExecutorStringVar struct { | |||||
| blder *PlanBuilder | |||||
| v *ioswitch.StringVar | |||||
| } | |||||
| func (s *ExecutorStringVar) Store(key string) { | |||||
| s.blder.ExecutorPlan.ops = append(s.blder.ExecutorPlan.ops, &ops.Store{ | |||||
| Var: s.v, | |||||
| Key: key, | |||||
| Store: s.blder.StoreMap, | |||||
| }) | |||||
| Var *ioswitch.StreamVar | |||||
| } | } | ||||
| type ExecutorSignalVar struct { | type ExecutorSignalVar struct { | ||||
| blder *PlanBuilder | |||||
| v *ioswitch.SignalVar | |||||
| } | |||||
| func (s *ExecutorSignalVar) To(node cdssdk.Node) *AgentSignalVar { | |||||
| s.blder.ExecutorPlan.ops = append(s.blder.ExecutorPlan.ops, &ops.SendVar{Var: s.v, Node: node}) | |||||
| return &AgentSignalVar{ | |||||
| owner: s.blder.AtAgent(node), | |||||
| v: s.v, | |||||
| } | |||||
| Var *ioswitch.SignalVar | |||||
| } | } | ||||
| */ | |||||
| @@ -2,27 +2,43 @@ package plans | |||||
| import ( | import ( | ||||
| cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" | cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" | ||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | |||||
| ) | ) | ||||
| type FromTo struct { | |||||
| Object stgmod.ObjectDetail | |||||
| Froms []From | |||||
| Tos []To | |||||
| } | |||||
| func (ft *FromTo) AddFrom(from From) *FromTo { | |||||
| ft.Froms = append(ft.Froms, from) | |||||
| return ft | |||||
| } | |||||
| func (ft *FromTo) AddTo(to To) *FromTo { | |||||
| ft.Tos = append(ft.Tos, to) | |||||
| return ft | |||||
| } | |||||
| type FromTos []FromTo | |||||
| type From interface { | type From interface { | ||||
| GetDataIndex() int | GetDataIndex() int | ||||
| BuildOp() Node | |||||
| } | } | ||||
| type To interface { | type To interface { | ||||
| GetRange() Range | |||||
| GetDataIndex() int | GetDataIndex() int | ||||
| BuildOp() Node | |||||
| } | } | ||||
| type FromTos []FromTo | |||||
| type FromTo struct { | |||||
| Froms []From | |||||
| Tos []To | |||||
| type Range struct { | |||||
| Offset int64 | |||||
| Length int64 | |||||
| } | } | ||||
| type FromExecutor struct { | type FromExecutor struct { | ||||
| Stream *ExecutorWriteStream | |||||
| Handle *ExecutorWriteStream | |||||
| DataIndex int | DataIndex int | ||||
| } | } | ||||
| @@ -30,64 +46,43 @@ func (f *FromExecutor) GetDataIndex() int { | |||||
| return f.DataIndex | return f.DataIndex | ||||
| } | } | ||||
| func (f *FromExecutor) BuildOp() Node { | |||||
| func (f *FromExecutor) BuildNode(ft *FromTo) Node { | |||||
| op := Node{ | op := Node{ | ||||
| Env: &ExecutorEnv{}, | Env: &ExecutorEnv{}, | ||||
| Type: FromExecutorOp{ | |||||
| OutputVar: 0, | |||||
| Handle: f.Stream, | |||||
| Type: &FromExecutorOp{ | |||||
| Handle: f.Handle, | |||||
| }, | }, | ||||
| } | } | ||||
| op.NewOutput(nil) | |||||
| op.NewOutput(f.DataIndex) | |||||
| return op | return op | ||||
| } | } | ||||
| type FromIPFS struct { | |||||
| type FromNode struct { | |||||
| Node *cdssdk.Node | Node *cdssdk.Node | ||||
| FileHash string | |||||
| DataIndex int | DataIndex int | ||||
| } | } | ||||
| func NewFromIPFS(node *cdssdk.Node, fileHash string, dataIndex int) *FromIPFS { | |||||
| return &FromIPFS{ | |||||
| func NewFromNode(node *cdssdk.Node, dataIndex int) *FromNode { | |||||
| return &FromNode{ | |||||
| Node: node, | Node: node, | ||||
| FileHash: fileHash, | |||||
| DataIndex: dataIndex, | DataIndex: dataIndex, | ||||
| } | } | ||||
| } | } | ||||
| func (f *FromIPFS) GetDataIndex() int { | |||||
| func (f *FromNode) GetDataIndex() int { | |||||
| return f.DataIndex | return f.DataIndex | ||||
| } | } | ||||
| func (f *FromIPFS) BuildOp() Node { | |||||
| op := Node{ | |||||
| Pinned: true, | |||||
| Type: &IPFSReadType{ | |||||
| OutputVar: 0, | |||||
| FileHash: f.FileHash, | |||||
| }, | |||||
| } | |||||
| if f.Node == nil { | |||||
| op.Env = nil | |||||
| } else { | |||||
| op.Env = &AgentEnv{*f.Node} | |||||
| } | |||||
| op.NewOutput(nil) | |||||
| return op | |||||
| } | |||||
| type ToExecutor struct { | type ToExecutor struct { | ||||
| Stream *ExecutorReadStream | |||||
| Handle *ExecutorReadStream | |||||
| DataIndex int | DataIndex int | ||||
| Range Range | |||||
| } | } | ||||
| func NewToExecutor(dataIndex int) (*ToExecutor, *ExecutorReadStream) { | func NewToExecutor(dataIndex int) (*ToExecutor, *ExecutorReadStream) { | ||||
| str := ExecutorReadStream{} | str := ExecutorReadStream{} | ||||
| return &ToExecutor{ | return &ToExecutor{ | ||||
| Stream: &str, | |||||
| Handle: &str, | |||||
| DataIndex: dataIndex, | DataIndex: dataIndex, | ||||
| }, &str | }, &str | ||||
| } | } | ||||
| @@ -96,48 +91,31 @@ func (t *ToExecutor) GetDataIndex() int { | |||||
| return t.DataIndex | return t.DataIndex | ||||
| } | } | ||||
| func (t *ToExecutor) BuildOp() Node { | |||||
| op := Node{ | |||||
| Env: &ExecutorEnv{}, | |||||
| Pinned: true, | |||||
| Type: ToExecutorOp{ | |||||
| InputVar: 0, | |||||
| Handle: t.Stream, | |||||
| }, | |||||
| } | |||||
| op.NewOutput(nil) | |||||
| return op | |||||
| func (t *ToExecutor) GetRange() Range { | |||||
| return t.Range | |||||
| } | } | ||||
| type ToIPFS struct { | |||||
| Node cdssdk.Node | |||||
| DataIndex int | |||||
| FileHashKey string | |||||
| type ToAgent struct { | |||||
| Node cdssdk.Node | |||||
| DataIndex int | |||||
| Range Range | |||||
| FileHashStoreKey string | |||||
| } | } | ||||
| func NewToIPFS(node cdssdk.Node, dataIndex int, fileHashKey string) *ToIPFS { | |||||
| return &ToIPFS{ | |||||
| Node: node, | |||||
| DataIndex: dataIndex, | |||||
| FileHashKey: fileHashKey, | |||||
| func NewToAgent(node cdssdk.Node, dataIndex int, fileHashStoreKey string) *ToAgent { | |||||
| return &ToAgent{ | |||||
| Node: node, | |||||
| DataIndex: dataIndex, | |||||
| FileHashStoreKey: fileHashStoreKey, | |||||
| } | } | ||||
| } | } | ||||
| func (t *ToIPFS) GetDataIndex() int { | |||||
| func (t *ToAgent) GetDataIndex() int { | |||||
| return t.DataIndex | return t.DataIndex | ||||
| } | } | ||||
| func (t *ToIPFS) BuildOp() Node { | |||||
| op := Node{ | |||||
| Env: &AgentEnv{t.Node}, | |||||
| Pinned: true, | |||||
| Type: &IPFSWriteType{ | |||||
| InputVar: 0, | |||||
| FileHashVar: 0, | |||||
| }, | |||||
| } | |||||
| op.NewInput(nil) | |||||
| return op | |||||
| func (t *ToAgent) GetRange() Range { | |||||
| return t.Range | |||||
| } | } | ||||
| // type ToStorage struct { | // type ToStorage struct { | ||||
| @@ -5,7 +5,9 @@ import ( | |||||
| "gitlink.org.cn/cloudream/common/pkgs/ipfs" | "gitlink.org.cn/cloudream/common/pkgs/ipfs" | ||||
| cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" | cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" | ||||
| "gitlink.org.cn/cloudream/common/utils/lo2" | "gitlink.org.cn/cloudream/common/utils/lo2" | ||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ec" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | ||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/ops" | |||||
| ) | ) | ||||
| type VarIndex int | type VarIndex int | ||||
| @@ -130,8 +132,13 @@ type IPFSReadType struct { | |||||
| Option ipfs.ReadOption | Option ipfs.ReadOption | ||||
| } | } | ||||
| func (t *IPFSReadType) GenerateOp(op *Node, blder *PlanBuilder) error { | |||||
| func (t *IPFSReadType) GenerateOp(node *Node, blder *PlanBuilder) error { | |||||
| addOpByEnv(&ops.IPFSRead{ | |||||
| Output: node.OutputStreams[0].Var, | |||||
| FileHash: t.FileHash, | |||||
| Option: t.Option, | |||||
| }, node.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type IPFSWriteType struct { | type IPFSWriteType struct { | ||||
| @@ -139,7 +146,11 @@ type IPFSWriteType struct { | |||||
| } | } | ||||
| func (t *IPFSWriteType) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *IPFSWriteType) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.IPFSWrite{ | |||||
| Input: op.InputStreams[0].Var, | |||||
| FileHash: op.OutputValues[0].Var.(*ioswitch.StringVar), | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type ChunkedSplitOp struct { | type ChunkedSplitOp struct { | ||||
| @@ -148,7 +159,15 @@ type ChunkedSplitOp struct { | |||||
| } | } | ||||
| func (t *ChunkedSplitOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *ChunkedSplitOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.ChunkedSplit{ | |||||
| Input: op.InputStreams[0].Var, | |||||
| Outputs: lo.Map(op.OutputStreams, func(v *StreamVar, idx int) *ioswitch.StreamVar { | |||||
| return v.Var | |||||
| }), | |||||
| ChunkSize: t.ChunkSize, | |||||
| PaddingZeros: t.PaddingZeros, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type ChunkedJoinOp struct { | type ChunkedJoinOp struct { | ||||
| @@ -156,27 +175,68 @@ type ChunkedJoinOp struct { | |||||
| } | } | ||||
| func (t *ChunkedJoinOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *ChunkedJoinOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.ChunkedJoin{ | |||||
| Inputs: lo.Map(op.InputStreams, func(v *StreamVar, idx int) *ioswitch.StreamVar { | |||||
| return v.Var | |||||
| }), | |||||
| Output: op.OutputStreams[0].Var, | |||||
| ChunkSize: t.ChunkSize, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type CloneStreamOp struct{} | type CloneStreamOp struct{} | ||||
| func (t *CloneStreamOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *CloneStreamOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.CloneStream{ | |||||
| Input: op.InputStreams[0].Var, | |||||
| Outputs: lo.Map(op.OutputStreams, func(v *StreamVar, idx int) *ioswitch.StreamVar { | |||||
| return v.Var | |||||
| }), | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type CloneVarOp struct{} | type CloneVarOp struct{} | ||||
| func (t *CloneVarOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *CloneVarOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.CloneVar{ | |||||
| Raw: op.InputValues[0].Var, | |||||
| Cloneds: lo.Map(op.OutputValues, func(v *ValueVar, idx int) ioswitch.Var { | |||||
| return v.Var | |||||
| }), | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type MultiplyOp struct { | type MultiplyOp struct { | ||||
| Coef [][]byte | |||||
| EC cdssdk.ECRedundancy | |||||
| ChunkSize int | ChunkSize int | ||||
| } | } | ||||
| func (t *MultiplyOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *MultiplyOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| var inputIdxs []int | |||||
| var outputIdxs []int | |||||
| for _, in := range op.InputStreams { | |||||
| inputIdxs = append(inputIdxs, in.DataIndex) | |||||
| } | |||||
| for _, out := range op.OutputStreams { | |||||
| outputIdxs = append(outputIdxs, out.DataIndex) | |||||
| } | |||||
| rs, _ := ec.NewRs(t.EC.K, t.EC.N) | |||||
| coef, err := rs.GenerateMatrix(inputIdxs, outputIdxs) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| addOpByEnv(&ops.ECMultiply{ | |||||
| Coef: coef, | |||||
| Inputs: lo.Map(op.InputStreams, func(v *StreamVar, idx int) *ioswitch.StreamVar { return v.Var }), | |||||
| Outputs: lo.Map(op.OutputStreams, func(v *StreamVar, idx int) *ioswitch.StreamVar { return v.Var }), | |||||
| ChunkSize: t.ChunkSize, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type FileReadOp struct { | type FileReadOp struct { | ||||
| @@ -184,6 +244,11 @@ type FileReadOp struct { | |||||
| } | } | ||||
| func (t *FileReadOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *FileReadOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.FileRead{ | |||||
| Output: op.OutputStreams[0].Var, | |||||
| FilePath: t.FilePath, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type FileWriteOp struct { | type FileWriteOp struct { | ||||
| @@ -191,6 +256,11 @@ type FileWriteOp struct { | |||||
| } | } | ||||
| func (t *FileWriteOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *FileWriteOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.FileWrite{ | |||||
| Input: op.InputStreams[0].Var, | |||||
| FilePath: t.FilePath, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type FromExecutorOp struct { | type FromExecutorOp struct { | ||||
| @@ -198,6 +268,8 @@ type FromExecutorOp struct { | |||||
| } | } | ||||
| func (t *FromExecutorOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *FromExecutorOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| t.Handle.Var = op.OutputStreams[0].Var | |||||
| return nil | |||||
| } | } | ||||
| type ToExecutorOp struct { | type ToExecutorOp struct { | ||||
| @@ -205,6 +277,8 @@ type ToExecutorOp struct { | |||||
| } | } | ||||
| func (t *ToExecutorOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *ToExecutorOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| t.Handle.Var = op.InputStreams[0].Var | |||||
| return nil | |||||
| } | } | ||||
| type StoreOp struct { | type StoreOp struct { | ||||
| @@ -212,29 +286,76 @@ type StoreOp struct { | |||||
| } | } | ||||
| func (t *StoreOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *StoreOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| blder.AtExecutor().AddOp(&ops.Store{ | |||||
| Var: op.InputValues[0].Var, | |||||
| Key: t.StoreKey, | |||||
| Store: blder.ExecutorPlan.StoreMap, | |||||
| }) | |||||
| return nil | |||||
| } | } | ||||
| type DropOp struct{} | type DropOp struct{} | ||||
| func (t *DropOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *DropOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| addOpByEnv(&ops.DropStream{ | |||||
| Input: op.InputStreams[0].Var, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type SendStreamOp struct{} | type SendStreamOp struct{} | ||||
| func (t *SendStreamOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *SendStreamOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| toAgt := op.OutputStreams[0].Toes[0].Env.(*AgentEnv) | |||||
| addOpByEnv(&ops.SendStream{ | |||||
| Input: op.InputStreams[0].Var, | |||||
| Send: op.OutputStreams[0].Var, | |||||
| Node: toAgt.Node, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type GetStreamOp struct{} | type GetStreamOp struct{} | ||||
| func (t *GetStreamOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *GetStreamOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| fromAgt := op.InputStreams[0].From.Env.(*AgentEnv) | |||||
| addOpByEnv(&ops.GetStream{ | |||||
| Output: op.OutputStreams[0].Var, | |||||
| Get: op.InputStreams[0].Var, | |||||
| Node: fromAgt.Node, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type SendVarOp struct{} | type SendVarOp struct{} | ||||
| func (t *SendVarOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *SendVarOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| toAgt := op.OutputValues[0].Toes[0].Env.(*AgentEnv) | |||||
| addOpByEnv(&ops.SendVar{ | |||||
| Input: op.InputValues[0].Var, | |||||
| Send: op.OutputValues[0].Var, | |||||
| Node: toAgt.Node, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | } | ||||
| type GetVarOp struct{} | type GetVarOp struct{} | ||||
| func (t *GetVarOp) GenerateOp(op *Node, blder *PlanBuilder) error { | func (t *GetVarOp) GenerateOp(op *Node, blder *PlanBuilder) error { | ||||
| fromAgt := op.InputValues[0].From.Env.(*AgentEnv) | |||||
| addOpByEnv(&ops.GetVar{ | |||||
| Output: op.OutputValues[0].Var, | |||||
| Get: op.InputValues[0].Var, | |||||
| Node: fromAgt.Node, | |||||
| }, op.Env, blder) | |||||
| return nil | |||||
| } | |||||
| func addOpByEnv(op ioswitch.Op, env OpEnv, blder *PlanBuilder) { | |||||
| switch env := env.(type) { | |||||
| case *AgentEnv: | |||||
| blder.AtAgent(env.Node).AddOp(op) | |||||
| case *ExecutorEnv: | |||||
| blder.AtExecutor().AddOp(op) | |||||
| } | |||||
| } | } | ||||
| @@ -12,12 +12,12 @@ type FromToParser interface { | |||||
| } | } | ||||
| type DefaultParser struct { | type DefaultParser struct { | ||||
| EC *cdssdk.ECRedundancy | |||||
| EC cdssdk.ECRedundancy | |||||
| } | } | ||||
| type ParseContext struct { | type ParseContext struct { | ||||
| Ft FromTo | |||||
| Ops []*Node | |||||
| Ft FromTo | |||||
| Nodes []*Node | |||||
| } | } | ||||
| func (p *DefaultParser) Parse(ft FromTo, blder *PlanBuilder) error { | func (p *DefaultParser) Parse(ft FromTo, blder *PlanBuilder) error { | ||||
| @@ -85,7 +85,7 @@ func (p *DefaultParser) Parse(ft FromTo, blder *PlanBuilder) error { | |||||
| return p.buildPlan(&ctx, blder) | return p.buildPlan(&ctx, blder) | ||||
| } | } | ||||
| func (p *DefaultParser) findOutputStream(ctx *ParseContext, dataIndex int) *StreamVar { | func (p *DefaultParser) findOutputStream(ctx *ParseContext, dataIndex int) *StreamVar { | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| for _, o := range op.OutputStreams { | for _, o := range op.OutputStreams { | ||||
| if o.DataIndex == dataIndex { | if o.DataIndex == dataIndex { | ||||
| return o | return o | ||||
| @@ -98,8 +98,11 @@ func (p *DefaultParser) findOutputStream(ctx *ParseContext, dataIndex int) *Stre | |||||
| func (p *DefaultParser) extend(ctx *ParseContext, ft FromTo, blder *PlanBuilder) error { | func (p *DefaultParser) extend(ctx *ParseContext, ft FromTo, blder *PlanBuilder) error { | ||||
| for _, f := range ft.Froms { | for _, f := range ft.Froms { | ||||
| o := f.BuildOp() | |||||
| ctx.Ops = append(ctx.Ops, &o) | |||||
| n, err := p.buildFromNode(&ft, f) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| ctx.Nodes = append(ctx.Nodes, n) | |||||
| // 对于完整文件的From,生成Split指令 | // 对于完整文件的From,生成Split指令 | ||||
| if f.GetDataIndex() == -1 { | if f.GetDataIndex() == -1 { | ||||
| @@ -107,18 +110,18 @@ func (p *DefaultParser) extend(ctx *ParseContext, ft FromTo, blder *PlanBuilder) | |||||
| Env: nil, | Env: nil, | ||||
| Type: &ChunkedSplitOp{ChunkSize: p.EC.ChunkSize, PaddingZeros: true}, | Type: &ChunkedSplitOp{ChunkSize: p.EC.ChunkSize, PaddingZeros: true}, | ||||
| } | } | ||||
| splitOp.AddInput(o.OutputStreams[0]) | |||||
| splitOp.AddInput(n.OutputStreams[0]) | |||||
| for i := 0; i < p.EC.K; i++ { | for i := 0; i < p.EC.K; i++ { | ||||
| splitOp.NewOutput(i) | splitOp.NewOutput(i) | ||||
| } | } | ||||
| ctx.Ops = append(ctx.Ops, splitOp) | |||||
| ctx.Nodes = append(ctx.Nodes, splitOp) | |||||
| } | } | ||||
| } | } | ||||
| // 如果有K个不同的文件块流,则生成Multiply指令,同时针对其生成的流,生成Join指令 | // 如果有K个不同的文件块流,则生成Multiply指令,同时针对其生成的流,生成Join指令 | ||||
| ecInputStrs := make(map[int]*StreamVar) | ecInputStrs := make(map[int]*StreamVar) | ||||
| loop: | loop: | ||||
| for _, o := range ctx.Ops { | |||||
| for _, o := range ctx.Nodes { | |||||
| for _, s := range o.OutputStreams { | for _, s := range o.OutputStreams { | ||||
| if s.DataIndex >= 0 && ecInputStrs[s.DataIndex] == nil { | if s.DataIndex >= 0 && ecInputStrs[s.DataIndex] == nil { | ||||
| ecInputStrs[s.DataIndex] = s | ecInputStrs[s.DataIndex] = s | ||||
| @@ -140,7 +143,7 @@ loop: | |||||
| for i := 0; i < p.EC.N; i++ { | for i := 0; i < p.EC.N; i++ { | ||||
| mulOp.NewOutput(i) | mulOp.NewOutput(i) | ||||
| } | } | ||||
| ctx.Ops = append(ctx.Ops, mulOp) | |||||
| ctx.Nodes = append(ctx.Nodes, mulOp) | |||||
| joinOp := &Node{ | joinOp := &Node{ | ||||
| Env: nil, | Env: nil, | ||||
| @@ -155,24 +158,75 @@ loop: | |||||
| // 为每一个To找到一个输入流 | // 为每一个To找到一个输入流 | ||||
| for _, t := range ft.Tos { | for _, t := range ft.Tos { | ||||
| o := t.BuildOp() | |||||
| ctx.Ops = append(ctx.Ops, &o) | |||||
| n, err := p.buildToNode(&ft, t) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| ctx.Nodes = append(ctx.Nodes, n) | |||||
| str := p.findOutputStream(ctx, t.GetDataIndex()) | str := p.findOutputStream(ctx, t.GetDataIndex()) | ||||
| if str == nil { | if str == nil { | ||||
| return fmt.Errorf("no output stream found for data index %d", t.GetDataIndex()) | return fmt.Errorf("no output stream found for data index %d", t.GetDataIndex()) | ||||
| } | } | ||||
| o.AddInput(str) | |||||
| n.AddInput(str) | |||||
| } | } | ||||
| return nil | return nil | ||||
| } | } | ||||
| func (p *DefaultParser) buildFromNode(ft *FromTo, f From) (*Node, error) { | |||||
| switch f := f.(type) { | |||||
| case *FromNode: | |||||
| n := &Node{ | |||||
| // TODO2 需要FromTo的Range来设置Option | |||||
| Type: &IPFSReadType{FileHash: ft.Object.Object.FileHash}, | |||||
| } | |||||
| n.NewOutput(f.DataIndex) | |||||
| if f.Node != nil { | |||||
| n.Env = &AgentEnv{Node: *f.Node} | |||||
| } | |||||
| return n, nil | |||||
| case *FromExecutor: | |||||
| n := &Node{ | |||||
| Env: &ExecutorEnv{}, | |||||
| Type: &FromExecutorOp{Handle: f.Handle}, | |||||
| } | |||||
| n.NewOutput(f.DataIndex) | |||||
| return n, nil | |||||
| default: | |||||
| return nil, fmt.Errorf("unsupported from type %T", f) | |||||
| } | |||||
| } | |||||
| func (p *DefaultParser) buildToNode(ft *FromTo, t To) (*Node, error) { | |||||
| switch t := t.(type) { | |||||
| case *ToAgent: | |||||
| return &Node{ | |||||
| Env: &AgentEnv{t.Node}, | |||||
| Type: &IPFSWriteType{FileHashStoreKey: t.FileHashStoreKey}, | |||||
| }, nil | |||||
| case *ToExecutor: | |||||
| return &Node{ | |||||
| Env: &ExecutorEnv{}, | |||||
| Type: &ToExecutorOp{Handle: t.Handle}, | |||||
| }, nil | |||||
| default: | |||||
| return nil, fmt.Errorf("unsupported to type %T", t) | |||||
| } | |||||
| } | |||||
| // 删除输出流未被使用的Join指令 | // 删除输出流未被使用的Join指令 | ||||
| func (p *DefaultParser) removeUnusedJoin(ctx *ParseContext) bool { | func (p *DefaultParser) removeUnusedJoin(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for i, op := range ctx.Ops { | |||||
| for i, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*ChunkedJoinOp) | _, ok := op.Type.(*ChunkedJoinOp) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -186,18 +240,18 @@ func (p *DefaultParser) removeUnusedJoin(ctx *ParseContext) bool { | |||||
| in.RemoveTo(op) | in.RemoveTo(op) | ||||
| } | } | ||||
| ctx.Ops[i] = nil | |||||
| ctx.Nodes[i] = nil | |||||
| opted = true | opted = true | ||||
| } | } | ||||
| ctx.Ops = lo2.RemoveAllDefault(ctx.Ops) | |||||
| ctx.Nodes = lo2.RemoveAllDefault(ctx.Nodes) | |||||
| return opted | return opted | ||||
| } | } | ||||
| // 减少未使用的Multiply指令的输出流。如果减少到0,则删除该指令 | // 减少未使用的Multiply指令的输出流。如果减少到0,则删除该指令 | ||||
| func (p *DefaultParser) removeUnusedMultiplyOutput(ctx *ParseContext) bool { | func (p *DefaultParser) removeUnusedMultiplyOutput(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for i, op := range ctx.Ops { | |||||
| for i, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*MultiplyOp) | _, ok := op.Type.(*MultiplyOp) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -217,20 +271,20 @@ func (p *DefaultParser) removeUnusedMultiplyOutput(ctx *ParseContext) bool { | |||||
| in.RemoveTo(op) | in.RemoveTo(op) | ||||
| } | } | ||||
| ctx.Ops[i] = nil | |||||
| ctx.Nodes[i] = nil | |||||
| } | } | ||||
| opted = true | opted = true | ||||
| } | } | ||||
| ctx.Ops = lo2.RemoveAllDefault(ctx.Ops) | |||||
| ctx.Nodes = lo2.RemoveAllDefault(ctx.Nodes) | |||||
| return opted | return opted | ||||
| } | } | ||||
| // 删除未使用的Split指令 | // 删除未使用的Split指令 | ||||
| func (p *DefaultParser) removeUnusedSplit(ctx *ParseContext) bool { | func (p *DefaultParser) removeUnusedSplit(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for i, op := range ctx.Ops { | |||||
| for i, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*ChunkedSplitOp) | _, ok := op.Type.(*ChunkedSplitOp) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -247,12 +301,12 @@ func (p *DefaultParser) removeUnusedSplit(ctx *ParseContext) bool { | |||||
| if isAllUnused { | if isAllUnused { | ||||
| op.InputStreams[0].RemoveTo(op) | op.InputStreams[0].RemoveTo(op) | ||||
| ctx.Ops[i] = nil | |||||
| ctx.Nodes[i] = nil | |||||
| opted = true | opted = true | ||||
| } | } | ||||
| } | } | ||||
| ctx.Ops = lo2.RemoveAllDefault(ctx.Ops) | |||||
| ctx.Nodes = lo2.RemoveAllDefault(ctx.Nodes) | |||||
| return opted | return opted | ||||
| } | } | ||||
| @@ -260,7 +314,7 @@ func (p *DefaultParser) removeUnusedSplit(ctx *ParseContext) bool { | |||||
| func (p *DefaultParser) omitSplitJoin(ctx *ParseContext) bool { | func (p *DefaultParser) omitSplitJoin(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| loop: | loop: | ||||
| for iSplit, splitOp := range ctx.Ops { | |||||
| for iSplit, splitOp := range ctx.Nodes { | |||||
| // 进行合并操作时会删除多个指令,因此这里存在splitOp == nil的情况 | // 进行合并操作时会删除多个指令,因此这里存在splitOp == nil的情况 | ||||
| if splitOp == nil { | if splitOp == nil { | ||||
| continue | continue | ||||
| @@ -309,19 +363,19 @@ loop: | |||||
| } | } | ||||
| // 并删除这两个指令 | // 并删除这两个指令 | ||||
| ctx.Ops[iSplit] = nil | |||||
| lo2.Clear(ctx.Ops, joinOp) | |||||
| ctx.Nodes[iSplit] = nil | |||||
| lo2.Clear(ctx.Nodes, joinOp) | |||||
| opted = true | opted = true | ||||
| } | } | ||||
| ctx.Ops = lo2.RemoveAllDefault(ctx.Ops) | |||||
| ctx.Nodes = lo2.RemoveAllDefault(ctx.Nodes) | |||||
| return opted | return opted | ||||
| } | } | ||||
| // 确定Split命令的执行位置 | // 确定Split命令的执行位置 | ||||
| func (p *DefaultParser) pinSplit(ctx *ParseContext) bool { | func (p *DefaultParser) pinSplit(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*ChunkedSplitOp) | _, ok := op.Type.(*ChunkedSplitOp) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -380,7 +434,7 @@ func (p *DefaultParser) pinSplit(ctx *ParseContext) bool { | |||||
| // 确定Join命令的执行位置,策略与固定Split类似 | // 确定Join命令的执行位置,策略与固定Split类似 | ||||
| func (p *DefaultParser) pinJoin(ctx *ParseContext) bool { | func (p *DefaultParser) pinJoin(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*ChunkedJoinOp) | _, ok := op.Type.(*ChunkedJoinOp) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -443,7 +497,7 @@ func (p *DefaultParser) pinJoin(ctx *ParseContext) bool { | |||||
| // 确定Multiply命令的执行位置 | // 确定Multiply命令的执行位置 | ||||
| func (p *DefaultParser) pinMultiply(ctx *ParseContext) bool { | func (p *DefaultParser) pinMultiply(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*MultiplyOp) | _, ok := op.Type.(*MultiplyOp) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -507,7 +561,7 @@ func (p *DefaultParser) pinMultiply(ctx *ParseContext) bool { | |||||
| // 确定IPFS读取指令的执行位置 | // 确定IPFS读取指令的执行位置 | ||||
| func (p *DefaultParser) pinIPFSRead(ctx *ParseContext) bool { | func (p *DefaultParser) pinIPFSRead(ctx *ParseContext) bool { | ||||
| opted := false | opted := false | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| _, ok := op.Type.(*IPFSReadType) | _, ok := op.Type.(*IPFSReadType) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -545,7 +599,7 @@ func (p *DefaultParser) pinIPFSRead(ctx *ParseContext) bool { | |||||
| // 对于所有未使用的流,增加Drop指令 | // 对于所有未使用的流,增加Drop指令 | ||||
| func (p *DefaultParser) dropUnused(ctx *ParseContext) { | func (p *DefaultParser) dropUnused(ctx *ParseContext) { | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| for _, out := range op.OutputStreams { | for _, out := range op.OutputStreams { | ||||
| if len(out.Toes) == 0 { | if len(out.Toes) == 0 { | ||||
| dropOp := &Node{ | dropOp := &Node{ | ||||
| @@ -553,7 +607,7 @@ func (p *DefaultParser) dropUnused(ctx *ParseContext) { | |||||
| Type: &DropOp{}, | Type: &DropOp{}, | ||||
| } | } | ||||
| dropOp.AddInput(out) | dropOp.AddInput(out) | ||||
| ctx.Ops = append(ctx.Ops, dropOp) | |||||
| ctx.Nodes = append(ctx.Nodes, dropOp) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -561,7 +615,7 @@ func (p *DefaultParser) dropUnused(ctx *ParseContext) { | |||||
| // 为IPFS写入指令存储结果 | // 为IPFS写入指令存储结果 | ||||
| func (p *DefaultParser) storeIPFSWriteResult(ctx *ParseContext) { | func (p *DefaultParser) storeIPFSWriteResult(ctx *ParseContext) { | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| w, ok := op.Type.(*IPFSWriteType) | w, ok := op.Type.(*IPFSWriteType) | ||||
| if !ok { | if !ok { | ||||
| continue | continue | ||||
| @@ -578,13 +632,13 @@ func (p *DefaultParser) storeIPFSWriteResult(ctx *ParseContext) { | |||||
| }, | }, | ||||
| } | } | ||||
| storeOp.AddInputVar(op.OutputValues[0]) | storeOp.AddInputVar(op.OutputValues[0]) | ||||
| ctx.Ops = append(ctx.Ops, storeOp) | |||||
| ctx.Nodes = append(ctx.Nodes, storeOp) | |||||
| } | } | ||||
| } | } | ||||
| // 生成Clone指令 | // 生成Clone指令 | ||||
| func (p *DefaultParser) generateClone(ctx *ParseContext) { | func (p *DefaultParser) generateClone(ctx *ParseContext) { | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| for _, out := range op.OutputStreams { | for _, out := range op.OutputStreams { | ||||
| if len(out.Toes) <= 1 { | if len(out.Toes) <= 1 { | ||||
| continue | continue | ||||
| @@ -599,7 +653,7 @@ func (p *DefaultParser) generateClone(ctx *ParseContext) { | |||||
| } | } | ||||
| out.Toes = nil | out.Toes = nil | ||||
| cloneOp.AddInput(out) | cloneOp.AddInput(out) | ||||
| ctx.Ops = append(ctx.Ops, cloneOp) | |||||
| ctx.Nodes = append(ctx.Nodes, cloneOp) | |||||
| } | } | ||||
| for _, out := range op.OutputValues { | for _, out := range op.OutputValues { | ||||
| @@ -622,7 +676,7 @@ func (p *DefaultParser) generateClone(ctx *ParseContext) { | |||||
| // 生成Send指令 | // 生成Send指令 | ||||
| func (p *DefaultParser) generateSend(ctx *ParseContext) { | func (p *DefaultParser) generateSend(ctx *ParseContext) { | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| for _, out := range op.OutputStreams { | for _, out := range op.OutputStreams { | ||||
| to := out.Toes[0] | to := out.Toes[0] | ||||
| if to.Env.Equals(op.Env) { | if to.Env.Equals(op.Env) { | ||||
| @@ -639,7 +693,7 @@ func (p *DefaultParser) generateSend(ctx *ParseContext) { | |||||
| out.Toes = nil | out.Toes = nil | ||||
| getStrOp.AddInput(out) | getStrOp.AddInput(out) | ||||
| to.ReplaceInput(out, getStrOp.NewOutput(out.DataIndex)) | to.ReplaceInput(out, getStrOp.NewOutput(out.DataIndex)) | ||||
| ctx.Ops = append(ctx.Ops, getStrOp) | |||||
| ctx.Nodes = append(ctx.Nodes, getStrOp) | |||||
| case *AgentEnv: | case *AgentEnv: | ||||
| // 如果是要送到Agent,则可以直接发送 | // 如果是要送到Agent,则可以直接发送 | ||||
| @@ -650,7 +704,7 @@ func (p *DefaultParser) generateSend(ctx *ParseContext) { | |||||
| out.Toes = nil | out.Toes = nil | ||||
| sendStrOp.AddInput(out) | sendStrOp.AddInput(out) | ||||
| to.ReplaceInput(out, sendStrOp.NewOutput(out.DataIndex)) | to.ReplaceInput(out, sendStrOp.NewOutput(out.DataIndex)) | ||||
| ctx.Ops = append(ctx.Ops, sendStrOp) | |||||
| ctx.Nodes = append(ctx.Nodes, sendStrOp) | |||||
| } | } | ||||
| } | } | ||||
| @@ -670,7 +724,7 @@ func (p *DefaultParser) generateSend(ctx *ParseContext) { | |||||
| out.Toes = nil | out.Toes = nil | ||||
| getVarOp.AddInputVar(out) | getVarOp.AddInputVar(out) | ||||
| to.ReplaceInputVar(out, getVarOp.NewOutputVar(out.Type)) | to.ReplaceInputVar(out, getVarOp.NewOutputVar(out.Type)) | ||||
| ctx.Ops = append(ctx.Ops, getVarOp) | |||||
| ctx.Nodes = append(ctx.Nodes, getVarOp) | |||||
| case *AgentEnv: | case *AgentEnv: | ||||
| // 如果是要送到Agent,则可以直接发送 | // 如果是要送到Agent,则可以直接发送 | ||||
| @@ -681,7 +735,7 @@ func (p *DefaultParser) generateSend(ctx *ParseContext) { | |||||
| out.Toes = nil | out.Toes = nil | ||||
| sendVarOp.AddInputVar(out) | sendVarOp.AddInputVar(out) | ||||
| to.ReplaceInputVar(out, sendVarOp.NewOutputVar(out.Type)) | to.ReplaceInputVar(out, sendVarOp.NewOutputVar(out.Type)) | ||||
| ctx.Ops = append(ctx.Ops, sendVarOp) | |||||
| ctx.Nodes = append(ctx.Nodes, sendVarOp) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -689,7 +743,7 @@ func (p *DefaultParser) generateSend(ctx *ParseContext) { | |||||
| // 生成Plan | // 生成Plan | ||||
| func (p *DefaultParser) buildPlan(ctx *ParseContext, blder *PlanBuilder) error { | func (p *DefaultParser) buildPlan(ctx *ParseContext, blder *PlanBuilder) error { | ||||
| for _, op := range ctx.Ops { | |||||
| for _, op := range ctx.Nodes { | |||||
| for _, out := range op.OutputStreams { | for _, out := range op.OutputStreams { | ||||
| if out.Var != nil { | if out.Var != nil { | ||||
| continue | continue | ||||