Add rclone mount --dir-cache-time to control caching of directory entries - fixes #680

This commit is contained in:
Nick Craig-Wood 2016-10-18 14:44:16 +01:00
parent 368cce93ff
commit a02edb9e69
2 changed files with 31 additions and 7 deletions

View File

@ -30,7 +30,7 @@ type Dir struct {
f fs.Fs
path string
mu sync.RWMutex // protects the following
read bool
read time.Time // time directory entry last read
items map[string]*DirEntry
}
@ -66,8 +66,15 @@ func (d *Dir) delObject(leaf string) {
func (d *Dir) readDir() error {
d.mu.Lock()
defer d.mu.Unlock()
if d.read {
return nil
when := time.Now()
if d.read.IsZero() {
fs.Debug(d.path, "Reading directory")
} else {
age := when.Sub(d.read)
if age < dirCacheTime {
return nil
}
fs.Debug(d.path, "Re-reading directory (%v old)", age)
}
objs, dirs, err := fs.NewLister().SetLevel(1).Start(d.f, d.path).GetAll()
if err == fs.ErrorDirNotFound {
@ -76,6 +83,13 @@ func (d *Dir) readDir() error {
} else if err != nil {
return err
}
// NB when we re-read a directory after its cache has expired
// we drop the old files which should lead to correct
// behaviour but may not be very efficient.
// Keep a note of the previous contents of the directory
oldItems := d.items
// Cache the items by name
d.items = make(map[string]*DirEntry, len(objs)+len(dirs))
for _, obj := range objs {
@ -87,12 +101,19 @@ func (d *Dir) readDir() error {
}
for _, dir := range dirs {
name := path.Base(dir.Remote())
// Use old dir value if it exists
if oldItem, ok := oldItems[name]; ok {
if _, ok := oldItem.o.(*fs.Dir); ok {
d.items[name] = oldItem
continue
}
}
d.items[name] = &DirEntry{
o: dir,
node: nil,
}
}
d.read = true
d.read = when
return nil
}

View File

@ -7,6 +7,7 @@ package mount
import (
"log"
"os"
"time"
"bazil.org/fuse"
"github.com/ncw/rclone/cmd"
@ -18,9 +19,10 @@ import (
// Globals
var (
noModTime = false
debugFUSE = false
noSeek = false
noModTime = false
debugFUSE = false
noSeek = false
dirCacheTime = 5 * 60 * time.Second
// mount options
readOnly = false
allowNonEmpty = false
@ -45,6 +47,7 @@ func init() {
mountCmd.Flags().BoolVarP(&noModTime, "no-modtime", "", noModTime, "Don't read the modification time (can speed things up).")
mountCmd.Flags().BoolVarP(&debugFUSE, "debug-fuse", "", debugFUSE, "Debug the FUSE internals - needs -v.")
mountCmd.Flags().BoolVarP(&noSeek, "no-seek", "", noSeek, "Don't allow seeking in files.")
mountCmd.Flags().DurationVarP(&dirCacheTime, "dir-cache-time", "", dirCacheTime, "Time to cache directory entries for.")
// mount options
mountCmd.Flags().BoolVarP(&readOnly, "read-only", "", readOnly, "Mount read-only.")
mountCmd.Flags().BoolVarP(&allowNonEmpty, "allow-non-empty", "", allowNonEmpty, "Allow mounting over a non-empty directory.")