diff options
author | Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com> | 2024-02-09 10:31:11 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-09 10:31:11 +0100 |
commit | 92df765457ea4fc0f2af58dee196f60a465ad297 (patch) | |
tree | 4251c436b5d370471904b1398bd26d55197bd5b2 /lib/private | |
parent | ef786616ec61565c7a9f61dfcee031b2f84218a6 (diff) | |
parent | 7c8d71d0a04e07a56262ef4d7994b6371e1bb41f (diff) | |
download | nextcloud-server-92df765457ea4fc0f2af58dee196f60a465ad297.tar.gz nextcloud-server-92df765457ea4fc0f2af58dee196f60a465ad297.zip |
Merge pull request #43246 from nextcloud/backport/41327/stable27
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Files/Cache/Scanner.php | 38 | ||||
-rw-r--r-- | lib/private/Files/ObjectStore/ObjectStoreScanner.php | 2 |
2 files changed, 32 insertions, 8 deletions
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 9f99bbaab2b..fd1aba9f99b 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -203,7 +203,9 @@ class Scanner extends BasicEmitter implements IScanner { $fileId = $cacheData['fileid']; $data['fileid'] = $fileId; // only reuse data if the file hasn't explicitly changed - if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) { + $mtimeUnchanged = isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']; + // if the folder is marked as unscanned, never reuse etags + if ($mtimeUnchanged && $cacheData['size'] !== -1) { $data['mtime'] = $cacheData['mtime']; if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) { $data['size'] = $cacheData['size']; @@ -220,6 +222,11 @@ class Scanner extends BasicEmitter implements IScanner { // Only update metadata that has changed $newData = array_diff_assoc($data, $cacheData->getData()); + + // make it known to the caller that etag has been changed and needs propagation + if (isset($newData['etag'])) { + $data['etag_changed'] = true; + } } else { // we only updated unencrypted_size if it's already set unset($data['unencrypted_size']); @@ -388,16 +395,20 @@ class Scanner extends BasicEmitter implements IScanner { * @param int|float $oldSize the size of the folder before (re)scanning the children * @return int|float the size of the scanned folder or -1 if the size is unknown at this stage */ - protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize) { + protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize, &$etagChanged = false) { if ($reuse === -1) { $reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG; } $this->emit('\OC\Files\Cache\Scanner', 'scanFolder', [$path, $this->storageId]); $size = 0; - $childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size); + $childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size, $etagChanged); foreach ($childQueue as $child => [$childId, $childSize]) { - $childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock, $childSize); + // "etag changed" propagates up, but not down, so we pass `false` to the children even if we already know that the etag of the current folder changed + $childEtagChanged = false; + $childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock, $childSize, $childEtagChanged); + $etagChanged |= $childEtagChanged; + if ($childSize === -1) { $size = -1; } elseif ($size !== -1) { @@ -410,8 +421,17 @@ class Scanner extends BasicEmitter implements IScanner { if ($this->storage->instanceOfStorage(Encryption::class)) { $this->cache->calculateFolderSize($path); } else { - if ($this->cacheActive && $oldSize !== $size) { - $this->cache->update($folderId, ['size' => $size]); + if ($this->cacheActive) { + $updatedData = []; + if ($oldSize !== $size) { + $updatedData['size'] = $size; + } + if ($etagChanged) { + $updatedData['etag'] = uniqid(); + } + if ($updatedData) { + $this->cache->update($folderId, $updatedData); + } } } $this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', [$path, $this->storageId]); @@ -421,7 +441,7 @@ class Scanner extends BasicEmitter implements IScanner { /** * @param bool|IScanner::SCAN_RECURSIVE_INCOMPLETE $recursive */ - private function handleChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float &$size): array { + private function handleChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float &$size, bool &$etagChanged): array { // we put this in it's own function so it cleans up the memory before we start recursing $existingChildren = $this->getExistingChildren($folderId); $newChildren = iterator_to_array($this->storage->getDirectoryContent($path)); @@ -469,6 +489,10 @@ class Scanner extends BasicEmitter implements IScanner { } elseif ($size !== -1) { $size += $data['size']; } + + if (isset($data['etag_changed']) && $data['etag_changed']) { + $etagChanged = true; + } } } catch (Exception $ex) { // might happen if inserting duplicate while a scanning diff --git a/lib/private/Files/ObjectStore/ObjectStoreScanner.php b/lib/private/Files/ObjectStore/ObjectStoreScanner.php index d827662ae0b..8a9b844c47f 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreScanner.php +++ b/lib/private/Files/ObjectStore/ObjectStoreScanner.php @@ -39,7 +39,7 @@ class ObjectStoreScanner extends Scanner { return []; } - protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize) { + protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize, &$etagChanged = false) { return 0; } |