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.

driver.go 3.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package exec
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "sync"
  7. "github.com/hashicorp/go-multierror"
  8. "gitlink.org.cn/cloudream/common/pkgs/future"
  9. "gitlink.org.cn/cloudream/common/utils/io2"
  10. "gitlink.org.cn/cloudream/common/utils/math2"
  11. )
  12. type Driver struct {
  13. planID PlanID
  14. planBlder *PlanBuilder
  15. callback *future.SetValueFuture[PlanResult]
  16. ctx *ExecContext
  17. cancel context.CancelFunc
  18. driverExec *Executor
  19. }
  20. // 开始写入一个流。此函数会将输入视为一个完整的流,因此会给流包装一个Range来获取只需要的部分。
  21. func (e *Driver) BeginWrite(str io.ReadCloser, handle *DriverWriteStream) {
  22. e.driverExec.PutVar(handle.ID, &StreamValue{Stream: io2.NewRange(str, handle.RangeHint.Offset, handle.RangeHint.Length)})
  23. }
  24. // 开始写入一个流。此函数默认输入流已经是Handle的RangeHint锁描述的范围,因此不会做任何其他处理
  25. func (e *Driver) BeginWriteRanged(str io.ReadCloser, handle *DriverWriteStream) {
  26. e.driverExec.PutVar(handle.ID, &StreamValue{Stream: str})
  27. }
  28. func (e *Driver) BeginRead(handle *DriverReadStream) (io.ReadCloser, error) {
  29. str, err := BindVar[*StreamValue](e.driverExec, e.ctx.Context, handle.ID)
  30. if err != nil {
  31. return nil, fmt.Errorf("bind vars: %w", err)
  32. }
  33. return str.Stream, nil
  34. }
  35. func (e *Driver) Signal(signal *DriverSignalVar) {
  36. e.driverExec.PutVar(signal.ID, &SignalValue{})
  37. }
  38. func (e *Driver) Wait(ctx context.Context) (PlanResult, error) {
  39. ret, err := e.callback.Wait(ctx)
  40. if err != nil {
  41. return PlanResult{}, err
  42. }
  43. return ret, nil
  44. }
  45. func (e *Driver) execute() {
  46. wg := sync.WaitGroup{}
  47. retLock := sync.Mutex{}
  48. var execErr error
  49. stored := make(map[string][]VarValue)
  50. for _, p := range e.planBlder.WorkerPlans {
  51. wg.Add(1)
  52. go func(p *WorkerPlanBuilder, ctx context.Context, cancel context.CancelFunc) {
  53. defer wg.Done()
  54. plan := Plan{
  55. ID: e.planID,
  56. Ops: p.Ops,
  57. }
  58. cli, err := p.Worker.NewClient()
  59. if err != nil {
  60. retLock.Lock()
  61. execErr = multierror.Append(execErr, fmt.Errorf("worker %v: new client: %w", p.Worker, err))
  62. retLock.Unlock()
  63. cancel()
  64. return
  65. }
  66. defer cli.Close()
  67. ret, err := cli.ExecutePlan(ctx, plan)
  68. if err != nil {
  69. retLock.Lock()
  70. execErr = multierror.Append(execErr, fmt.Errorf("worker %v: execute plan: %w", p.Worker, err))
  71. retLock.Unlock()
  72. cancel()
  73. return
  74. }
  75. retLock.Lock()
  76. for k, v := range ret.Stored {
  77. stored[k] = append(stored[k], v...)
  78. }
  79. retLock.Unlock()
  80. }(p, e.ctx.Context, e.cancel)
  81. }
  82. ret, err := e.driverExec.Run(e.ctx)
  83. if err != nil {
  84. retLock.Lock()
  85. execErr = multierror.Append(execErr, fmt.Errorf("driver: execute plan: %w", err))
  86. retLock.Unlock()
  87. e.cancel()
  88. }
  89. wg.Wait()
  90. for k, v := range ret.Stored {
  91. stored[k] = append(stored[k], v...)
  92. }
  93. e.callback.SetComplete(PlanResult{
  94. Stored: stored,
  95. }, execErr)
  96. }
  97. type DriverWriteStream struct {
  98. ID VarID
  99. RangeHint *math2.Range
  100. }
  101. type DriverReadStream struct {
  102. ID VarID
  103. }
  104. type DriverSignalVar struct {
  105. ID VarID
  106. Signal SignalValue
  107. }
  108. type PlanResult struct {
  109. Stored map[string][]VarValue
  110. }
  111. func (r *PlanResult) Get(key string) VarValue {
  112. v, ok := r.Stored[key]
  113. if !ok || len(v) == 0 {
  114. return nil
  115. }
  116. return v[0]
  117. }
  118. func (r *PlanResult) GetArray(key string) []VarValue {
  119. v, ok := r.Stored[key]
  120. if !ok {
  121. return nil
  122. }
  123. return v
  124. }

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