seaweedfs/weed/filesys/fscache.go

180 lines
3.2 KiB
Go
Raw Normal View History

2020-03-26 05:19:19 +00:00
package filesys
import (
"sync"
2020-03-26 05:19:19 +00:00
"github.com/chrislusf/seaweedfs/weed/util"
"github.com/seaweedfs/fuse/fs"
)
type FsCache struct {
root *FsNode
}
type FsNode struct {
parent *FsNode
node fs.Node
name string
childrenLock sync.RWMutex
children map[string]*FsNode
2020-03-26 05:19:19 +00:00
}
func newFsCache(root fs.Node) *FsCache {
return &FsCache{
root: &FsNode{
node: root,
},
}
}
func (c *FsCache) GetFsNode(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) {
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 {
t := c.GetFsNode(path)
if t != nil {
return t
}
t = genNodeFn()
c.SetFsNode(path, t)
return t
}
func (c *FsCache) DeleteFsNode(path util.FullPath) {
t := c.root
for _, p := range path.Split() {
t = t.findChild(p)
if t == nil {
return
}
}
if t.parent != nil {
2020-03-26 10:30:02 +00:00
t.parent.disconnectChild(t)
2020-03-26 05:19:19 +00:00
}
t.deleteSelf()
}
// oldPath and newPath are full path including the new name
func (c *FsCache) Move(oldPath util.FullPath, newPath util.FullPath) *FsNode {
// find old node
src := c.root
for _, p := range oldPath.Split() {
src = src.findChild(p)
if src == nil {
return src
}
}
if src.parent != nil {
2020-03-26 10:30:02 +00:00
src.parent.disconnectChild(src)
2020-03-26 05:19:19 +00:00
}
// 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
}
2020-03-26 10:30:23 +00:00
if f, ok := src.node.(*File); ok {
2020-03-26 17:56:18 +00:00
f.Name = target.name
2020-03-26 10:30:23 +00:00
if f.entry != nil {
f.entry.Name = f.Name
}
}
2020-03-26 10:30:02 +00:00
parent.disconnectChild(target)
2020-03-26 05:19:19 +00:00
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)
}
2020-03-27 07:30:55 +00:00
if f, ok := n.node.(*File); ok {
f.dir = parent.node.(*Dir)
}
n.childrenLock.Lock()
2020-03-26 05:19:19 +00:00
parent.children[n.name] = n
n.childrenLock.Unlock()
2020-03-26 05:19:19 +00:00
}
func (n *FsNode) findChild(name string) *FsNode {
n.childrenLock.RLock()
defer n.childrenLock.RUnlock()
2020-03-26 05:19:19 +00:00
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()
2020-03-26 05:19:19 +00:00
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
}
2020-03-26 10:30:02 +00:00
func (n *FsNode) disconnectChild(child *FsNode) {
n.childrenLock.Lock()
2020-03-26 10:30:02 +00:00
delete(n.children, child.name)
n.childrenLock.Unlock()
2020-03-26 10:30:02 +00:00
child.parent = nil
2020-03-26 05:19:19 +00:00
}
func (n *FsNode) deleteSelf() {
n.childrenLock.Lock()
2020-03-26 05:19:19 +00:00
for _, child := range n.children {
child.deleteSelf()
}
n.children = nil
n.childrenLock.Unlock()
2020-03-26 05:19:19 +00:00
n.node = nil
n.parent = nil
2020-03-26 05:19:19 +00:00
}