| @@ -185,7 +185,7 @@ func PackageUpdateRepPackage(ctx CommandContext, packageID int64, rootPath strin | |||||
| } | } | ||||
| } | } | ||||
| func PackageUploadECPackage(ctx CommandContext, rootPath string, bucketID int64, name string, ecName string, chunkSize int64, nodeAffinity []int64) error { | |||||
| func PackageUploadECPackage(ctx CommandContext, rootPath string, bucketID int64, name string, ecName string, chunkSize int, nodeAffinity []int64) error { | |||||
| rootPath = filepath.Clean(rootPath) | rootPath = filepath.Clean(rootPath) | ||||
| var uploadFilePathes []string | var uploadFilePathes []string | ||||
| @@ -23,7 +23,7 @@ | |||||
| "vhost": "/" | "vhost": "/" | ||||
| }, | }, | ||||
| "ipfs": { | "ipfs": { | ||||
| "port": 5001 | |||||
| "address": "127.0.0.1:5001" | |||||
| }, | }, | ||||
| "distlock": { | "distlock": { | ||||
| "etcdAddress": "127.0.0.1:2379", | "etcdAddress": "127.0.0.1:2379", | ||||
| @@ -8,10 +8,10 @@ type EC struct { | |||||
| ID int64 `json:"id"` | ID int64 `json:"id"` | ||||
| K int `json:"k"` | K int `json:"k"` | ||||
| N int `json:"n"` | N int `json:"n"` | ||||
| ChunkSize int64 `json:"chunkSize"` | |||||
| ChunkSize int `json:"chunkSize"` | |||||
| } | } | ||||
| func NewEc(id int64, k int, n int, chunkSize int64) EC { | |||||
| func NewEc(id int64, k int, n int, chunkSize int) EC { | |||||
| return EC{ | return EC{ | ||||
| ID: id, | ID: id, | ||||
| K: k, | K: k, | ||||
| @@ -193,7 +193,7 @@ func uploadECObject(obj *iterator.IterUploadingObject, uploadNodes []UploadNodeI | |||||
| } | } | ||||
| outputs := myio.ChunkedSplit(obj.File, ecInfo.ChunkSize, ecMod.EcK, myio.ChunkedSplitOption{ | outputs := myio.ChunkedSplit(obj.File, ecInfo.ChunkSize, ecMod.EcK, myio.ChunkedSplitOption{ | ||||
| FillZeros: true, | |||||
| PaddingZeros: true, | |||||
| }) | }) | ||||
| var readers []io.Reader | var readers []io.Reader | ||||
| for _, o := range outputs { | for _, o := range outputs { | ||||
| @@ -12,10 +12,10 @@ type Rs struct { | |||||
| ecN int | ecN int | ||||
| ecK int | ecK int | ||||
| ecP int | ecP int | ||||
| chunkSize int64 | |||||
| chunkSize int | |||||
| } | } | ||||
| func NewRs(k int, n int, chunkSize int64) (*Rs, error) { | |||||
| func NewRs(k int, n int, chunkSize int) (*Rs, error) { | |||||
| enc := Rs{ | enc := Rs{ | ||||
| ecN: n, | ecN: n, | ||||
| ecK: k, | ecK: k, | ||||
| @@ -0,0 +1,49 @@ | |||||
| package ops | |||||
| import ( | |||||
| "context" | |||||
| "io" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/future" | |||||
| myio "gitlink.org.cn/cloudream/common/utils/io" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| ) | |||||
| type ChunkedJoin struct { | |||||
| InputIDs []ioswitch.StreamID `json:"inputIDs"` | |||||
| OutputID ioswitch.StreamID `json:"outputID"` | |||||
| ChunkSize int `json:"chunkSize"` | |||||
| } | |||||
| func (o *ChunkedJoin) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| strs, err := sw.WaitStreams(planID, o.InputIDs...) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| var strReaders []io.Reader | |||||
| for _, s := range strs { | |||||
| strReaders = append(strReaders, s.Stream) | |||||
| } | |||||
| defer func() { | |||||
| for _, str := range strs { | |||||
| str.Stream.Close() | |||||
| } | |||||
| }() | |||||
| fut := future.NewSetVoid() | |||||
| sw.StreamReady(planID, | |||||
| ioswitch.NewStream(o.OutputID, | |||||
| myio.AfterReadClosedOnce(myio.ChunkedJoin(strReaders, o.ChunkSize), func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | |||||
| }), | |||||
| ), | |||||
| ) | |||||
| fut.Wait(context.TODO()) | |||||
| return nil | |||||
| } | |||||
| func init() { | |||||
| OpUnion.AddT((*ChunkedJoin)(nil)) | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| package ops | |||||
| import ( | |||||
| "io" | |||||
| "sync" | |||||
| myio "gitlink.org.cn/cloudream/common/utils/io" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| ) | |||||
| type ChunkedSplit struct { | |||||
| InputID ioswitch.StreamID `json:"inputID"` | |||||
| OutputIDs []ioswitch.StreamID `json:"outputIDs"` | |||||
| ChunkSize int `json:"chunkSize"` | |||||
| StreamCount int `json:"streamCount"` | |||||
| PaddingZeros bool `json:"paddingZeros"` | |||||
| } | |||||
| func (o *ChunkedSplit) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| str, err := sw.WaitStreams(planID, o.InputID) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer str[0].Stream.Close() | |||||
| wg := sync.WaitGroup{} | |||||
| outputs := myio.ChunkedSplit(str[0].Stream, o.ChunkSize, o.StreamCount, myio.ChunkedSplitOption{ | |||||
| PaddingZeros: o.PaddingZeros, | |||||
| }) | |||||
| for i := range outputs { | |||||
| wg.Add(1) | |||||
| sw.StreamReady(planID, ioswitch.NewStream( | |||||
| o.OutputIDs[i], | |||||
| myio.AfterReadClosedOnce(outputs[i], func(closer io.ReadCloser) { | |||||
| wg.Done() | |||||
| }), | |||||
| )) | |||||
| } | |||||
| wg.Wait() | |||||
| return nil | |||||
| } | |||||
| func init() { | |||||
| OpUnion.AddT((*ChunkedSplit)(nil)) | |||||
| } | |||||
| @@ -0,0 +1,102 @@ | |||||
| package ops | |||||
| import ( | |||||
| "fmt" | |||||
| "io" | |||||
| "sync" | |||||
| myio "gitlink.org.cn/cloudream/common/utils/io" | |||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ec" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| ) | |||||
| type ECCompute struct { | |||||
| EC stgmod.EC `json:"ec"` | |||||
| InputIDs []ioswitch.StreamID `json:"inputIDs"` | |||||
| OutputIDs []ioswitch.StreamID `json:"outputIDs"` | |||||
| InputBlockIndexes []int `json:"inputBlockIndexes"` | |||||
| OutputBlockIndexes []int `json:"outputBlockIndexes"` | |||||
| } | |||||
| func (o *ECCompute) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| rs, err := ec.NewRs(o.EC.K, o.EC.N, o.EC.ChunkSize) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new ec: %w", err) | |||||
| } | |||||
| strs, err := sw.WaitStreams(planID, o.InputIDs...) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer func() { | |||||
| for _, s := range strs { | |||||
| s.Stream.Close() | |||||
| } | |||||
| }() | |||||
| var inputs []io.Reader | |||||
| for _, s := range strs { | |||||
| inputs = append(inputs, s.Stream) | |||||
| } | |||||
| outputs := rs.ReconstructSome(inputs, o.InputBlockIndexes, o.OutputBlockIndexes) | |||||
| wg := sync.WaitGroup{} | |||||
| for i, id := range o.OutputIDs { | |||||
| wg.Add(1) | |||||
| sw.StreamReady(planID, ioswitch.NewStream(id, myio.AfterReadClosedOnce(outputs[i], func(closer io.ReadCloser) { | |||||
| wg.Done() | |||||
| }))) | |||||
| } | |||||
| wg.Wait() | |||||
| return nil | |||||
| } | |||||
| type ECReconstruct struct { | |||||
| EC stgmod.EC `json:"ec"` | |||||
| InputIDs []ioswitch.StreamID `json:"inputIDs"` | |||||
| OutputIDs []ioswitch.StreamID `json:"outputIDs"` | |||||
| InputBlockIndexes []int `json:"inputBlockIndexes"` | |||||
| } | |||||
| func (o *ECReconstruct) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| rs, err := ec.NewRs(o.EC.K, o.EC.N, o.EC.ChunkSize) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new ec: %w", err) | |||||
| } | |||||
| strs, err := sw.WaitStreams(planID, o.InputIDs...) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer func() { | |||||
| for _, s := range strs { | |||||
| s.Stream.Close() | |||||
| } | |||||
| }() | |||||
| var inputs []io.Reader | |||||
| for _, s := range strs { | |||||
| inputs = append(inputs, s.Stream) | |||||
| } | |||||
| outputs := rs.ReconstructData(inputs, o.InputBlockIndexes) | |||||
| wg := sync.WaitGroup{} | |||||
| for i, id := range o.OutputIDs { | |||||
| wg.Add(1) | |||||
| sw.StreamReady(planID, ioswitch.NewStream(id, myio.AfterReadClosedOnce(outputs[i], func(closer io.ReadCloser) { | |||||
| wg.Done() | |||||
| }))) | |||||
| } | |||||
| wg.Wait() | |||||
| return nil | |||||
| } | |||||
| func init() { | |||||
| OpUnion.AddT((*ECCompute)(nil)) | |||||
| OpUnion.AddT((*ECReconstruct)(nil)) | |||||
| } | |||||
| @@ -0,0 +1,64 @@ | |||||
| package ops | |||||
| import ( | |||||
| "context" | |||||
| "fmt" | |||||
| "io" | |||||
| "os" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/future" | |||||
| myio "gitlink.org.cn/cloudream/common/utils/io" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| ) | |||||
| type FileWrite struct { | |||||
| InputID ioswitch.StreamID `json:"inputID"` | |||||
| FilePath string `json:"filePath"` | |||||
| } | |||||
| func (o *FileWrite) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| str, err := sw.WaitStreams(planID, o.InputID) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer str[0].Stream.Close() | |||||
| file, err := os.Create(o.FilePath) | |||||
| if err != nil { | |||||
| return fmt.Errorf("opening file: %w", err) | |||||
| } | |||||
| defer file.Close() | |||||
| _, err = io.Copy(file, str[0].Stream) | |||||
| if err != nil { | |||||
| return fmt.Errorf("copying data to file: %w", err) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| type FileRead struct { | |||||
| OutputID ioswitch.StreamID `json:"outputID"` | |||||
| FilePath string `json:"filePath"` | |||||
| } | |||||
| func (o *FileRead) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| file, err := os.Open(o.FilePath) | |||||
| if err != nil { | |||||
| return fmt.Errorf("opening file: %w", err) | |||||
| } | |||||
| fut := future.NewSetVoid() | |||||
| sw.StreamReady(planID, ioswitch.NewStream(o.OutputID, myio.AfterReadClosed(file, func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | |||||
| }))) | |||||
| fut.Wait(context.TODO()) | |||||
| return nil | |||||
| } | |||||
| func init() { | |||||
| OpUnion.AddT((*FileRead)(nil)) | |||||
| OpUnion.AddT((*FileWrite)(nil)) | |||||
| } | |||||
| @@ -0,0 +1,84 @@ | |||||
| package ops | |||||
| import ( | |||||
| "context" | |||||
| "fmt" | |||||
| "io" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/future" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/logger" | |||||
| myio "gitlink.org.cn/cloudream/common/utils/io" | |||||
| stgglb "gitlink.org.cn/cloudream/storage/common/globals" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| ) | |||||
| type GRPCSend struct { | |||||
| LocalID ioswitch.StreamID `json:"localID"` | |||||
| RemoteID ioswitch.StreamID `json:"remoteID"` | |||||
| Node model.Node `json:"node"` | |||||
| } | |||||
| func (o *GRPCSend) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| logger. | |||||
| WithField("LocalID", o.LocalID). | |||||
| WithField("RemoteID", o.RemoteID). | |||||
| Debugf("grpc send") | |||||
| strs, err := sw.WaitStreams(planID, o.LocalID) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer strs[0].Stream.Close() | |||||
| // TODO 根据客户端地址选择IP和端口 | |||||
| agtCli, err := stgglb.AgentRPCPool.Acquire(o.Node.ExternalIP, o.Node.ExternalGRPCPort) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new agent rpc client: %w", err) | |||||
| } | |||||
| defer stgglb.AgentRPCPool.Release(agtCli) | |||||
| err = agtCli.SendStream(planID, o.RemoteID, strs[0].Stream) | |||||
| if err != nil { | |||||
| return fmt.Errorf("sending stream: %w", err) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| type GRPCFetch struct { | |||||
| RemoteID ioswitch.StreamID `json:"remoteID"` | |||||
| LocalID ioswitch.StreamID `json:"localID"` | |||||
| Node model.Node `json:"node"` | |||||
| } | |||||
| func (o *GRPCFetch) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| // TODO 根据客户端地址选择IP和端口 | |||||
| agtCli, err := stgglb.AgentRPCPool.Acquire(o.Node.ExternalIP, o.Node.ExternalGRPCPort) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new agent rpc client: %w", err) | |||||
| } | |||||
| defer stgglb.AgentRPCPool.Release(agtCli) | |||||
| str, err := agtCli.FetchStream(planID, o.RemoteID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("fetching stream: %w", err) | |||||
| } | |||||
| fut := future.NewSetVoid() | |||||
| str = myio.AfterReadClosedOnce(str, func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | |||||
| }) | |||||
| sw.StreamReady(planID, ioswitch.NewStream(o.LocalID, str)) | |||||
| // TODO | |||||
| fut.Wait(context.TODO()) | |||||
| return err | |||||
| } | |||||
| func init() { | |||||
| OpUnion.AddT((*GRPCSend)(nil)) | |||||
| OpUnion.AddT((*GRPCFetch)(nil)) | |||||
| } | |||||
| @@ -4,7 +4,6 @@ import ( | |||||
| "context" | "context" | ||||
| "fmt" | "fmt" | ||||
| "io" | "io" | ||||
| "sync" | |||||
| "gitlink.org.cn/cloudream/common/pkgs/future" | "gitlink.org.cn/cloudream/common/pkgs/future" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/logger" | "gitlink.org.cn/cloudream/common/pkgs/logger" | ||||
| @@ -12,18 +11,12 @@ import ( | |||||
| myio "gitlink.org.cn/cloudream/common/utils/io" | myio "gitlink.org.cn/cloudream/common/utils/io" | ||||
| "gitlink.org.cn/cloudream/common/utils/serder" | "gitlink.org.cn/cloudream/common/utils/serder" | ||||
| stgglb "gitlink.org.cn/cloudream/storage/common/globals" | stgglb "gitlink.org.cn/cloudream/storage/common/globals" | ||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ec" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | ||||
| ) | ) | ||||
| var _ = serder.UseTypeUnionExternallyTagged(types.Ref(types.NewTypeUnion[ioswitch.Op]( | |||||
| var OpUnion = serder.UseTypeUnionExternallyTagged(types.Ref(types.NewTypeUnion[ioswitch.Op]( | |||||
| (*IPFSRead)(nil), | (*IPFSRead)(nil), | ||||
| (*IPFSWrite)(nil), | (*IPFSWrite)(nil), | ||||
| (*GRPCSend)(nil), | |||||
| (*GRPCFetch)(nil), | |||||
| (*ECCompute)(nil), | |||||
| (*Join)(nil), | (*Join)(nil), | ||||
| ))) | ))) | ||||
| @@ -51,7 +44,7 @@ func (o *IPFSRead) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| } | } | ||||
| fut := future.NewSetVoid() | fut := future.NewSetVoid() | ||||
| file = myio.AfterReadClosed(file, func(closer io.ReadCloser) { | |||||
| file = myio.AfterReadClosedOnce(file, func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | fut.SetVoid() | ||||
| }) | }) | ||||
| @@ -100,111 +93,6 @@ func (o *IPFSWrite) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| type GRPCSend struct { | |||||
| StreamID ioswitch.StreamID `json:"streamID"` | |||||
| Node model.Node `json:"node"` | |||||
| } | |||||
| func (o *GRPCSend) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| logger. | |||||
| WithField("ioswitch.StreamID", o.StreamID). | |||||
| Debugf("grpc send") | |||||
| strs, err := sw.WaitStreams(planID, o.StreamID) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer strs[0].Stream.Close() | |||||
| // TODO 根据客户端地址选择IP和端口 | |||||
| agtCli, err := stgglb.AgentRPCPool.Acquire(o.Node.ExternalIP, o.Node.ExternalGRPCPort) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new agent rpc client: %w", err) | |||||
| } | |||||
| defer stgglb.AgentRPCPool.Release(agtCli) | |||||
| err = agtCli.SendStream(planID, o.StreamID, strs[0].Stream) | |||||
| if err != nil { | |||||
| return fmt.Errorf("sending stream: %w", err) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| type GRPCFetch struct { | |||||
| StreamID ioswitch.StreamID `json:"streamID"` | |||||
| Node model.Node `json:"node"` | |||||
| } | |||||
| func (o *GRPCFetch) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| // TODO 根据客户端地址选择IP和端口 | |||||
| agtCli, err := stgglb.AgentRPCPool.Acquire(o.Node.ExternalIP, o.Node.ExternalGRPCPort) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new agent rpc client: %w", err) | |||||
| } | |||||
| defer stgglb.AgentRPCPool.Release(agtCli) | |||||
| str, err := agtCli.FetchStream(planID, o.StreamID) | |||||
| if err != nil { | |||||
| return fmt.Errorf("fetching stream: %w", err) | |||||
| } | |||||
| fut := future.NewSetVoid() | |||||
| str = myio.AfterReadClosed(str, func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | |||||
| }) | |||||
| sw.StreamReady(planID, ioswitch.NewStream(o.StreamID, str)) | |||||
| // TODO | |||||
| fut.Wait(context.TODO()) | |||||
| return err | |||||
| } | |||||
| type ECCompute struct { | |||||
| EC stgmod.EC `json:"ec"` | |||||
| InputIDs []ioswitch.StreamID `json:"inputIDs"` | |||||
| OutputIDs []ioswitch.StreamID `json:"outputIDs"` | |||||
| InputBlockIndexes []int `json:"inputBlockIndexes"` | |||||
| OutputBlockIndexes []int `json:"outputBlockIndexes"` | |||||
| } | |||||
| func (o *ECCompute) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| rs, err := ec.NewRs(o.EC.K, o.EC.N, o.EC.ChunkSize) | |||||
| if err != nil { | |||||
| return fmt.Errorf("new ec: %w", err) | |||||
| } | |||||
| strs, err := sw.WaitStreams(planID, o.InputIDs...) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| defer func() { | |||||
| for _, s := range strs { | |||||
| s.Stream.Close() | |||||
| } | |||||
| }() | |||||
| var inputs []io.Reader | |||||
| for _, s := range strs { | |||||
| inputs = append(inputs, s.Stream) | |||||
| } | |||||
| outputs := rs.ReconstructSome(inputs, o.InputBlockIndexes, o.OutputBlockIndexes) | |||||
| wg := sync.WaitGroup{} | |||||
| for i, id := range o.OutputIDs { | |||||
| wg.Add(1) | |||||
| sw.StreamReady(planID, ioswitch.NewStream(id, myio.AfterReadClosed(outputs[i], func(closer io.ReadCloser) { | |||||
| wg.Done() | |||||
| }))) | |||||
| } | |||||
| wg.Wait() | |||||
| return nil | |||||
| } | |||||
| type Join struct { | type Join struct { | ||||
| InputIDs []ioswitch.StreamID `json:"inputIDs"` | InputIDs []ioswitch.StreamID `json:"inputIDs"` | ||||
| OutputID ioswitch.StreamID `json:"outputID"` | OutputID ioswitch.StreamID `json:"outputID"` | ||||
| @@ -230,7 +118,7 @@ func (o *Join) Execute(sw *ioswitch.Switch, planID ioswitch.PlanID) error { | |||||
| fut := future.NewSetVoid() | fut := future.NewSetVoid() | ||||
| sw.StreamReady(planID, | sw.StreamReady(planID, | ||||
| ioswitch.NewStream(o.OutputID, | ioswitch.NewStream(o.OutputID, | ||||
| myio.AfterReadClosed(myio.Length(myio.Join(strReaders), o.Length), func(closer io.ReadCloser) { | |||||
| myio.AfterReadClosedOnce(myio.Length(myio.Join(strReaders), o.Length), func(closer io.ReadCloser) { | |||||
| fut.SetVoid() | fut.SetVoid() | ||||
| }), | }), | ||||
| ), | ), | ||||
| @@ -0,0 +1,116 @@ | |||||
| package plans | |||||
| import ( | |||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/ops" | |||||
| ) | |||||
| func (b *AgentPlanBuilder) GRCPFetch(node model.Node, str *AgentStream) *AgentStream { | |||||
| agtStr := &AgentStream{ | |||||
| owner: b, | |||||
| info: b.owner.newStream(), | |||||
| } | |||||
| b.ops = append(b.ops, &ops.GRPCFetch{ | |||||
| RemoteID: str.info.ID, | |||||
| LocalID: agtStr.info.ID, | |||||
| Node: node, | |||||
| }) | |||||
| return agtStr | |||||
| } | |||||
| func (s *AgentStream) GRPCSend(node model.Node) *AgentStream { | |||||
| agtStr := &AgentStream{ | |||||
| owner: s.owner.owner.AtAgent(node), | |||||
| info: s.owner.owner.newStream(), | |||||
| } | |||||
| s.owner.ops = append(s.owner.ops, &ops.GRPCSend{ | |||||
| LocalID: s.info.ID, | |||||
| RemoteID: agtStr.info.ID, | |||||
| Node: node, | |||||
| }) | |||||
| return agtStr | |||||
| } | |||||
| func (b *AgentPlanBuilder) FileRead(filePath string) *AgentStream { | |||||
| agtStr := &AgentStream{ | |||||
| owner: b, | |||||
| info: b.owner.newStream(), | |||||
| } | |||||
| b.ops = append(b.ops, &ops.FileRead{ | |||||
| OutputID: agtStr.info.ID, | |||||
| FilePath: filePath, | |||||
| }) | |||||
| return agtStr | |||||
| } | |||||
| func (b *AgentStream) FileWrite(filePath string) { | |||||
| b.owner.ops = append(b.owner.ops, &ops.FileWrite{ | |||||
| InputID: b.info.ID, | |||||
| FilePath: filePath, | |||||
| }) | |||||
| } | |||||
| func (b *AgentPlanBuilder) ECCompute(ec stgmod.EC, inBlockIndexes []int, outBlockIndexes []int, streams ...*AgentStream) *MultiStream { | |||||
| mstr := &MultiStream{} | |||||
| var inputStrIDs []ioswitch.StreamID | |||||
| for _, str := range streams { | |||||
| inputStrIDs = append(inputStrIDs, str.info.ID) | |||||
| } | |||||
| var outputStrIDs []ioswitch.StreamID | |||||
| for i := 0; i < ec.N-ec.K; i++ { | |||||
| info := b.owner.newStream() | |||||
| mstr.Streams = append(mstr.Streams, &AgentStream{ | |||||
| owner: b, | |||||
| info: info, | |||||
| }) | |||||
| outputStrIDs = append(outputStrIDs, info.ID) | |||||
| } | |||||
| b.ops = append(b.ops, &ops.ECCompute{ | |||||
| EC: ec, | |||||
| InputIDs: inputStrIDs, | |||||
| OutputIDs: outputStrIDs, | |||||
| InputBlockIndexes: inBlockIndexes, | |||||
| OutputBlockIndexes: outBlockIndexes, | |||||
| }) | |||||
| return mstr | |||||
| } | |||||
| func (b *AgentPlanBuilder) ECReconstruct(ec stgmod.EC, inBlockIndexes []int, streams ...*AgentStream) *MultiStream { | |||||
| mstr := &MultiStream{} | |||||
| var inputStrIDs []ioswitch.StreamID | |||||
| for _, str := range streams { | |||||
| inputStrIDs = append(inputStrIDs, str.info.ID) | |||||
| } | |||||
| var outputStrIDs []ioswitch.StreamID | |||||
| for i := 0; i < ec.K; i++ { | |||||
| info := b.owner.newStream() | |||||
| mstr.Streams = append(mstr.Streams, &AgentStream{ | |||||
| owner: b, | |||||
| info: info, | |||||
| }) | |||||
| outputStrIDs = append(outputStrIDs, info.ID) | |||||
| } | |||||
| b.ops = append(b.ops, &ops.ECReconstruct{ | |||||
| EC: ec, | |||||
| InputIDs: inputStrIDs, | |||||
| OutputIDs: outputStrIDs, | |||||
| InputBlockIndexes: inBlockIndexes, | |||||
| }) | |||||
| return mstr | |||||
| } | |||||
| @@ -4,7 +4,6 @@ import ( | |||||
| "fmt" | "fmt" | ||||
| "github.com/google/uuid" | "github.com/google/uuid" | ||||
| stgmod "gitlink.org.cn/cloudream/storage/common/models" | |||||
| "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | "gitlink.org.cn/cloudream/storage/common/pkgs/db/model" | ||||
| "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" | "gitlink.org.cn/cloudream/storage/common/pkgs/ioswitch/ops" | ||||
| @@ -105,18 +104,28 @@ func (s *AgentStream) IPFSWrite(resultKey string) { | |||||
| }) | }) | ||||
| } | } | ||||
| func (s *AgentStream) GRPCSend(node model.Node) *AgentStream { | |||||
| agtStr := &AgentStream{ | |||||
| owner: s.owner.owner.AtAgent(node), | |||||
| info: s.info, | |||||
| func (b *AgentStream) ChunkSplit(chunkSize int, streamCount int, paddingZeros bool) *MultiStream { | |||||
| mstr := &MultiStream{} | |||||
| var outputStrIDs []ioswitch.StreamID | |||||
| for i := 0; i < streamCount; i++ { | |||||
| info := b.owner.owner.newStream() | |||||
| mstr.Streams = append(mstr.Streams, &AgentStream{ | |||||
| owner: b.owner, | |||||
| info: info, | |||||
| }) | |||||
| outputStrIDs = append(outputStrIDs, info.ID) | |||||
| } | } | ||||
| s.owner.ops = append(s.owner.ops, &ops.GRPCSend{ | |||||
| StreamID: s.info.ID, | |||||
| Node: node, | |||||
| b.owner.ops = append(b.owner.ops, &ops.ChunkedSplit{ | |||||
| InputID: b.info.ID, | |||||
| OutputIDs: outputStrIDs, | |||||
| ChunkSize: chunkSize, | |||||
| StreamCount: streamCount, | |||||
| PaddingZeros: paddingZeros, | |||||
| }) | }) | ||||
| return agtStr | |||||
| return mstr | |||||
| } | } | ||||
| func (s *AgentStream) ToExecutor() *ToExecutorStream { | func (s *AgentStream) ToExecutor() *ToExecutorStream { | ||||
| @@ -132,20 +141,6 @@ type AgentPlanBuilder struct { | |||||
| ops []ioswitch.Op | ops []ioswitch.Op | ||||
| } | } | ||||
| func (b *AgentPlanBuilder) GRCPFetch(node model.Node) *AgentStream { | |||||
| agtStr := &AgentStream{ | |||||
| owner: b, | |||||
| info: b.owner.newStream(), | |||||
| } | |||||
| b.ops = append(b.ops, &ops.GRPCFetch{ | |||||
| StreamID: agtStr.info.ID, | |||||
| Node: node, | |||||
| }) | |||||
| return agtStr | |||||
| } | |||||
| func (b *AgentPlanBuilder) IPFSRead(fileHash string) *AgentStream { | func (b *AgentPlanBuilder) IPFSRead(fileHash string) *AgentStream { | ||||
| agtStr := &AgentStream{ | agtStr := &AgentStream{ | ||||
| owner: b, | owner: b, | ||||
| @@ -160,36 +155,27 @@ func (b *AgentPlanBuilder) IPFSRead(fileHash string) *AgentStream { | |||||
| return agtStr | return agtStr | ||||
| } | } | ||||
| func (b *AgentPlanBuilder) ECCompute(ec stgmod.EC, inBlockIndexes []int, outBlockIndexes []int, streams ...*AgentStream) *MultiStream { | |||||
| mstr := &MultiStream{} | |||||
| func (b *AgentPlanBuilder) Join(length int64, streams ...*AgentStream) *AgentStream { | |||||
| agtStr := &AgentStream{ | |||||
| owner: b, | |||||
| info: b.owner.newStream(), | |||||
| } | |||||
| var inputStrIDs []ioswitch.StreamID | var inputStrIDs []ioswitch.StreamID | ||||
| for _, str := range streams { | for _, str := range streams { | ||||
| inputStrIDs = append(inputStrIDs, str.info.ID) | inputStrIDs = append(inputStrIDs, str.info.ID) | ||||
| } | } | ||||
| var outputStrIDs []ioswitch.StreamID | |||||
| for i := 0; i < ec.N-ec.K; i++ { | |||||
| info := b.owner.newStream() | |||||
| mstr.streams[i] = &AgentStream{ | |||||
| owner: b, | |||||
| info: info, | |||||
| } | |||||
| outputStrIDs = append(outputStrIDs, info.ID) | |||||
| } | |||||
| b.ops = append(b.ops, &ops.ECCompute{ | |||||
| EC: ec, | |||||
| InputIDs: inputStrIDs, | |||||
| OutputIDs: outputStrIDs, | |||||
| InputBlockIndexes: inBlockIndexes, | |||||
| OutputBlockIndexes: outBlockIndexes, | |||||
| b.ops = append(b.ops, &ops.Join{ | |||||
| InputIDs: inputStrIDs, | |||||
| OutputID: agtStr.info.ID, | |||||
| Length: length, | |||||
| }) | }) | ||||
| return mstr | |||||
| return agtStr | |||||
| } | } | ||||
| func (b *AgentPlanBuilder) Join(length int64, streams ...*AgentStream) *AgentStream { | |||||
| func (b *AgentPlanBuilder) ChunkJoin(chunkSize int, streams ...*AgentStream) *AgentStream { | |||||
| agtStr := &AgentStream{ | agtStr := &AgentStream{ | ||||
| owner: b, | owner: b, | ||||
| info: b.owner.newStream(), | info: b.owner.newStream(), | ||||
| @@ -200,10 +186,10 @@ func (b *AgentPlanBuilder) Join(length int64, streams ...*AgentStream) *AgentStr | |||||
| inputStrIDs = append(inputStrIDs, str.info.ID) | inputStrIDs = append(inputStrIDs, str.info.ID) | ||||
| } | } | ||||
| b.ops = append(b.ops, &ops.Join{ | |||||
| InputIDs: inputStrIDs, | |||||
| OutputID: agtStr.info.ID, | |||||
| Length: length, | |||||
| b.ops = append(b.ops, &ops.ChunkedJoin{ | |||||
| InputIDs: inputStrIDs, | |||||
| OutputID: agtStr.info.ID, | |||||
| ChunkSize: chunkSize, | |||||
| }) | }) | ||||
| return agtStr | return agtStr | ||||
| @@ -222,9 +208,13 @@ func (b *AgentPlanBuilder) Build(planID ioswitch.PlanID) (AgentPlan, error) { | |||||
| } | } | ||||
| type MultiStream struct { | type MultiStream struct { | ||||
| streams []*AgentStream | |||||
| Streams []*AgentStream | |||||
| } | |||||
| func (m *MultiStream) Count() int { | |||||
| return len(m.Streams) | |||||
| } | } | ||||
| func (m *MultiStream) Stream(index int) *AgentStream { | func (m *MultiStream) Stream(index int) *AgentStream { | ||||
| return m.streams[index] | |||||
| return m.Streams[index] | |||||
| } | } | ||||