|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package exec
-
- import (
- "context"
- "fmt"
- "io"
- "sync"
-
- "github.com/hashicorp/go-multierror"
- "gitlink.org.cn/cloudream/common/pkgs/future"
- "gitlink.org.cn/cloudream/common/utils/io2"
- "gitlink.org.cn/cloudream/common/utils/math2"
- )
-
- type Driver struct {
- planID PlanID
- planBlder *PlanBuilder
- callback *future.SetValueFuture[map[string]VarValue]
- ctx *ExecContext
- cancel context.CancelFunc
- driverExec *Executor
- }
-
- // 开始写入一个流。此函数会将输入视为一个完整的流,因此会给流包装一个Range来获取只需要的部分。
- func (e *Driver) BeginWrite(str io.ReadCloser, handle *DriverWriteStream) {
- e.driverExec.PutVar(handle.ID, &StreamValue{Stream: io2.NewRange(str, handle.RangeHint.Offset, handle.RangeHint.Length)})
- }
-
- // 开始写入一个流。此函数默认输入流已经是Handle的RangeHint锁描述的范围,因此不会做任何其他处理
- func (e *Driver) BeginWriteRanged(str io.ReadCloser, handle *DriverWriteStream) {
- e.driverExec.PutVar(handle.ID, &StreamValue{Stream: str})
- }
-
- func (e *Driver) BeginRead(handle *DriverReadStream) (io.ReadCloser, error) {
- str, err := BindVar[*StreamValue](e.driverExec, e.ctx.Context, handle.ID)
- if err != nil {
- return nil, fmt.Errorf("bind vars: %w", err)
- }
-
- return str.Stream, nil
- }
-
- func (e *Driver) Signal(signal *DriverSignalVar) {
- e.driverExec.PutVar(signal.ID, &SignalValue{})
- }
-
- func (e *Driver) Wait(ctx context.Context) (map[string]VarValue, error) {
- stored, err := e.callback.Wait(ctx)
- if err != nil {
- return nil, err
- }
-
- return stored, nil
- }
-
- func (e *Driver) execute() {
- wg := sync.WaitGroup{}
-
- errLock := sync.Mutex{}
- var execErr error
- for _, p := range e.planBlder.WorkerPlans {
- wg.Add(1)
-
- go func(p *WorkerPlanBuilder, ctx context.Context, cancel context.CancelFunc) {
- defer wg.Done()
-
- plan := Plan{
- ID: e.planID,
- Ops: p.Ops,
- }
-
- cli, err := p.Worker.NewClient()
- if err != nil {
- errLock.Lock()
- execErr = multierror.Append(execErr, fmt.Errorf("worker %v: new client: %w", p.Worker, err))
- errLock.Unlock()
- cancel()
- return
- }
- defer cli.Close()
-
- err = cli.ExecutePlan(ctx, plan)
- if err != nil {
- errLock.Lock()
- execErr = multierror.Append(execErr, fmt.Errorf("worker %v: execute plan: %w", p.Worker, err))
- errLock.Unlock()
- cancel()
- return
- }
- }(p, e.ctx.Context, e.cancel)
- }
-
- stored, err := e.driverExec.Run(e.ctx)
- if err != nil {
- errLock.Lock()
- execErr = multierror.Append(execErr, fmt.Errorf("driver: execute plan: %w", err))
- errLock.Unlock()
- e.cancel()
- }
-
- wg.Wait()
-
- e.callback.SetComplete(stored, execErr)
- }
-
- type DriverWriteStream struct {
- ID VarID
- RangeHint *math2.Range
- }
-
- type DriverReadStream struct {
- ID VarID
- }
-
- type DriverSignalVar struct {
- ID VarID
- Signal SignalValue
- }
|