Merge pull request #8968 from owncloud/scanner-parent-repair

Repair broken parent link in the scanner
remotes/origin/ldap_group_count
Vincent Petry 10 years ago
commit b595c982d0

@ -89,10 +89,9 @@ class Scanner extends BasicEmitter {
* *
* @param string $file * @param string $file
* @param int $reuseExisting * @param int $reuseExisting
* @param bool $parentExistsInCache
* @return array an array of 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) if (!self::isPartialFile($file)
and !Filesystem::isFileBlacklisted($file) and !Filesystem::isFileBlacklisted($file)
) { ) {
@ -100,45 +99,49 @@ class Scanner extends BasicEmitter {
\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
$data = $this->getData($file); $data = $this->getData($file);
if ($data) { if ($data) {
if ($file and !$parentExistsInCache) { $parent = dirname($file);
$parent = dirname($file); if ($parent === '.' or $parent === '/') {
if ($parent === '.' or $parent === '/') { $parent = '';
$parent = ''; }
} $parentId = $this->cache->getId($parent);
if (!$this->cache->inCache($parent)) {
$this->scanFile($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); $cacheData = $this->cache->get($file);
if ($cacheData) { if ($cacheData and $reuseExisting) {
if ($reuseExisting) { // prevent empty etag
// prevent empty etag if (empty($cacheData['etag'])) {
if (empty($cacheData['etag'])) { $etag = $data['etag'];
$etag = $data['etag']; } else {
} else { $etag = $cacheData['etag'];
$etag = $cacheData['etag']; }
} // only reuse data if the file hasn't explicitly changed
// 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 (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) { $data['mtime'] = $cacheData['mtime'];
$data['mtime'] = $cacheData['mtime']; if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) { $data['size'] = $cacheData['size'];
$data['size'] = $cacheData['size'];
}
if ($reuseExisting & self::REUSE_ETAG) {
$data['etag'] = $etag;
}
} }
// Only update metadata that has changed if ($reuseExisting & self::REUSE_ETAG) {
$newData = array_diff_assoc($data, $cacheData); $data['etag'] = $etag;
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);
} }
} }
// 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)) { if (!empty($newData)) {
$data['fileid'] = $this->addToCache($file, $newData); $data['fileid'] = $this->addToCache($file, $newData);
@ -238,7 +241,7 @@ class Scanner extends BasicEmitter {
if (!Filesystem::isIgnoredDir($file)) { if (!Filesystem::isIgnoredDir($file)) {
$newChildren[] = $file; $newChildren[] = $file;
try { try {
$data = $this->scanFile($child, $reuse, true); $data = $this->scanFile($child, $reuse);
if ($data) { if ($data) {
if ($data['mimetype'] === 'httpd/unix-directory' and $recursive === self::SCAN_RECURSIVE) { if ($data['mimetype'] === 'httpd/unix-directory' and $recursive === self::SCAN_RECURSIVE) {
$childQueue[] = $child; $childQueue[] = $child;

@ -32,7 +32,6 @@ class Scanner extends \PHPUnit_Framework_TestCase {
function tearDown() { function tearDown() {
if ($this->cache) { if ($this->cache) {
$ids = $this->cache->getAll();
$this->cache->clear(); $this->cache->clear();
} }
} }
@ -199,7 +198,7 @@ class Scanner extends \PHPUnit_Framework_TestCase {
$this->assertFalse($this->cache->inCache('folder/bar.txt')); $this->assertFalse($this->cache->inCache('folder/bar.txt'));
} }
public function testScanRemovedFile(){ public function testScanRemovedFile() {
$this->fillTestFolders(); $this->fillTestFolders();
$this->scanner->scan(''); $this->scanner->scan('');
@ -233,4 +232,52 @@ class Scanner extends \PHPUnit_Framework_TestCase {
$this->assertInternalType('string', $newData0['etag']); $this->assertInternalType('string', $newData0['etag']);
$this->assertNotEmpty($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']);
}
} }

Loading…
Cancel
Save