summaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2017-01-30 17:15:57 -0600
committerGitHub <noreply@github.com>2017-01-30 17:15:57 -0600
commit687e38c40949ac291c036523e6d8cb5f1d8dd180 (patch)
treebe8cf978fbdb1ca1f14d6e3ef0a2da5705d3173c /apps/files_external/lib
parentf70f427a631436f22eb90f01f74f2e2996cbf75f (diff)
parent90c011379c09821887f9a17e5068ec7f590efc05 (diff)
downloadnextcloud-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.php57
-rw-r--r--apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php150
-rw-r--r--apps/files_external/lib/Lib/Storage/SMB.php51
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);
}
}