123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- 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
- }
|