forked from TrueCloudLab/rclone
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:
parent
143abe39f2
commit
06a12f5e27
3 changed files with 176 additions and 8 deletions
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue