|
@@ -1,207 +0,0 @@
|
|
|
-package filesys
|
|
|
-
|
|
|
-import (
|
|
|
- "sync"
|
|
|
-
|
|
|
- "github.com/chrislusf/seaweedfs/weed/util"
|
|
|
- "github.com/seaweedfs/fuse/fs"
|
|
|
-)
|
|
|
-
|
|
|
-type FsCache struct {
|
|
|
- root *FsNode
|
|
|
- sync.RWMutex
|
|
|
-}
|
|
|
-type FsNode struct {
|
|
|
- parent *FsNode
|
|
|
- node fs.Node
|
|
|
- name string
|
|
|
- childrenLock sync.RWMutex
|
|
|
- children map[string]*FsNode
|
|
|
-}
|
|
|
-
|
|
|
-func newFsCache(root fs.Node) *FsCache {
|
|
|
- return &FsCache{
|
|
|
- root: &FsNode{
|
|
|
- node: root,
|
|
|
- },
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (c *FsCache) GetFsNode(path util.FullPath) fs.Node {
|
|
|
-
|
|
|
- c.RLock()
|
|
|
- defer c.RUnlock()
|
|
|
-
|
|
|
- return c.doGetFsNode(path)
|
|
|
-}
|
|
|
-
|
|
|
-func (c *FsCache) doGetFsNode(path util.FullPath) fs.Node {
|
|
|
- t := c.root
|
|
|
- for _, p := range path.Split() {
|
|
|
- t = t.findChild(p)
|
|
|
- if t == nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
- }
|
|
|
- return t.node
|
|
|
-}
|
|
|
-
|
|
|
-func (c *FsCache) SetFsNode(path util.FullPath, node fs.Node) {
|
|
|
-
|
|
|
- c.Lock()
|
|
|
- defer c.Unlock()
|
|
|
-
|
|
|
- c.doSetFsNode(path, node)
|
|
|
-}
|
|
|
-
|
|
|
-func (c *FsCache) doSetFsNode(path util.FullPath, node fs.Node) {
|
|
|
- t := c.root
|
|
|
- for _, p := range path.Split() {
|
|
|
- t = t.ensureChild(p)
|
|
|
- }
|
|
|
- t.node = node
|
|
|
-}
|
|
|
-
|
|
|
-func (c *FsCache) EnsureFsNode(path util.FullPath, genNodeFn func() fs.Node) fs.Node {
|
|
|
-
|
|
|
- c.Lock()
|
|
|
- defer c.Unlock()
|
|
|
-
|
|
|
- t := c.doGetFsNode(path)
|
|
|
- if t != nil {
|
|
|
- return t
|
|
|
- }
|
|
|
- t = genNodeFn()
|
|
|
- c.doSetFsNode(path, t)
|
|
|
- return t
|
|
|
-}
|
|
|
-
|
|
|
-func (c *FsCache) DeleteFsNode(path util.FullPath) {
|
|
|
-
|
|
|
- c.Lock()
|
|
|
- defer c.Unlock()
|
|
|
-
|
|
|
- t := c.root
|
|
|
- for _, p := range path.Split() {
|
|
|
- t = t.findChild(p)
|
|
|
- if t == nil {
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
- if t.parent != nil {
|
|
|
- t.parent.disconnectChild(t)
|
|
|
- }
|
|
|
- t.deleteSelf()
|
|
|
-}
|
|
|
-
|
|
|
-// oldPath and newPath are full path including the new name
|
|
|
-func (c *FsCache) Move(oldPath util.FullPath, newPath util.FullPath) *FsNode {
|
|
|
-
|
|
|
- c.Lock()
|
|
|
- defer c.Unlock()
|
|
|
-
|
|
|
- // find old node
|
|
|
- src := c.root
|
|
|
- for _, p := range oldPath.Split() {
|
|
|
- src = src.findChild(p)
|
|
|
- if src == nil {
|
|
|
- return src
|
|
|
- }
|
|
|
- }
|
|
|
- if src.parent != nil {
|
|
|
- src.parent.disconnectChild(src)
|
|
|
- }
|
|
|
-
|
|
|
- // find new node
|
|
|
- target := c.root
|
|
|
- for _, p := range newPath.Split() {
|
|
|
- target = target.ensureChild(p)
|
|
|
- }
|
|
|
- parent := target.parent
|
|
|
- src.name = target.name
|
|
|
- if dir, ok := src.node.(*Dir); ok {
|
|
|
- dir.name = target.name // target is not Dir, but a shortcut
|
|
|
- }
|
|
|
- if f, ok := src.node.(*File); ok {
|
|
|
- f.Name = target.name
|
|
|
- if f.entry != nil {
|
|
|
- f.entry.Name = f.Name
|
|
|
- }
|
|
|
- }
|
|
|
- parent.disconnectChild(target)
|
|
|
-
|
|
|
- target.deleteSelf()
|
|
|
-
|
|
|
- src.connectToParent(parent)
|
|
|
-
|
|
|
- return src
|
|
|
-}
|
|
|
-
|
|
|
-func (n *FsNode) connectToParent(parent *FsNode) {
|
|
|
- n.parent = parent
|
|
|
- oldNode := parent.findChild(n.name)
|
|
|
- if oldNode != nil {
|
|
|
- oldNode.deleteSelf()
|
|
|
- }
|
|
|
- if dir, ok := n.node.(*Dir); ok {
|
|
|
- dir.parent = parent.node.(*Dir)
|
|
|
- }
|
|
|
- if f, ok := n.node.(*File); ok {
|
|
|
- f.dir = parent.node.(*Dir)
|
|
|
- }
|
|
|
- n.childrenLock.Lock()
|
|
|
- parent.children[n.name] = n
|
|
|
- n.childrenLock.Unlock()
|
|
|
-}
|
|
|
-
|
|
|
-func (n *FsNode) findChild(name string) *FsNode {
|
|
|
- n.childrenLock.RLock()
|
|
|
- defer n.childrenLock.RUnlock()
|
|
|
-
|
|
|
- child, found := n.children[name]
|
|
|
- if found {
|
|
|
- return child
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func (n *FsNode) ensureChild(name string) *FsNode {
|
|
|
- n.childrenLock.Lock()
|
|
|
- defer n.childrenLock.Unlock()
|
|
|
-
|
|
|
- if n.children == nil {
|
|
|
- n.children = make(map[string]*FsNode)
|
|
|
- }
|
|
|
- child, found := n.children[name]
|
|
|
- if found {
|
|
|
- return child
|
|
|
- }
|
|
|
- t := &FsNode{
|
|
|
- parent: n,
|
|
|
- node: nil,
|
|
|
- name: name,
|
|
|
- children: nil,
|
|
|
- }
|
|
|
- n.children[name] = t
|
|
|
- return t
|
|
|
-}
|
|
|
-
|
|
|
-func (n *FsNode) disconnectChild(child *FsNode) {
|
|
|
- n.childrenLock.Lock()
|
|
|
- delete(n.children, child.name)
|
|
|
- n.childrenLock.Unlock()
|
|
|
- child.parent = nil
|
|
|
-}
|
|
|
-
|
|
|
-func (n *FsNode) deleteSelf() {
|
|
|
- n.childrenLock.Lock()
|
|
|
- for _, child := range n.children {
|
|
|
- child.deleteSelf()
|
|
|
- }
|
|
|
- n.children = nil
|
|
|
- n.childrenLock.Unlock()
|
|
|
-
|
|
|
- n.node = nil
|
|
|
- n.parent = nil
|
|
|
-
|
|
|
-}
|