inode_to_path.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package mount
  2. import (
  3. "github.com/chrislusf/seaweedfs/weed/glog"
  4. "github.com/chrislusf/seaweedfs/weed/util"
  5. "sync"
  6. )
  7. type InodeToPath struct {
  8. sync.RWMutex
  9. nextInodeId uint64
  10. inode2path map[uint64]*InodeEntry
  11. path2inode map[util.FullPath]uint64
  12. }
  13. type InodeEntry struct {
  14. util.FullPath
  15. nlookup uint64
  16. isDirectory bool
  17. isChildrenCached bool
  18. }
  19. func NewInodeToPath() *InodeToPath {
  20. t := &InodeToPath{
  21. inode2path: make(map[uint64]*InodeEntry),
  22. path2inode: make(map[util.FullPath]uint64),
  23. nextInodeId: 2, // the root inode id is 1
  24. }
  25. t.inode2path[1] = &InodeEntry{"/", 1, true, false}
  26. t.path2inode["/"] = 1
  27. return t
  28. }
  29. func (i *InodeToPath) Lookup(path util.FullPath, isDirectory bool) uint64 {
  30. i.Lock()
  31. defer i.Unlock()
  32. inode, found := i.path2inode[path]
  33. if !found {
  34. inode = i.nextInodeId
  35. i.nextInodeId++
  36. i.path2inode[path] = inode
  37. i.inode2path[inode] = &InodeEntry{path, 1, isDirectory, false}
  38. } else {
  39. i.inode2path[inode].nlookup++
  40. }
  41. return inode
  42. }
  43. func (i *InodeToPath) GetInode(path util.FullPath) uint64 {
  44. if path == "/" {
  45. return 1
  46. }
  47. i.Lock()
  48. defer i.Unlock()
  49. inode, found := i.path2inode[path]
  50. if !found {
  51. // glog.Fatalf("GetInode unknown inode for %s", path)
  52. // this could be the parent for mount point
  53. }
  54. return inode
  55. }
  56. func (i *InodeToPath) GetPath(inode uint64) util.FullPath {
  57. i.RLock()
  58. defer i.RUnlock()
  59. path, found := i.inode2path[inode]
  60. if !found {
  61. glog.Fatalf("not found inode %d", inode)
  62. }
  63. return path.FullPath
  64. }
  65. func (i *InodeToPath) HasPath(path util.FullPath) bool {
  66. i.RLock()
  67. defer i.RUnlock()
  68. _, found := i.path2inode[path]
  69. return found
  70. }
  71. func (i *InodeToPath) MarkChildrenCached(fullpath util.FullPath) {
  72. i.RLock()
  73. defer i.RUnlock()
  74. inode, found := i.path2inode[fullpath]
  75. if !found {
  76. glog.Fatalf("MarkChildrenCached not found inode %v", fullpath)
  77. }
  78. path, found := i.inode2path[inode]
  79. path.isChildrenCached = true
  80. }
  81. func (i *InodeToPath) IsChildrenCached(fullpath util.FullPath) bool {
  82. i.RLock()
  83. defer i.RUnlock()
  84. inode, found := i.path2inode[fullpath]
  85. if !found {
  86. return false
  87. }
  88. path, found := i.inode2path[inode]
  89. if found {
  90. return path.isChildrenCached
  91. }
  92. return false
  93. }
  94. func (i *InodeToPath) HasInode(inode uint64) bool {
  95. if inode == 1 {
  96. return true
  97. }
  98. i.RLock()
  99. defer i.RUnlock()
  100. _, found := i.inode2path[inode]
  101. return found
  102. }
  103. func (i *InodeToPath) RemovePath(path util.FullPath) {
  104. i.Lock()
  105. defer i.Unlock()
  106. inode, found := i.path2inode[path]
  107. if found {
  108. delete(i.path2inode, path)
  109. delete(i.inode2path, inode)
  110. }
  111. }
  112. func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) {
  113. i.Lock()
  114. defer i.Unlock()
  115. sourceInode, sourceFound := i.path2inode[sourcePath]
  116. targetInode, targetFound := i.path2inode[targetPath]
  117. if sourceFound {
  118. delete(i.path2inode, sourcePath)
  119. i.path2inode[targetPath] = sourceInode
  120. } else {
  121. // it is possible some source folder items has not been visited before
  122. // so no need to worry about their source inodes
  123. return
  124. }
  125. i.inode2path[sourceInode].FullPath = targetPath
  126. if targetFound {
  127. delete(i.inode2path, targetInode)
  128. } else {
  129. i.inode2path[sourceInode].nlookup++
  130. }
  131. }
  132. func (i *InodeToPath) Forget(inode, nlookup uint64, onForgetDir func(dir util.FullPath)) {
  133. i.Lock()
  134. path, found := i.inode2path[inode]
  135. if found {
  136. path.nlookup -= nlookup
  137. if path.nlookup <= 0 {
  138. delete(i.path2inode, path.FullPath)
  139. delete(i.inode2path, inode)
  140. }
  141. }
  142. i.Unlock()
  143. if found {
  144. if path.isDirectory && onForgetDir != nil {
  145. onForgetDir(path.FullPath)
  146. }
  147. }
  148. }