Merge pull request #14425 from cowai/fix-multiple-incomplete-folders

Do not calculate folder size for parent that also needs proper scan, fixes #3524
This commit is contained in:
Morris Jobke 2019-03-08 09:12:33 +01:00 committed by GitHub
commit 772303309d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 8 deletions

View file

@ -3,6 +3,7 @@
* @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2016, ownCloud, Inc.
* *
* @author Andreas Fischer <bantu@owncloud.com> * @author Andreas Fischer <bantu@owncloud.com>
* @author Ari Selseng <ari@selseng.net>
* @author Artem Kochnev <MrJeos@gmail.com> * @author Artem Kochnev <MrJeos@gmail.com>
* @author Björn Schießle <bjoern@schiessle.org> * @author Björn Schießle <bjoern@schiessle.org>
* @author Florin Peter <github@florin-peter.de> * @author Florin Peter <github@florin-peter.de>
@ -774,17 +775,40 @@ class Cache implements ICache {
* @param string|boolean $path * @param string|boolean $path
* @param array $data (optional) meta data of the folder * @param array $data (optional) meta data of the folder
*/ */
public function correctFolderSize($path, $data = null) { public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
$this->calculateFolderSize($path, $data); $this->calculateFolderSize($path, $data);
if ($path !== '') { if ($path !== '') {
$parent = dirname($path); $parent = dirname($path);
if ($parent === '.' or $parent === '/') { if ($parent === '.' or $parent === '/') {
$parent = ''; $parent = '';
} }
$this->correctFolderSize($parent); if ($isBackgroundScan) {
$parentData = $this->get($parent);
if ($parentData['size'] !== -1 && $this->getIncompleteChildrenCount($parentData['fileid']) === 0) {
$this->correctFolderSize($parent, $parentData, $isBackgroundScan);
}
} else {
$this->correctFolderSize($parent);
}
} }
} }
/**
* get the incomplete count that shares parent $folder
*
* @param int $fileId the file id of the folder
* @return int
*/
public function getIncompleteChildrenCount($fileId) {
if ($fileId > -1) {
$sql = 'SELECT count(*)
FROM `*PREFIX*filecache` WHERE `parent` = ? AND size = -1';
$result = $this->connection->executeQuery($sql, [$fileId]);
return (int)$result->fetchColumn();
}
return -1;
}
/** /**
* calculate the size of a folder and set it in the cache * calculate the size of a folder and set it in the cache
* *
@ -919,4 +943,4 @@ class Cache implements ICache {
return trim(\OC_Util::normalizeUnicode($path), '/'); return trim(\OC_Util::normalizeUnicode($path), '/');
} }
} }

View file

@ -532,7 +532,7 @@ class Scanner extends BasicEmitter implements IScanner {
$callback(); $callback();
\OC_Hook::emit('Scanner', 'correctFolderSize', array('path' => $path)); \OC_Hook::emit('Scanner', 'correctFolderSize', array('path' => $path));
if ($this->cacheActive && $this->cache instanceof Cache) { if ($this->cacheActive && $this->cache instanceof Cache) {
$this->cache->correctFolderSize($path); $this->cache->correctFolderSize($path, null, true);
} }
} catch (\OCP\Files\StorageInvalidException $e) { } catch (\OCP\Files\StorageInvalidException $e) {
// skip unavailable storages // skip unavailable storages

View file

@ -265,9 +265,9 @@ class CacheJail extends CacheWrapper {
* @param string|boolean $path * @param string|boolean $path
* @param array $data (optional) meta data of the folder * @param array $data (optional) meta data of the folder
*/ */
public function correctFolderSize($path, $data = null) { public function correctFolderSize($path, $data = null, $isBackgroundSize = false) {
if ($this->getCache() instanceof Cache) { if ($this->getCache() instanceof Cache) {
$this->getCache()->correctFolderSize($this->getSourcePath($path), $data); $this->getCache()->correctFolderSize($this->getSourcePath($path), $data, $isBackgroundSize);
} }
} }

View file

@ -258,9 +258,9 @@ class CacheWrapper extends Cache {
* @param string|boolean $path * @param string|boolean $path
* @param array $data (optional) meta data of the folder * @param array $data (optional) meta data of the folder
*/ */
public function correctFolderSize($path, $data = null) { public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
if ($this->getCache() instanceof Cache) { if ($this->getCache() instanceof Cache) {
$this->getCache()->correctFolderSize($path, $data); $this->getCache()->correctFolderSize($path, $data, $isBackgroundScan);
} }
} }

View file

@ -203,6 +203,44 @@ class ScannerTest extends \Test\TestCase {
$this->assertFalse($this->cache->getIncomplete()); $this->assertFalse($this->cache->getIncomplete());
} }
public function testBackgroundScanNestedIncompleteFolders() {
$this->storage->mkdir('folder');
$this->scanner->backgroundScan();
$this->storage->mkdir('folder/subfolder1');
$this->storage->mkdir('folder/subfolder2');
$this->storage->mkdir('folder/subfolder1/subfolder3');
$this->cache->put('folder', ['size' => -1]);
$this->cache->put('folder/subfolder1', ['size' => -1]);
// do a scan to get the folders into the cache.
$this->scanner->backgroundScan();
$this->assertTrue($this->cache->inCache('folder/subfolder1/subfolder3'));
$this->storage->file_put_contents('folder/subfolder1/bar1.txt', 'foobar');
$this->storage->file_put_contents('folder/subfolder1/subfolder3/bar3.txt', 'foobar');
$this->storage->file_put_contents('folder/subfolder2/bar2.txt', 'foobar');
//mark folders as incomplete.
$this->cache->put('folder/subfolder1', ['size' => -1]);
$this->cache->put('folder/subfolder2', ['size' => -1]);
$this->cache->put('folder/subfolder1/subfolder3', ['size' => -1]);
$this->scanner->backgroundScan();
$this->assertTrue($this->cache->inCache('folder/subfolder1/bar1.txt'));
$this->assertTrue($this->cache->inCache('folder/subfolder2/bar2.txt'));
$this->assertTrue($this->cache->inCache('folder/subfolder1/subfolder3/bar3.txt'));
//check if folder sizes are correct.
$this->assertEquals(18, $this->cache->get('folder')['size']);
$this->assertEquals(12, $this->cache->get('folder/subfolder1')['size']);
$this->assertEquals(6, $this->cache->get('folder/subfolder1/subfolder3')['size']);
$this->assertEquals(6, $this->cache->get('folder/subfolder2')['size']);
}
public function testReuseExisting() { public function testReuseExisting() {
$this->fillTestFolders(); $this->fillTestFolders();