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.

switch.go 2.8 kB

2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package ioswitch
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "gitlink.org.cn/cloudream/common/pkgs/future"
  7. "gitlink.org.cn/cloudream/common/utils/lo2"
  8. "gitlink.org.cn/cloudream/common/utils/sync2"
  9. )
  10. type bindingVars struct {
  11. Waittings []Var
  12. Bindeds []Var
  13. Callback *future.SetVoidFuture
  14. }
  15. type Switch struct {
  16. plan Plan
  17. vars map[VarID]Var
  18. bindings []*bindingVars
  19. lock sync.Mutex
  20. }
  21. func NewSwitch(plan Plan) *Switch {
  22. planning := Switch{
  23. plan: plan,
  24. vars: make(map[VarID]Var),
  25. }
  26. return &planning
  27. }
  28. func (s *Switch) Plan() *Plan {
  29. return &s.plan
  30. }
  31. func (s *Switch) Run(ctx context.Context) error {
  32. ctx2, cancel := context.WithCancel(ctx)
  33. defer cancel()
  34. return sync2.ParallelDo(s.plan.Ops, func(o Op, idx int) error {
  35. err := o.Execute(ctx2, s)
  36. s.lock.Lock()
  37. defer s.lock.Unlock()
  38. if err != nil {
  39. cancel()
  40. return fmt.Errorf("%T: %w", o, err)
  41. }
  42. return nil
  43. })
  44. }
  45. func (s *Switch) BindVars(ctx context.Context, vs ...Var) error {
  46. s.lock.Lock()
  47. callback := future.NewSetVoid()
  48. binding := &bindingVars{
  49. Callback: callback,
  50. }
  51. for _, v := range vs {
  52. v2 := s.vars[v.GetID()]
  53. if v2 == nil {
  54. binding.Waittings = append(binding.Waittings, v)
  55. continue
  56. }
  57. if err := AssignVar(v2, v); err != nil {
  58. s.lock.Unlock()
  59. return fmt.Errorf("assign var %v to %v: %w", v2.GetID(), v.GetID(), err)
  60. }
  61. binding.Bindeds = append(binding.Bindeds, v)
  62. }
  63. if len(binding.Waittings) == 0 {
  64. s.lock.Unlock()
  65. return nil
  66. }
  67. s.bindings = append(s.bindings, binding)
  68. s.lock.Unlock()
  69. err := callback.Wait(ctx)
  70. s.lock.Lock()
  71. defer s.lock.Unlock()
  72. s.bindings = lo2.Remove(s.bindings, binding)
  73. return err
  74. }
  75. func (s *Switch) PutVars(vs ...Var) {
  76. s.lock.Lock()
  77. defer s.lock.Unlock()
  78. loop:
  79. for _, v := range vs {
  80. for ib, b := range s.bindings {
  81. for iw, w := range b.Waittings {
  82. if w.GetID() != v.GetID() {
  83. continue
  84. }
  85. if err := AssignVar(v, w); err != nil {
  86. b.Callback.SetError(fmt.Errorf("assign var %v to %v: %w", v.GetID(), w.GetID(), err))
  87. // 绑定类型不对,说明生成的执行计划有问题,怎么处理都可以,因为最终会执行失败
  88. continue loop
  89. }
  90. b.Bindeds = append(b.Bindeds, w)
  91. b.Waittings = lo2.RemoveAt(b.Waittings, iw)
  92. if len(b.Waittings) == 0 {
  93. b.Callback.SetVoid()
  94. s.bindings = lo2.RemoveAt(s.bindings, ib)
  95. }
  96. // 绑定成功,继续最外层循环
  97. continue loop
  98. }
  99. }
  100. // 如果没有绑定,则直接放入变量表中
  101. s.vars[v.GetID()] = v
  102. }
  103. }
  104. func BindArrayVars[T Var](sw *Switch, ctx context.Context, vs []T) error {
  105. var vs2 []Var
  106. for _, v := range vs {
  107. vs2 = append(vs2, v)
  108. }
  109. return sw.BindVars(ctx, vs2...)
  110. }
  111. func PutArrayVars[T Var](sw *Switch, vs []T) {
  112. var vs2 []Var
  113. for _, v := range vs {
  114. vs2 = append(vs2, v)
  115. }
  116. sw.PutVars(vs2...)
  117. }

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