vfs: stop setting a file's modtime from discarding its cached data
Setting the modtime of a closed file refreshed the cache item's fingerprint before the new modtime had been applied to the remote object. The next open then saw a fingerprint mismatch, logged "removed cache file as stale (remote is different)" and downloaded the whole file again, even though only the modtime had changed. Refresh the cache fingerprint again once the remote modtime has been set.
This commit is contained in:
1 parent
e0fb01084d
commit
9380daed0d
2 files changed
+22
No files matched your search
@@ -495,6 +495,11 @@ func (f *File) _applyPendingModTime() error {
|
||||
switch err {
|
||||
case nil:
|
||||
fs.Debugf(f.o, "Applied pending mod time %v OK", f.pendingModTime)
|
||||
// The cache fingerprint predates the new modtime, so refresh
|
||||
// it or the next open discards the cached data as stale.
|
||||
if f.d.vfs.cache != nil && f.d.vfs.cache.Exists(f._cachePath()) {
|
||||
f.d.vfs.cache.SetModTime(f._cachePath(), f.pendingModTime)
|
||||
}
|
||||
case fs.ErrorCantSetModTime, fs.ErrorCantSetModTimeWithoutDelete:
|
||||
// do nothing, in order to not break "touch somefile" if it exists already
|
||||
default:
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/rclone/rclone/fstest"
|
||||
"github.com/rclone/rclone/fstest/mockfs"
|
||||
"github.com/rclone/rclone/fstest/mockobject"
|
||||
"github.com/rclone/rclone/lib/ranges"
|
||||
"github.com/rclone/rclone/vfs/vfscommon"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -163,6 +164,22 @@ func TestFileSetModTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Touching a closed, fully cached file must keep its cached data: the
|
||||
// remote modtime change it makes is not a change to the content.
|
||||
func TestFileSetModTimeKeepsCache(t *testing.T) {
|
||||
_, vfs, file, _ := fileCreate(t, vfscommon.CacheModeFull)
|
||||
fileCheckContents(t, file)
|
||||
whole := ranges.Range{Pos: 0, Size: int64(len("file1 contents"))}
|
||||
item := vfs.cache.Item(file.Path())
|
||||
require.True(t, item.HasRange(whole))
|
||||
|
||||
require.NoError(t, file.SetModTime(t2))
|
||||
|
||||
require.NoError(t, item.Open(file.getObject()))
|
||||
defer func() { require.NoError(t, item.Close(nil)) }()
|
||||
assert.True(t, item.HasRange(whole), "touch discarded the cached data")
|
||||
}
|
||||
|
||||
func fileCheckContents(t *testing.T, file *File) {
|
||||
fd, err := file.Open(os.O_RDONLY)
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in new issue
Block a user