diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php index dc95dde480..3af6f733b5 100644 --- a/apps/files_sharing/lib/watcher.php +++ b/apps/files_sharing/lib/watcher.php @@ -29,41 +29,41 @@ namespace OC\Files\Cache; * check the storage backends for updates and change the cache accordingly */ class Shared_Watcher extends Watcher { + /** + * @var \OC\Files\Storage\Shared $storage + */ + protected $storage; /** - * check $path for updates + * Update the cache for changes to $path * * @param string $path - * @param array $cachedEntry - * @return boolean true if path was updated + * @param array $cachedData */ - public function checkUpdate($path, $cachedEntry = null) { - if (parent::checkUpdate($path, $cachedEntry) === true) { - // since checkUpdate() has already updated the size of the subdirs, - // only apply the update to the owner's parent dirs + public function update($path, $cachedData) { + parent::update($path, $cachedData); + // since parent::update() has already updated the size of the subdirs, + // only apply the update to the owner's parent dirs - // find last parent before reaching the shared storage root, - // which is the actual shared dir from the owner - $sepPos = strpos($path, '/'); - if ($sepPos > 0) { - $baseDir = substr($path, 0, $sepPos); - } else { - $baseDir = $path; - } - - // find the path relative to the data dir - $file = $this->storage->getFile($baseDir); - $view = new \OC\Files\View('/' . $file['fileOwner']); - - // find the owner's storage and path - list($storage, $internalPath) = $view->resolvePath($file['path']); - - // update the parent dirs' sizes in the owner's cache - $storage->getCache()->correctFolderSize(dirname($internalPath)); - - return true; + // find last parent before reaching the shared storage root, + // which is the actual shared dir from the owner + $sepPos = strpos($path, '/'); + if ($sepPos > 0) { + $baseDir = substr($path, 0, $sepPos); + } else { + $baseDir = $path; } - return false; + + // find the path relative to the data dir + $file = $this->storage->getFile($baseDir); + $view = new \OC\Files\View('/' . $file['fileOwner']); + + // find the owner's storage and path + /** @var \OC\Files\Storage\Storage $storage */ + list($storage, $internalPath) = $view->resolvePath($file['path']); + + // update the parent dirs' sizes in the owner's cache + $storage->getCache()->correctFolderSize(dirname($internalPath)); } /** diff --git a/lib/private/files/cache/watcher.php b/lib/private/files/cache/watcher.php index ff97a1f9c0..e660e56bfe 100644 --- a/lib/private/files/cache/watcher.php +++ b/lib/private/files/cache/watcher.php @@ -74,36 +74,57 @@ class Watcher { } /** - * check $path for updates + * check $path for updates and update if needed * * @param string $path * @param array $cachedEntry * @return boolean true if path was updated */ public function checkUpdate($path, $cachedEntry = null) { - if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and array_search($path, $this->checkedPaths) === false)) { - if (is_null($cachedEntry)) { - $cachedEntry = $this->cache->get($path); - } - $this->checkedPaths[] = $path; - if ($this->storage->hasUpdated($path, $cachedEntry['storage_mtime'])) { - if ($this->storage->is_dir($path)) { - $this->scanner->scan($path, Scanner::SCAN_SHALLOW); - } else { - $this->scanner->scanFile($path); - } - if ($cachedEntry['mimetype'] === 'httpd/unix-directory') { - $this->cleanFolder($path); - } - $this->cache->correctFolderSize($path); - return true; - } - return false; + if (is_null($cachedEntry)) { + $cachedEntry = $this->cache->get($path); + } + if ($this->needsUpdate($path, $cachedEntry)) { + $this->update($path, $cachedEntry); + return true; } else { return false; } } + /** + * Update the cache for changes to $path + * + * @param string $path + * @param array $cachedData + */ + public function update($path, $cachedData) { + if ($this->storage->is_dir($path)) { + $this->scanner->scan($path, Scanner::SCAN_SHALLOW); + } else { + $this->scanner->scanFile($path); + } + if ($cachedData['mimetype'] === 'httpd/unix-directory') { + $this->cleanFolder($path); + } + $this->cache->correctFolderSize($path); + } + + /** + * Check if the cache for $path needs to be updated + * + * @param string $path + * @param array $cachedData + * @return bool + */ + public function needsUpdate($path, $cachedData) { + if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and array_search($path, $this->checkedPaths) === false)) { + $this->checkedPaths[] = $path; + return $this->storage->hasUpdated($path, $cachedData['storage_mtime']); + } + return false; + } + /** * remove deleted files in $path from the cache * diff --git a/lib/private/files/view.php b/lib/private/files/view.php index a11df53705..887b18530d 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1191,13 +1191,13 @@ class View { if ($storage) { $cache = $storage->getCache($internalPath); - try { - $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); - $data = $cache->get($internalPath); - $watcher = $storage->getWatcher($internalPath); + $data = $cache->get($internalPath); + $watcher = $storage->getWatcher($internalPath); + try { // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data if (!$data) { + $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); if (!$storage->file_exists($internalPath)) { $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); return false; @@ -1205,14 +1205,16 @@ class View { $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); $data = $cache->get($internalPath); - } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->checkUpdate($internalPath, $data)) { + $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); + } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) { + $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED); + $watcher->update($internalPath, $data); $this->updater->propagate($path); $data = $cache->get($internalPath); + $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); } - $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED); } catch (LockedException $e) { - // dont try to update the cache when the file is locked - $data = $cache->get($internalPath); + // if the file is locked we just use the old cache info } if ($data and isset($data['fileid'])) { @@ -1278,12 +1280,11 @@ class View { */ $files = array(); + $data = $cache->get($internalPath); + $watcher = $storage->getWatcher($internalPath); try { - $this->lockFile($directory, ILockingProvider::LOCK_SHARED); - - $data = $cache->get($internalPath); - $watcher = $storage->getWatcher($internalPath); if (!$data or $data['size'] === -1) { + $this->lockFile($directory, ILockingProvider::LOCK_SHARED); if (!$storage->file_exists($internalPath)) { $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); return array(); @@ -1291,20 +1292,21 @@ class View { $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); $data = $cache->get($internalPath); - } else if ($watcher->checkUpdate($internalPath, $data)) { + $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); + } else if ($watcher->needsUpdate($internalPath, $data)) { + $this->lockFile($directory, ILockingProvider::LOCK_SHARED); + $watcher->update($internalPath, $data); $this->updater->propagate($path); $data = $cache->get($internalPath); + $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); } - - $folderId = $data['fileid']; - $contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter - - $this->unlockFile($directory, ILockingProvider::LOCK_SHARED); } catch (LockedException $e) { - // dont try to update the cache when the file is locked - $contents = $cache->getFolderContents($internalPath); + // if the file is locked we just use the old cache info } + $folderId = $data['fileid']; + $contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter + foreach ($contents as $content) { if ($content['permissions'] === 0) { $content['permissions'] = $storage->getPermissions($content['path']);