diff options
-rw-r--r-- | lib/private/Files/Cache/Scanner.php | 35 | ||||
-rw-r--r-- | lib/private/Files/ObjectStore/NoopScanner.php | 7 |
2 files changed, 34 insertions, 8 deletions
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index eb5361238d4..98619887f80 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -200,6 +200,7 @@ class Scanner extends BasicEmitter implements IScanner { $data['fileid'] = $fileId; // only reuse data if the file hasn't explicitly changed $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)) { @@ -217,6 +218,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']); @@ -380,7 +386,7 @@ class Scanner extends BasicEmitter implements IScanner { * @param array $data the data 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($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = []) { + protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = [], &$etagChanged = false) { if ($reuse === -1) { $reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG; } @@ -389,10 +395,14 @@ class Scanner extends BasicEmitter implements IScanner { if (!is_null($folderId)) { $folderId = $this->cache->getId($path); } - $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 = $this->scanChildren($child, $recursive, $reuse, $childId, $lock); + // "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, [], $childEtagChanged); + $etagChanged |= $childEtagChanged; + if ($childSize === -1) { $size = -1; } elseif ($size !== -1) { @@ -406,15 +416,24 @@ 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]); return $size; } - private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$size) { + private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$size, bool &$etagChanged) { // 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)); @@ -462,6 +481,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/NoopScanner.php b/lib/private/Files/ObjectStore/NoopScanner.php index bdfc93758d4..e1c1b0ea433 100644 --- a/lib/private/Files/ObjectStore/NoopScanner.php +++ b/lib/private/Files/ObjectStore/NoopScanner.php @@ -65,10 +65,13 @@ class NoopScanner extends Scanner { * @param string $path * @param bool $recursive * @param int $reuse - * @param array $folderData existing cache data for the folder to be scanned + * @param ?int $folderId + * @param bool $lock + * @param array $data + * @param bool &$etagChanged * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ - protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = []) { + protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = [], &$etagChanged = false) { return 0; } |