mirror of
https://github.com/rclone/rclone.git
synced 2025-06-30 22:23:52 +02:00
vfs: stop virtual directory entries dropping out of the directory cache
Rclone adds virtual directory entries to the directory cache when it creates a file or directory. Before this change these dropped out of the directory cache when the directory cache was reloaded. This meant that when the directory cache expired: - On bucket based backends, empty directories would disappear - When using VFS writeback, files in the process of uploading would disappear This is fixed by keeping track of the virtual entries in each directory. The virtual entries are removed when they become real - ie the object is read back from the listing. This also keeps tracks of deletes in the same way so if a file is deleted, it will not re-appear when the directory cache is reloaded if the deletion hasn't finished yet.
This commit is contained in:
@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/rclone/rclone/fs"
|
||||
"github.com/rclone/rclone/fs/operations"
|
||||
"github.com/rclone/rclone/fstest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -277,6 +278,45 @@ func TestDirReadDirAll(t *testing.T) {
|
||||
dir = node.(*Dir)
|
||||
|
||||
checkListing(t, dir, []string{"file3,16,false"})
|
||||
|
||||
t.Run("Virtual", func(t *testing.T) {
|
||||
node, err := vfs.Stat("dir")
|
||||
require.NoError(t, err)
|
||||
dir := node.(*Dir)
|
||||
|
||||
// Add some virtual entries and check what happens
|
||||
dir.AddVirtual("virtualFile", 17, false)
|
||||
dir.AddVirtual("virtualDir", 0, true)
|
||||
// Remove some existing entries
|
||||
dir.DelVirtual("file2")
|
||||
dir.DelVirtual("subdir")
|
||||
|
||||
checkListing(t, dir, []string{"file1,14,false", "virtualDir,0,true", "virtualFile,17,false"})
|
||||
|
||||
// Force a directory reload...
|
||||
dir.invalidateDir("dir")
|
||||
|
||||
checkListing(t, dir, []string{"file1,14,false", "virtualDir,0,true", "virtualFile,17,false"})
|
||||
|
||||
// Now action the deletes and uploads
|
||||
_ = r.WriteObject(context.Background(), "dir/virtualFile", "virtualFile contents", t1)
|
||||
_ = r.WriteObject(context.Background(), "dir/virtualDir/testFile", "testFile contents", t1)
|
||||
o, err := r.Fremote.NewObject(context.Background(), "dir/file2")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, o.Remove(context.Background()))
|
||||
require.NoError(t, operations.Purge(context.Background(), r.Fremote, "dir/subdir"))
|
||||
|
||||
// Force a directory reload...
|
||||
dir.invalidateDir("dir")
|
||||
|
||||
checkListing(t, dir, []string{"file1,14,false", "virtualDir,0,true", "virtualFile,20,false"})
|
||||
|
||||
// check no virtuals left
|
||||
dir.mu.Lock()
|
||||
assert.Nil(t, dir.virtual)
|
||||
dir.mu.Unlock()
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestDirOpen(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user