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.

graph.go 3.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package dag
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "gitlink.org.cn/cloudream/common/utils/lo2"
  7. "gitlink.org.cn/cloudream/common/utils/reflect2"
  8. )
  9. type Graph struct {
  10. Nodes []Node
  11. isWalking bool
  12. }
  13. func NewGraph() *Graph {
  14. return &Graph{}
  15. }
  16. func (g *Graph) AddNode(node Node) {
  17. g.Nodes = append(g.Nodes, node)
  18. node.SetGraph(g)
  19. }
  20. func (g *Graph) RemoveNode(node Node) {
  21. for i, n := range g.Nodes {
  22. if n == node {
  23. if g.isWalking {
  24. g.Nodes[i] = nil
  25. } else {
  26. g.Nodes = lo2.RemoveAt(g.Nodes, i)
  27. }
  28. break
  29. }
  30. }
  31. }
  32. func (g *Graph) Walk(cb func(node Node) bool) {
  33. g.isWalking = true
  34. for i := 0; i < len(g.Nodes); i++ {
  35. if g.Nodes[i] == nil {
  36. continue
  37. }
  38. if !cb(g.Nodes[i]) {
  39. break
  40. }
  41. }
  42. g.isWalking = false
  43. g.Nodes = lo2.RemoveAllDefault(g.Nodes)
  44. }
  45. func (g *Graph) NewStreamVar() *StreamVar {
  46. return &StreamVar{}
  47. }
  48. func (g *Graph) NewValueVar() *ValueVar {
  49. return &ValueVar{}
  50. }
  51. func (g *Graph) Dump() string {
  52. nodeIDs := make(map[Node]int)
  53. for i, node := range g.Nodes {
  54. nodeIDs[node] = i
  55. }
  56. var sb strings.Builder
  57. for _, node := range g.Nodes {
  58. id, ok := nodeIDs[node]
  59. if !ok {
  60. id = len(nodeIDs)
  61. nodeIDs[node] = id
  62. }
  63. sb.WriteString(fmt.Sprintf("[%v]%v\n", id, nodeTypeName(node)))
  64. if node.InputStreams().Len() > 0 {
  65. sb.WriteString("SIn: ")
  66. for i, in := range node.InputStreams().Slots {
  67. if i > 0 {
  68. sb.WriteString(", ")
  69. }
  70. if in == nil {
  71. sb.WriteString("?")
  72. } else {
  73. sb.WriteString(fmt.Sprintf("%v", nodeIDs[in.Src]))
  74. }
  75. }
  76. sb.WriteString("\n")
  77. }
  78. if node.OutputStreams().Len() > 0 {
  79. sb.WriteString("SOut: ")
  80. for i, out := range node.OutputStreams().Slots {
  81. if i > 0 {
  82. sb.WriteString(", ")
  83. }
  84. sb.WriteString("(")
  85. for i2, dst := range out.Dst {
  86. if i2 > 0 {
  87. sb.WriteString(", ")
  88. }
  89. sb.WriteString(fmt.Sprintf("%v", nodeIDs[dst]))
  90. }
  91. sb.WriteString(")")
  92. }
  93. sb.WriteString("\n")
  94. }
  95. if node.InputValues().Len() > 0 {
  96. sb.WriteString("VIn: ")
  97. for i, in := range node.InputValues().Slots {
  98. if i > 0 {
  99. sb.WriteString(", ")
  100. }
  101. if in == nil {
  102. sb.WriteString("?")
  103. } else {
  104. sb.WriteString(fmt.Sprintf("%v", nodeIDs[in.Src]))
  105. }
  106. }
  107. sb.WriteString("\n")
  108. }
  109. if node.OutputValues().Len() > 0 {
  110. sb.WriteString("VOut: ")
  111. for i, out := range node.OutputValues().Slots {
  112. if i > 0 {
  113. sb.WriteString(", ")
  114. }
  115. sb.WriteString("(")
  116. for i2, dst := range out.Dst {
  117. if i2 > 0 {
  118. sb.WriteString(", ")
  119. }
  120. sb.WriteString(fmt.Sprintf("%v", nodeIDs[dst]))
  121. }
  122. sb.WriteString(")")
  123. }
  124. sb.WriteString("\n")
  125. }
  126. }
  127. return sb.String()
  128. }
  129. func nodeTypeName(node Node) string {
  130. typ := reflect2.TypeOfValue(node)
  131. for typ.Kind() == reflect.Ptr {
  132. typ = typ.Elem()
  133. }
  134. return typ.Name()
  135. }
  136. func AddNode[N Node](graph *Graph, typ N) N {
  137. graph.AddNode(typ)
  138. return typ
  139. }
  140. func WalkOnlyType[N Node](g *Graph, cb func(node N) bool) {
  141. g.Walk(func(n Node) bool {
  142. node, ok := n.(N)
  143. if ok {
  144. return cb(node)
  145. }
  146. return true
  147. })
  148. }

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