Skip to content

Commit d39107c

Browse files
committed
also updated parent etags when a changed etag is detected during scanning
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent 439958e commit d39107c

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

lib/private/Files/Cache/Scanner.php

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
200200
$data['fileid'] = $fileId;
201201
// only reuse data if the file hasn't explicitly changed
202202
$mtimeUnchanged = isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime'];
203+
// if the folder is marked as unscanned, never reuse etags
203204
if ($mtimeUnchanged && $cacheData['size'] !== -1) {
204205
$data['mtime'] = $cacheData['mtime'];
205206
if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
@@ -217,6 +218,11 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
217218

218219
// Only update metadata that has changed
219220
$newData = array_diff_assoc($data, $cacheData->getData());
221+
222+
// make it known to the caller that etag has been changed and needs propagation
223+
if (isset($newData['etag'])) {
224+
$data['etag_changed'] = true;
225+
}
220226
} else {
221227
// we only updated unencrypted_size if it's already set
222228
unset($data['unencrypted_size']);
@@ -380,7 +386,7 @@ protected function getExistingChildren($folderId) {
380386
* @param array $data the data of the folder before (re)scanning the children
381387
* @return int|float the size of the scanned folder or -1 if the size is unknown at this stage
382388
*/
383-
protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = []) {
389+
protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true, array $data = [], &$etagChanged = false) {
384390
if ($reuse === -1) {
385391
$reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG;
386392
}
@@ -389,10 +395,14 @@ protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse
389395
if (!is_null($folderId)) {
390396
$folderId = $this->cache->getId($path);
391397
}
392-
$childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size);
398+
$childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size, $etagChanged);
393399

394400
foreach ($childQueue as $child => $childId) {
395-
$childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock);
401+
// "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
402+
$childEtagChanged = false;
403+
$childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock, [], $childEtagChanged);
404+
$etagChanged |= $childEtagChanged;
405+
396406
if ($childSize === -1) {
397407
$size = -1;
398408
} elseif ($size !== -1) {
@@ -406,15 +416,24 @@ protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse
406416
if ($this->storage->instanceOfStorage(Encryption::class)) {
407417
$this->cache->calculateFolderSize($path);
408418
} else {
409-
if ($this->cacheActive && $oldSize !== $size) {
410-
$this->cache->update($folderId, ['size' => $size]);
419+
if ($this->cacheActive) {
420+
$updatedData = [];
421+
if ($oldSize !== $size) {
422+
$updatedData['size'] = $size;
423+
}
424+
if ($etagChanged) {
425+
$updatedData['etag'] = uniqid();
426+
}
427+
if ($updatedData) {
428+
$this->cache->update($folderId, $updatedData);
429+
}
411430
}
412431
}
413432
$this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', [$path, $this->storageId]);
414433
return $size;
415434
}
416435

417-
private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$size) {
436+
private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$size, bool &$etagChanged) {
418437
// we put this in it's own function so it cleans up the memory before we start recursing
419438
$existingChildren = $this->getExistingChildren($folderId);
420439
$newChildren = iterator_to_array($this->storage->getDirectoryContent($path));
@@ -462,6 +481,10 @@ private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$s
462481
} elseif ($size !== -1) {
463482
$size += $data['size'];
464483
}
484+
485+
if (isset($data['etag_changed']) && $data['etag_changed']) {
486+
$etagChanged = true;
487+
}
465488
}
466489
} catch (Exception $ex) {
467490
// might happen if inserting duplicate while a scanning

0 commit comments

Comments
 (0)