aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/private/Files/Cache/Scanner.php35
-rw-r--r--lib/private/Files/ObjectStore/NoopScanner.php7
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;
}