Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Nick Craig-Wood
1a66ed9315 vfs: make uploaded files retain modtime with non-modtime backends
Before this change if a file was uploaded to a backend which didn't
support modtimes, the time of the file read after the upload had
completed would change to the time the file was uploaded on the
backend.

When using `--vfs-cache-mode writes` or `full` this time would be
different by the `--vfs-write-back` delay which would cause
applications to think the file had been modified.

This changes uses the last modification time read in the cache as the
modtime for backends which don't support setting modtimes. It does not
change the modtime to that actually uploaded.

This means that as long as the file remains in the directory cache it
will have the expected modtime.

See: https://forum.rclone.org/t/saving-files-causes-wrong-modified-time-to-be-set-for-a-few-seconds-on-webdav-mount-with-bitrix24/36451
2023-03-08 12:10:50 +00:00
Nick Craig-Wood
f07abea072 vfs: cache: factor common code from InUse and DirtyItem into ItemOrNil 2023-03-08 11:51:13 +00:00
3 changed files with 20 additions and 10 deletions

View file

@ -322,7 +322,9 @@ func (f *File) ModTime() (modTime time.Time) {
}
// Read the modtime from a dirty item if it exists
if f.d.vfs.Opt.CacheMode >= vfscommon.CacheModeMinimal {
if item := f.d.vfs.cache.DirtyItem(f._path()); item != nil {
item := f.d.vfs.cache.ItemOrNil(f._path())
noModTime := f.d.f.Precision() == fs.ModTimeNotSupported
if item != nil && (item.IsDirty() || noModTime) {
modTime, err := item.GetModTime()
if err != nil {
fs.Errorf(f._path(), "ModTime: Item GetModTime failed: %v", err)

View file

@ -294,14 +294,22 @@ func (c *Cache) put(name string, item *Item) (oldItem *Item) {
return oldItem
}
// ItemOrNil returns the Item if it exists in the cache otherwise it
// returns nil.
//
// name should be a remote path not an osPath
func (c *Cache) ItemOrNil(name string) (item *Item) {
name = clean(name)
c.mu.Lock()
defer c.mu.Unlock()
return c.item[name]
}
// InUse returns whether the name is in use in the cache
//
// name should be a remote path not an osPath
func (c *Cache) InUse(name string) bool {
name = clean(name)
c.mu.Lock()
item := c.item[name]
c.mu.Unlock()
item := c.ItemOrNil(name)
if item == nil {
return false
}
@ -313,10 +321,7 @@ func (c *Cache) InUse(name string) bool {
//
// name should be a remote path not an osPath
func (c *Cache) DirtyItem(name string) (item *Item) {
name = clean(name)
c.mu.Lock()
defer c.mu.Unlock()
item = c.item[name]
item = c.ItemOrNil(name)
if item != nil && !item.IsDirty() {
item = nil
}

View file

@ -1223,7 +1223,7 @@ func (item *Item) setModTime(modTime time.Time) {
item.mu.Unlock()
}
// GetModTime of the cache file
// GetModTime of the cache item
func (item *Item) GetModTime() (modTime time.Time, err error) {
// defer log.Trace(item.name, "modTime=%v", modTime)("")
item.mu.Lock()
@ -1231,6 +1231,9 @@ func (item *Item) GetModTime() (modTime time.Time, err error) {
fi, err := item._stat()
if err == nil {
modTime = fi.ModTime()
item.info.ModTime = modTime
} else {
modTime = item.info.ModTime
}
return modTime, nil
}