mirror of
https://github.com/nextcloud/server.git
synced 2026-06-03 22:06:34 -04:00
Merge pull request #9008 from owncloud/repair-parent-stable6
Repair broken parent link in the scanner - stable6
This commit is contained in:
commit
f6c970e214
3 changed files with 94 additions and 43 deletions
83
lib/private/files/cache/scanner.php
vendored
83
lib/private/files/cache/scanner.php
vendored
|
|
@ -94,10 +94,9 @@ class Scanner extends BasicEmitter {
|
|||
*
|
||||
* @param string $file
|
||||
* @param int $reuseExisting
|
||||
* @param bool $parentExistsInCache
|
||||
* @return array with metadata of the scanned file
|
||||
* @return array an array of metadata of the scanned file
|
||||
*/
|
||||
public function scanFile($file, $reuseExisting = 0, $parentExistsInCache = false) {
|
||||
public function scanFile($file, $reuseExisting = 0) {
|
||||
if (!self::isPartialFile($file)
|
||||
and !Filesystem::isFileBlacklisted($file)
|
||||
) {
|
||||
|
|
@ -105,48 +104,52 @@ class Scanner extends BasicEmitter {
|
|||
\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
|
||||
$data = $this->getData($file);
|
||||
if ($data) {
|
||||
if ($file and !$parentExistsInCache) {
|
||||
$parent = dirname($file);
|
||||
if ($parent === '.' or $parent === '/') {
|
||||
$parent = '';
|
||||
}
|
||||
if (!$this->cache->inCache($parent)) {
|
||||
$this->scanFile($parent);
|
||||
}
|
||||
$parent = dirname($file);
|
||||
if ($parent === '.' or $parent === '/') {
|
||||
$parent = '';
|
||||
}
|
||||
$parentId = $this->cache->getId($parent);
|
||||
|
||||
// scan the parent if it's not in the cache (id -1) and the current file is not the root folder
|
||||
if ($file and $parentId === -1) {
|
||||
$parentData = $this->scanFile($parent);
|
||||
$parentId = $parentData['fileid'];
|
||||
}
|
||||
if ($parent) {
|
||||
$data['parent'] = $parentId;
|
||||
}
|
||||
$newData = $data;
|
||||
$cacheData = $this->cache->get($file);
|
||||
if ($cacheData) {
|
||||
if (isset($cacheData['fileid'])) {
|
||||
$this->permissionsCache->remove($cacheData['fileid']);
|
||||
}
|
||||
if ($reuseExisting) {
|
||||
// prevent empty etag
|
||||
if ( $cacheData and isset($cacheData['fileid'])) {
|
||||
$this->permissionsCache->remove($cacheData['fileid']);
|
||||
}
|
||||
if ($cacheData and $reuseExisting) {
|
||||
// prevent empty etag
|
||||
if (empty($cacheData['etag'])) {
|
||||
$etag = $data['etag'];
|
||||
} else {
|
||||
$etag = $cacheData['etag'];
|
||||
if (empty($etag)) {
|
||||
$etag = $data['etag'];
|
||||
} else {
|
||||
$etag = $cacheData['etag'];
|
||||
}
|
||||
// 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']) {
|
||||
$data['mtime'] = $cacheData['mtime'];
|
||||
if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
|
||||
$data['size'] = $cacheData['size'];
|
||||
}
|
||||
// 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']) {
|
||||
if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
|
||||
$data['size'] = $cacheData['size'];
|
||||
}
|
||||
if ($reuseExisting & self::REUSE_ETAG) {
|
||||
$data['etag'] = $etag;
|
||||
}
|
||||
}
|
||||
// Only update metadata that has changed
|
||||
$newData = array_diff_assoc($data, $cacheData);
|
||||
if (isset($newData['etag'])) {
|
||||
$cacheDataString = print_r($cacheData, true);
|
||||
$dataString = print_r($data, true);
|
||||
\OCP\Util::writeLog('OC\Files\Cache\Scanner',
|
||||
"!!! No reuse of etag for '$file' !!! \ncache: $cacheDataString \ndata: $dataString",
|
||||
\OCP\Util::DEBUG);
|
||||
if ($reuseExisting & self::REUSE_ETAG) {
|
||||
$data['etag'] = $etag;
|
||||
}
|
||||
}
|
||||
// Only update metadata that has changed
|
||||
$newData = array_diff_assoc($data, $cacheData);
|
||||
if (isset($newData['etag'])) {
|
||||
$cacheDataString = print_r($cacheData, true);
|
||||
$dataString = print_r($data, true);
|
||||
\OCP\Util::writeLog('OC\Files\Cache\Scanner',
|
||||
"!!! No reuse of etag for '$file' !!! \ncache: $cacheDataString \ndata: $dataString",
|
||||
\OCP\Util::DEBUG);
|
||||
}
|
||||
} else {
|
||||
$newData = $data;
|
||||
}
|
||||
if (!empty($newData)) {
|
||||
$data['fileid'] = $this->addToCache($file, $newData);
|
||||
|
|
@ -244,7 +247,7 @@ class Scanner extends BasicEmitter {
|
|||
if (!Filesystem::isIgnoredDir($file)) {
|
||||
$newChildren[] = $file;
|
||||
try {
|
||||
$data = $this->scanFile($child, $reuse, true);
|
||||
$data = $this->scanFile($child, $reuse);
|
||||
if ($data) {
|
||||
if ($data['mimetype'] === 'httpd/unix-directory' and $recursive === self::SCAN_RECURSIVE) {
|
||||
$childQueue[] = $child;
|
||||
|
|
|
|||
50
tests/lib/files/cache/scanner.php
vendored
50
tests/lib/files/cache/scanner.php
vendored
|
|
@ -199,7 +199,7 @@ class Scanner extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertFalse($this->cache->inCache('folder/bar.txt'));
|
||||
}
|
||||
|
||||
public function testScanRemovedFile(){
|
||||
public function testScanRemovedFile() {
|
||||
$this->fillTestFolders();
|
||||
|
||||
$this->scanner->scan('');
|
||||
|
|
@ -230,4 +230,52 @@ class Scanner extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertInternalType('string', $newData0['etag']);
|
||||
$this->assertNotEmpty($newData0['etag']);
|
||||
}
|
||||
|
||||
public function testRepairParent() {
|
||||
$this->fillTestFolders();
|
||||
$this->scanner->scan('');
|
||||
$this->assertTrue($this->cache->inCache('folder/bar.txt'));
|
||||
$oldFolderId = $this->cache->getId('folder');
|
||||
|
||||
// delete the folder without removing the childs
|
||||
$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
|
||||
\OC_DB::executeAudited($sql, array($oldFolderId));
|
||||
|
||||
$cachedData = $this->cache->get('folder/bar.txt');
|
||||
$this->assertEquals($oldFolderId, $cachedData['parent']);
|
||||
$this->assertFalse($this->cache->inCache('folder'));
|
||||
|
||||
$this->scanner->scan('');
|
||||
|
||||
$this->assertTrue($this->cache->inCache('folder'));
|
||||
$newFolderId = $this->cache->getId('folder');
|
||||
$this->assertNotEquals($oldFolderId, $newFolderId);
|
||||
|
||||
$cachedData = $this->cache->get('folder/bar.txt');
|
||||
$this->assertEquals($newFolderId, $cachedData['parent']);
|
||||
}
|
||||
|
||||
public function testRepairParentShallow() {
|
||||
$this->fillTestFolders();
|
||||
$this->scanner->scan('');
|
||||
$this->assertTrue($this->cache->inCache('folder/bar.txt'));
|
||||
$oldFolderId = $this->cache->getId('folder');
|
||||
|
||||
// delete the folder without removing the childs
|
||||
$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
|
||||
\OC_DB::executeAudited($sql, array($oldFolderId));
|
||||
|
||||
$cachedData = $this->cache->get('folder/bar.txt');
|
||||
$this->assertEquals($oldFolderId, $cachedData['parent']);
|
||||
$this->assertFalse($this->cache->inCache('folder'));
|
||||
|
||||
$this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW);
|
||||
|
||||
$this->assertTrue($this->cache->inCache('folder'));
|
||||
$newFolderId = $this->cache->getId('folder');
|
||||
$this->assertNotEquals($oldFolderId, $newFolderId);
|
||||
|
||||
$cachedData = $this->cache->get('folder/bar.txt');
|
||||
$this->assertEquals($newFolderId, $cachedData['parent']);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class Scanner extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertEquals(array('/foo', '/foo/folder', '/foo/folder/bar.txt', '/foo/foo.txt'), $changes);
|
||||
$this->assertEquals(array('/', '/foo', '/foo/folder'), $parents);
|
||||
|
||||
$cache->put('foo.txt', array('mtime' => time() - 50));
|
||||
$cache->put('foo.txt', array('storage_mtime' => time() - 50));
|
||||
|
||||
$propagator = $this->getMock('\OC\Files\Cache\ChangePropagator', array('propagateChanges'), array(), '', false);
|
||||
$scanner->setPropagator($propagator);
|
||||
|
|
@ -128,7 +128,7 @@ class Scanner extends \PHPUnit_Framework_TestCase {
|
|||
$scanner->setPropagator($originalPropagator);
|
||||
|
||||
$oldInfo = $cache->get('');
|
||||
$cache->put('foo.txt', array('mtime' => time() - 70));
|
||||
$cache->put('foo.txt', array('storage_mtime' => time() - 70));
|
||||
$storage->file_put_contents('foo.txt', 'asdasd');
|
||||
|
||||
$scanner->scan('');
|
||||
|
|
|
|||
Loading…
Reference in a new issue