mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 17:57:44 +08:00
vfs: stop change notify polling clearing so much of the directory cache
Before this change, change notify polls would clear the directory cache recursively. So uploading a file to the root would clear the entire directory cache. After this change we just invalidate the directory cache of the parent directory of the item and if the item was a directory we invalidate it too.
This commit is contained in:
parent
2bbfcc74e9
commit
76f5e273d2
45
vfs/dir.go
45
vfs/dir.go
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/rclone/rclone/fs"
|
||||
"github.com/rclone/rclone/fs/dirtree"
|
||||
"github.com/rclone/rclone/fs/list"
|
||||
"github.com/rclone/rclone/fs/log"
|
||||
"github.com/rclone/rclone/fs/operations"
|
||||
"github.com/rclone/rclone/fs/walk"
|
||||
)
|
||||
|
@ -119,20 +120,10 @@ func (d *Dir) ForgetAll() {
|
|||
d.forgetDirPath("")
|
||||
}
|
||||
|
||||
// ForgetPath clears the cache for itself and all subdirectories if
|
||||
// they match the given path. The path is specified relative from the
|
||||
// directory it is called from. The cache of the parent directory is
|
||||
// marked as stale, but not cleared otherwise.
|
||||
// It is not possible to traverse the directory tree upwards, i.e.
|
||||
// you cannot clear the cache for the Dir's ancestors or siblings.
|
||||
func (d *Dir) ForgetPath(relativePath string, entryType fs.EntryType) {
|
||||
if absPath := path.Join(d.path, relativePath); absPath != "" {
|
||||
parent := path.Dir(absPath)
|
||||
if parent == "." || parent == "/" {
|
||||
parent = ""
|
||||
}
|
||||
parentNode := d.vfs.root.cachedNode(parent)
|
||||
if dir, ok := parentNode.(*Dir); ok {
|
||||
// invalidateDir invalidates the directory cache for absPath relative to this dir
|
||||
func (d *Dir) invalidateDir(absPath string) {
|
||||
node := d.vfs.root.cachedNode(absPath)
|
||||
if dir, ok := node.(*Dir); ok {
|
||||
dir.mu.Lock()
|
||||
if !dir.read.IsZero() {
|
||||
fs.Debugf(dir.path, "invalidating directory cache")
|
||||
|
@ -140,8 +131,32 @@ func (d *Dir) ForgetPath(relativePath string, entryType fs.EntryType) {
|
|||
}
|
||||
dir.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// changeNotify invalidates the directory cache for the relativePath
|
||||
// passed in.
|
||||
//
|
||||
// if entryType is a directory it invalidates the parent of the directory too.
|
||||
func (d *Dir) changeNotify(relativePath string, entryType fs.EntryType) {
|
||||
defer log.Trace(d.path, "relativePath=%q, type=%v", relativePath, entryType)("")
|
||||
absPath := path.Join(d.path, relativePath)
|
||||
d.invalidateDir(findParent(absPath))
|
||||
if entryType == fs.EntryDirectory {
|
||||
d.invalidateDir(absPath)
|
||||
}
|
||||
}
|
||||
|
||||
// ForgetPath clears the cache for itself and all subdirectories if
|
||||
// they match the given path. The path is specified relative from the
|
||||
// directory it is called from. The cache of the parent directory is
|
||||
// marked as stale, but not cleared otherwise.
|
||||
// It is not possible to traverse the directory tree upwards, i.e.
|
||||
// you cannot clear the cache for the Dir's ancestors or siblings.
|
||||
func (d *Dir) ForgetPath(relativePath string, entryType fs.EntryType) {
|
||||
defer log.Trace(d.path, "relativePath=%q, type=%v", relativePath, entryType)("")
|
||||
if absPath := path.Join(d.path, relativePath); absPath != "" {
|
||||
d.invalidateDir(findParent(absPath))
|
||||
}
|
||||
if entryType == fs.EntryDirectory {
|
||||
d.forgetDirPath(relativePath)
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ func New(f fs.Fs, opt *Options) *VFS {
|
|||
// Start polling function
|
||||
if do := vfs.f.Features().ChangeNotify; do != nil {
|
||||
vfs.pollChan = make(chan time.Duration)
|
||||
do(context.TODO(), vfs.root.ForgetPath, vfs.pollChan)
|
||||
do(context.TODO(), vfs.root.changeNotify, vfs.pollChan)
|
||||
vfs.pollChan <- vfs.Opt.PollInterval
|
||||
} else {
|
||||
fs.Infof(f, "poll-interval is not supported by this remote")
|
||||
|
|
Loading…
Reference in New Issue
Block a user