diff options
author | Robin Appelman <robin@icewind.nl> | 2017-08-25 14:53:16 +0200 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2017-08-26 18:58:06 +0200 |
commit | 804d97d6ff5e21ae3253e1b09ce283047e6b14d9 (patch) | |
tree | 12259efa90a78b3217c14a025fb0c94e1b6be2b8 /lib/private/Files | |
parent | 18908af87b6048521c90364aaca01e83e24c22ef (diff) | |
download | nextcloud-server-804d97d6ff5e21ae3253e1b09ce283047e6b14d9.tar.gz nextcloud-server-804d97d6ff5e21ae3253e1b09ce283047e6b14d9.zip |
unlock file when an exception occurs during scanning
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib/private/Files')
-rw-r--r-- | lib/private/Files/Cache/Scanner.php | 156 |
1 files changed, 87 insertions, 69 deletions
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index a81c34c31fa..3245af0c095 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -137,7 +137,6 @@ class Scanner extends BasicEmitter implements IScanner { return null; } } - // only proceed if $file is not a partial file nor a blacklisted file if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) { @@ -151,88 +150,103 @@ class Scanner extends BasicEmitter implements IScanner { try { $data = $this->getData($file); } catch (ForbiddenException $e) { + if ($lock) { + if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { + $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); + } + } + return null; } - if ($data) { + try { + if ($data) { - // pre-emit only if it was a file. By that we avoid counting/treating folders as files - if ($data['mimetype'] !== 'httpd/unix-directory') { - $this->emit('\OC\Files\Cache\Scanner', 'scanFile', array($file, $this->storageId)); - \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); - } + // pre-emit only if it was a file. By that we avoid counting/treating folders as files + if ($data['mimetype'] !== 'httpd/unix-directory') { + $this->emit('\OC\Files\Cache\Scanner', 'scanFile', array($file, $this->storageId)); + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); + } - $parent = dirname($file); - if ($parent === '.' or $parent === '/') { - $parent = ''; - } - if ($parentId === -1) { - $parentId = $this->cache->getParentId($file); - } + $parent = dirname($file); + if ($parent === '.' or $parent === '/') { + $parent = ''; + } + if ($parentId === -1) { + $parentId = $this->cache->getParentId($file); + } - // 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); - if (!$parentData) { - return null; + // 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); + if (!$parentData) { + return null; + } + $parentId = $parentData['fileid']; } - $parentId = $parentData['fileid']; - } - if ($parent) { - $data['parent'] = $parentId; - } - if (is_null($cacheData)) { - /** @var CacheEntry $cacheData */ - $cacheData = $this->cache->get($file); - } - if ($cacheData and $reuseExisting and isset($cacheData['fileid'])) { - // prevent empty etag - if (empty($cacheData['etag'])) { - $etag = $data['etag']; - } else { - $etag = $cacheData['etag']; + if ($parent) { + $data['parent'] = $parentId; + } + if (is_null($cacheData)) { + /** @var CacheEntry $cacheData */ + $cacheData = $this->cache->get($file); } - $fileId = $cacheData['fileid']; - $data['fileid'] = $fileId; - // 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']; + if ($cacheData and $reuseExisting and isset($cacheData['fileid'])) { + // prevent empty etag + if (empty($cacheData['etag'])) { + $etag = $data['etag']; + } else { + $etag = $cacheData['etag']; } - if ($reuseExisting & self::REUSE_ETAG) { - $data['etag'] = $etag; + $fileId = $cacheData['fileid']; + $data['fileid'] = $fileId; + // 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']; + } + if ($reuseExisting & self::REUSE_ETAG) { + $data['etag'] = $etag; + } } + // Only update metadata that has changed + $newData = array_diff_assoc($data, $cacheData->getData()); + } else { + $newData = $data; + $fileId = -1; + } + if (!empty($newData)) { + // Reset the checksum if the data has changed + $newData['checksum'] = ''; + $data['fileid'] = $this->addToCache($file, $newData, $fileId); + } + if (isset($cacheData['size'])) { + $data['oldSize'] = $cacheData['size']; + } else { + $data['oldSize'] = 0; } - // Only update metadata that has changed - $newData = array_diff_assoc($data, $cacheData->getData()); - } else { - $newData = $data; - $fileId = -1; - } - if (!empty($newData)) { - // Reset the checksum if the data has changed - $newData['checksum'] = ''; - $data['fileid'] = $this->addToCache($file, $newData, $fileId); - } - if (isset($cacheData['size'])) { - $data['oldSize'] = $cacheData['size']; - } else { - $data['oldSize'] = 0; - } - if (isset($cacheData['encrypted'])) { - $data['encrypted'] = $cacheData['encrypted']; - } + if (isset($cacheData['encrypted'])) { + $data['encrypted'] = $cacheData['encrypted']; + } - // post-emit only if it was a file. By that we avoid counting/treating folders as files - if ($data['mimetype'] !== 'httpd/unix-directory') { - $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', array($file, $this->storageId)); - \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId)); - } + // post-emit only if it was a file. By that we avoid counting/treating folders as files + if ($data['mimetype'] !== 'httpd/unix-directory') { + $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', array($file, $this->storageId)); + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId)); + } - } else { - $this->removeFromCache($file); + } else { + $this->removeFromCache($file); + } + } catch (\Exception $e) { + if ($lock) { + if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { + $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); + } + } + throw $e; } //release the acquired lock @@ -436,6 +450,10 @@ class Scanner extends BasicEmitter implements IScanner { // might happen if inserting duplicate while a scanning // process is running in parallel // log and ignore + if ($this->useTransactions) { + \OC::$server->getDatabaseConnection()->rollback(); + \OC::$server->getDatabaseConnection()->beginTransaction(); + } \OCP\Util::writeLog('core', 'Exception while scanning file "' . $child . '": ' . $ex->getMessage(), \OCP\Util::DEBUG); $exceptionOccurred = true; } catch (\OCP\Lock\LockedException $e) { |