diff --git a/vfs/read_write.go b/vfs/read_write.go index 56b9c467d..7f278f56b 100644 --- a/vfs/read_write.go +++ b/vfs/read_write.go @@ -113,6 +113,17 @@ func (fh *RWFileHandle) openPending() (err error) { } fh.opened = true fh.d.addObject(fh.file) // make sure the directory has this object in it now + + // If we are downloading the file first, then do that here + if fh.d.vfs.Opt.DownloadFirst { + fs.Errorf(fh.logPrefix(), "downloading %v file completely to cache", fs.SizeSuffix(size)) + err = fh.item.Ensure() + if err != nil { + fs.Errorf(fh.logPrefix(), "failed to download file to cache: %v", err) + return fmt.Errorf("failed to download file to cache: %w", err) + } + fs.Errorf(fh.logPrefix(), "downloaded %v file completely to cache", fs.SizeSuffix(size)) + } return nil } diff --git a/vfs/vfscache/item.go b/vfs/vfscache/item.go index 66adc9b66..6f03f4afd 100644 --- a/vfs/vfscache/item.go +++ b/vfs/vfscache/item.go @@ -642,6 +642,16 @@ func (item *Item) store(ctx context.Context, storeFn StoreFn) (err error) { return item._store(ctx, storeFn) } +// Ensure item is entirely on disk +func (item *Item) Ensure() (err error) { + item.mu.Lock() + defer item.mu.Unlock() + if item.o == nil { + return nil + } + return item._ensure(0, item.info.Size) +} + // Close the cache file func (item *Item) Close(storeFn StoreFn) (err error) { // defer log.Trace(item.o, "Item.Close")("err=%v", &err) diff --git a/vfs/vfscommon/options.go b/vfs/vfscommon/options.go index 650aedd97..557d2493b 100644 --- a/vfs/vfscommon/options.go +++ b/vfs/vfscommon/options.go @@ -145,6 +145,11 @@ var OptionsInfo = fs.Options{{ Default: false, Help: "Use fast (less accurate) fingerprints for change detection", Groups: "VFS", +}, { + Name: "vfs_download_first", + Default: false, + Help: "If set and --vfs-cache-mode full then download files completely on first access.", + Groups: "VFS", }, { Name: "vfs_disk_space_total_size", Default: fs.SizeSuffix(-1), @@ -203,6 +208,7 @@ type Options struct { ReadAhead fs.SizeSuffix `config:"vfs_read_ahead"` // bytes to read ahead in cache mode "full" UsedIsSize bool `config:"vfs_used_is_size"` // if true, use the `rclone size` algorithm for Used size FastFingerprint bool `config:"vfs_fast_fingerprint"` // if set use fast fingerprints + DownloadFirst bool `config:"vfs_download_first"` // if set download files to VFS cache first DiskSpaceTotalSize fs.SizeSuffix `config:"vfs_disk_space_total_size"` }