mnt_tree.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package mountree
  2. import (
  3. "strings"
  4. "sync"
  5. )
  6. type TreeNode[T PayloadType] struct {
  7. Path []string
  8. Children map[string]*TreeNode[T]
  9. Parent *TreeNode[T]
  10. Payload *T
  11. }
  12. type Tree[T PayloadType] struct {
  13. root *TreeNode[T]
  14. rwlock sync.RWMutex
  15. }
  16. func NewTree[T PayloadType]() *Tree[T] {
  17. tree := &Tree[T]{
  18. root: &TreeNode[T]{
  19. Path: []string{},
  20. Children: make(map[string]*TreeNode[T]),
  21. Parent: nil,
  22. Payload: nil,
  23. },
  24. rwlock: sync.RWMutex{},
  25. }
  26. return tree
  27. }
  28. func (t *Tree[T]) search(
  29. pathSeq []string,
  30. found func(fnode *TreeNode[T], remainPath []string, pnode *TreeNode[T]) error,
  31. readonly bool,
  32. ) error {
  33. fspnode := t.root
  34. if readonly {
  35. defer t.rwlock.RUnlock()
  36. t.rwlock.RLock()
  37. } else {
  38. defer t.rwlock.Unlock()
  39. t.rwlock.Lock()
  40. }
  41. total := len(pathSeq)
  42. if total <= 0 {
  43. return found(t.root, []string{}, fspnode)
  44. }
  45. current := t.root
  46. for i, v := range pathSeq {
  47. if current.Children == nil || len(current.Children) == 0 {
  48. return found(current, pathSeq[i:], fspnode)
  49. }
  50. if child, ok := current.Children[v]; ok {
  51. current = child
  52. if current.Payload != nil {
  53. fspnode = current
  54. }
  55. } else {
  56. return found(current, pathSeq[i:], fspnode)
  57. }
  58. }
  59. return found(current, []string{}, fspnode)
  60. }
  61. func (t *Tree[T]) Mount(pathSeq []string, payload T, forceRemount bool) error {
  62. return t.search(
  63. pathSeq,
  64. func(fnode *TreeNode[T], remainPath []string, pnode *TreeNode[T]) error {
  65. if len(remainPath) == 0 {
  66. if fnode.Payload != nil && !forceRemount {
  67. return ErrMountPointAlreadyExists
  68. }
  69. fnode.Payload = &payload
  70. return nil
  71. }
  72. currentPath := fnode.Path
  73. currentNode := fnode
  74. for _, v := range remainPath {
  75. currentPath = append(currentPath, v)
  76. newNode := &TreeNode[T]{
  77. Path: currentPath,
  78. Children: make(map[string]*TreeNode[T]),
  79. Parent: currentNode,
  80. Payload: nil,
  81. }
  82. currentNode.Children[v] = newNode
  83. currentNode = newNode
  84. }
  85. currentNode.Payload = &payload
  86. return nil
  87. },
  88. false,
  89. )
  90. }
  91. func (t *Tree[T]) Umount(pathSeq []string) error {
  92. if len(pathSeq) == 0 {
  93. t.root.Payload = nil
  94. return nil
  95. }
  96. return t.search(
  97. pathSeq,
  98. func(fnode *TreeNode[T], remainPath []string, pnode *TreeNode[T]) error {
  99. if len(remainPath) != 0 {
  100. return ErrMountPointNotExists
  101. }
  102. if len(fnode.Children) > 0 {
  103. fnode.Payload = nil
  104. return nil
  105. } else {
  106. pnode := fnode.Parent
  107. delete(pnode.Children, fnode.Path[len(fnode.Path)-1])
  108. return nil
  109. }
  110. },
  111. false,
  112. )
  113. }
  114. func (t *Tree[T]) GetPayload(pathSeq []string) (payload *T, RemainPath []string, rerr error) {
  115. payload = nil
  116. RemainPath = pathSeq
  117. rerr = t.search(
  118. pathSeq,
  119. func(fnode *TreeNode[T], remainPath []string, pnode *TreeNode[T]) error {
  120. if fnode.Payload == nil {
  121. if pnode.Payload == nil {
  122. return ErrNoAvailableMountPointForThisPath
  123. } else {
  124. payload = pnode.Payload
  125. xpl := len(pnode.Path)
  126. RemainPath = pathSeq[xpl:]
  127. return nil
  128. }
  129. } else {
  130. RemainPath = remainPath
  131. payload = fnode.Payload
  132. return nil
  133. }
  134. },
  135. true,
  136. )
  137. return
  138. }
  139. func (t *Tree[T]) ListAllMount(prt func(path string, payload T), sep string) {
  140. stack := []*TreeNode[T]{t.root}
  141. for len(stack) > 0 {
  142. node := stack[len(stack)-1]
  143. stack = stack[:len(stack)-1]
  144. if node.Payload != nil {
  145. prtPath := sep + strings.Join(node.Path, sep)
  146. prt(prtPath, *node.Payload)
  147. }
  148. for _, child := range node.Children {
  149. stack = append(stack, child)
  150. }
  151. }
  152. }