diff options
author | Morris Jobke <hey@morrisjobke.de> | 2017-01-30 17:15:57 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-30 17:15:57 -0600 |
commit | 687e38c40949ac291c036523e6d8cb5f1d8dd180 (patch) | |
tree | be8cf978fbdb1ca1f14d6e3ef0a2da5705d3173c /apps/files_external/lib | |
parent | f70f427a631436f22eb90f01f74f2e2996cbf75f (diff) | |
parent | 90c011379c09821887f9a17e5068ec7f590efc05 (diff) | |
download | nextcloud-server-687e38c40949ac291c036523e6d8cb5f1d8dd180.tar.gz nextcloud-server-687e38c40949ac291c036523e6d8cb5f1d8dd180.zip |
Merge pull request #2970 from nextcloud/notify-self-test
Add self-test for files_external:notify
Diffstat (limited to 'apps/files_external/lib')
-rw-r--r-- | apps/files_external/lib/Command/Notify.php | 57 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php | 150 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Storage/SMB.php | 51 |
3 files changed, 209 insertions, 49 deletions
diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php index 913299b59b4..a55b16a45c4 100644 --- a/apps/files_external/lib/Command/Notify.php +++ b/apps/files_external/lib/Command/Notify.php @@ -27,7 +27,11 @@ use OC\Core\Command\Base; use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\Service\GlobalStoragesService; +use OCP\Files\Notify\IChange; +use OCP\Files\Notify\INotifyHandler; +use OCP\Files\Notify\IRenameChange; use OCP\Files\Storage\INotifyStorage; +use OCP\Files\Storage\IStorage; use OCP\Files\StorageNotAvailableException; use OCP\IDBConnection; use Symfony\Component\Console\Input\InputArgument; @@ -123,14 +127,16 @@ class Notify extends Base { $verbose = $input->getOption('verbose'); $path = trim($input->getOption('path'), '/'); - $storage->listen($path, function ($type, $path, $renameTarget) use ($mount, $verbose, $output) { + $notifyHandler = $storage->notify($path); + $this->selfTest($storage, $notifyHandler, $verbose, $output); + $notifyHandler->listen(function (IChange $change) use ($mount, $verbose, $output) { if ($verbose) { - $this->logUpdate($type, $path, $renameTarget, $output); + $this->logUpdate($change, $output); } - if ($type == INotifyStorage::NOTIFY_RENAMED) { - $this->markParentAsOutdated($mount->getId(), $renameTarget); + if ($change instanceof IRenameChange) { + $this->markParentAsOutdated($mount->getId(), $change->getTargetPath()); } - $this->markParentAsOutdated($mount->getId(), $path); + $this->markParentAsOutdated($mount->getId(), $change->getPath()); }); } @@ -147,8 +153,8 @@ class Notify extends Base { $this->updateQuery->execute([$parent, $mountId]); } - private function logUpdate($type, $path, $renameTarget, OutputInterface $output) { - switch ($type) { + private function logUpdate(IChange $change, OutputInterface $output) { + switch ($change->getType()) { case INotifyStorage::NOTIFY_ADDED: $text = 'added'; break; @@ -165,11 +171,42 @@ class Notify extends Base { return; } - $text .= ' ' . $path; - if ($type === INotifyStorage::NOTIFY_RENAMED) { - $text .= ' to ' . $renameTarget; + $text .= ' ' . $change->getPath(); + if ($change instanceof IRenameChange) { + $text .= ' to ' . $change->getTargetPath(); } $output->writeln($text); } + + private function selfTest(IStorage $storage, INotifyHandler $notifyHandler, $verbose, OutputInterface $output) { + usleep(100 * 1000); //give time for the notify to start + $storage->file_put_contents('/.nc_test_file.txt', 'test content'); + $storage->mkdir('/.nc_test_folder'); + $storage->file_put_contents('/.nc_test_folder/subfile.txt', 'test content'); + $storage->unlink('/.nc_test_file.txt'); + $storage->unlink('/.nc_test_folder/subfile.txt'); + $storage->rmdir('/.nc_test_folder'); + usleep(100 * 1000); //time for all changes to be processed + + $foundRootChange = false; + $foundSubfolderChange = false; + + $changes = $notifyHandler->getChanges(); + foreach ($changes as $change) { + if ($change->getPath() === '/.nc_test_file.txt') { + $foundRootChange = true; + } else if ($change->getPath() === '/.nc_test_folder/subfile.txt') { + $foundSubfolderChange = true; + } + } + + if ($foundRootChange && $foundSubfolderChange && $verbose) { + $output->writeln('<info>Self-test successful</info>'); + } else if ($foundRootChange && !$foundSubfolderChange) { + $output->writeln('<error>Error while running self-test, change is subfolder not detected</error>'); + } else if (!$foundRootChange) { + $output->writeln('<error>Error while running self-test, no changes detected</error>'); + } + } } diff --git a/apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php b/apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php new file mode 100644 index 00000000000..9ac74b32ad8 --- /dev/null +++ b/apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php @@ -0,0 +1,150 @@ +<?php +/** + * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> + * + * @author Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_External\Lib\Notify; + +use OC\Files\Notify\Change; +use OC\Files\Notify\RenameChange; +use OCP\Files\Notify\IChange; +use OCP\Files\Notify\INotifyHandler; + +class SMBNotifyHandler implements INotifyHandler { + /** + * @var \Icewind\SMB\INotifyHandler + */ + private $shareNotifyHandler; + + /** + * @var string + */ + private $root; + + private $oldRenamePath = null; + + /** + * SMBNotifyHandler constructor. + * + * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler + * @param string $root + */ + public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) { + $this->shareNotifyHandler = $shareNotifyHandler; + $this->root = $root; + } + + private function relativePath($fullPath) { + if ($fullPath === $this->root) { + return ''; + } else if (substr($fullPath, 0, strlen($this->root)) === $this->root) { + return substr($fullPath, strlen($this->root)); + } else { + return null; + } + } + + public function listen(callable $callback) { + $oldRenamePath = null; + $this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) { + $change = $this->mapChange($shareChange); + if (!is_null($change)) { + return $callback($change); + } else { + return true; + } + }); + } + + /** + * Get all changes detected since the start of the notify process or the last call to getChanges + * + * @return IChange[] + */ + public function getChanges() { + $shareChanges = $this->shareNotifyHandler->getChanges(); + $changes = []; + foreach ($shareChanges as $shareChange) { + $change = $this->mapChange($shareChange); + if ($change) { + $changes[] = $change; + } + } + return $changes; + } + + /** + * Stop listening for changes + * + * Note that any pending changes will be discarded + */ + public function stop() { + $this->shareNotifyHandler->stop(); + } + + /** + * @param \Icewind\SMB\Change $change + * @return IChange|null + */ + private function mapChange(\Icewind\SMB\Change $change) { + $path = $this->relativePath($change->getPath()); + if (is_null($path)) { + return null; + } + if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) { + $this->oldRenamePath = $path; + return null; + } + $type = $this->mapNotifyType($change->getCode()); + if (is_null($type)) { + return null; + } + if ($type === IChange::RENAMED) { + if (!is_null($this->oldRenamePath)) { + $result = new RenameChange($type, $this->oldRenamePath, $path); + $this->oldRenamePath = null; + } else { + $result = null; + } + } else { + $result = new Change($type, $path); + } + return $result; + } + + private function mapNotifyType($smbType) { + switch ($smbType) { + case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED: + return IChange::ADDED; + case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED: + return IChange::REMOVED; + case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED: + case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM: + case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM: + case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM: + return IChange::MODIFIED; + case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW: + return IChange::RENAMED; + default: + return null; + } + } +} diff --git a/apps/files_external/lib/Lib/Storage/SMB.php b/apps/files_external/lib/Lib/Storage/SMB.php index 7ffc078df6f..690f8e2a334 100644 --- a/apps/files_external/lib/Lib/Storage/SMB.php +++ b/apps/files_external/lib/Lib/Storage/SMB.php @@ -46,6 +46,9 @@ use Icewind\Streams\IteratorDirectory; use OC\Cache\CappedMemoryCache; use OC\Files\Filesystem; use OC\Files\Storage\Common; +use OCA\Files_External\Lib\Notify\SMBNotifyHandler; +use OCP\Files\Notify\IChange; +use OCP\Files\Notify\IRenameChange; use OCP\Files\Storage\INotifyStorage; use OCP\Files\StorageNotAvailableException; @@ -149,7 +152,7 @@ class SMB extends Common implements INotifyStorage { foreach ($files as $file) { $this->statCache[$path . '/' . $file->getName()] = $file; } - return array_filter($files, function(IFileInfo $file) { + return array_filter($files, function (IFileInfo $file) { return !$file->isHidden(); }); } catch (ConnectException $e) { @@ -486,48 +489,18 @@ class SMB extends Common implements INotifyStorage { } public function listen($path, callable $callback) { - $fullPath = $this->buildPath($path); - $oldRenamePath = null; - $this->share->notify($fullPath)->listen(function (Change $change) use (&$oldRenamePath, $callback) { - $path = $this->relativePath($change->getPath()); - if (is_null($path)) { - return true; - } - if ($change->getCode() === INotifyHandler::NOTIFY_RENAMED_OLD) { - $oldRenamePath = $path; - return true; - } - $type = $this->mapNotifyType($change->getCode()); - if (is_null($type)) { - return true; - } - if ($type === INotifyStorage::NOTIFY_RENAMED) { - if (!is_null($oldRenamePath)) { - $result = $callback($type, $oldRenamePath, $path); - $oldRenamePath = null; - } + $this->notify($path)->listen(function (IChange $change) use ($callback) { + if ($change instanceof IRenameChange) { + return $callback($change->getType(), $change->getPath(), $change->getTargetPath()); } else { - $result = $callback($type, $path); + return $callback($change->getType(), $change->getPath()); } - return $result; }); } - private function mapNotifyType($smbType) { - switch ($smbType) { - case INotifyHandler::NOTIFY_ADDED: - return INotifyStorage::NOTIFY_ADDED; - case INotifyHandler::NOTIFY_REMOVED: - return INotifyStorage::NOTIFY_REMOVED; - case INotifyHandler::NOTIFY_MODIFIED: - case INotifyHandler::NOTIFY_ADDED_STREAM: - case INotifyHandler::NOTIFY_MODIFIED_STREAM: - case INotifyHandler::NOTIFY_REMOVED_STREAM: - return INotifyStorage::NOTIFY_MODIFIED; - case INotifyHandler::NOTIFY_RENAMED_NEW: - return INotifyStorage::NOTIFY_RENAMED; - default: - return null; - } + public function notify($path) { + $path = '/' . ltrim($path, '/'); + $shareNotifyHandler = $this->share->notify($this->buildPath($path)); + return new SMBNotifyHandler($shareNotifyHandler, $this->root); } } |