[Pkg-owncloud-commits] [owncloud] 234/258: Add EtagPropagator to handle etag changes when external storages are changed

David Prévot taffit at moszumanska.debian.org
Sat Oct 11 17:22:40 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository owncloud.

commit a11a75fabae75b1e5e4f5394a4f0cb39bee39e3d
Author: Robin Appelman <icewind at owncloud.com>
Date:   Sun Sep 28 17:09:07 2014 +0200

    Add EtagPropagator to handle etag changes when external storages are changed
---
 apps/files_external/lib/etagpropagator.php   | 107 +++++++++
 apps/files_external/tests/etagpropagator.php | 328 +++++++++++++++++++++++++++
 2 files changed, 435 insertions(+)

diff --git a/apps/files_external/lib/etagpropagator.php b/apps/files_external/lib/etagpropagator.php
new file mode 100644
index 0000000..0057165
--- /dev/null
+++ b/apps/files_external/lib/etagpropagator.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind at owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Files_External;
+
+use OC\Files\Filesystem;
+
+class EtagPropagator {
+	/**
+	 * @var \OCP\IUser
+	 */
+	protected $user;
+
+	/**
+	 * @var \OC\Files\Cache\ChangePropagator
+	 */
+	protected $changePropagator;
+
+	/**
+	 * @var \OCP\IConfig
+	 */
+	protected $config;
+
+	/**
+	 * @param \OCP\IUser $user
+	 * @param \OC\Files\Cache\ChangePropagator $changePropagator
+	 * @param \OCP\IConfig $config
+	 */
+	public function __construct($user, $changePropagator, $config) {
+		$this->user = $user;
+		$this->changePropagator = $changePropagator;
+		$this->config = $config;
+	}
+
+	public function propagateDirtyMountPoints($time = null) {
+		if ($time === null) {
+			$time = time();
+		}
+		$mountPoints = $this->getDirtyMountPoints();
+		foreach ($mountPoints as $mountPoint) {
+			$this->changePropagator->addChange($mountPoint);
+			$this->config->setUserValue($this->user->getUID(), 'files_external', $mountPoint, $time);
+		}
+		if (count($mountPoints)) {
+			$this->changePropagator->propagateChanges($time);
+		}
+	}
+
+	/**
+	 * Get all mountpoints we need to update the etag for
+	 *
+	 * @return string[]
+	 */
+	protected function getDirtyMountPoints() {
+		$dirty = array();
+		$mountPoints = $this->config->getAppKeys('files_external');
+		foreach ($mountPoints as $mountPoint) {
+			if (substr($mountPoint, 0, 1) === '/') {
+				$updateTime = $this->config->getAppValue('files_external', $mountPoint);
+				$userTime = $this->config->getUserValue($this->user->getUID(), 'files_external', $mountPoint);
+				if ($updateTime > $userTime) {
+					$dirty[] = $mountPoint;
+				}
+			}
+		}
+		return $dirty;
+	}
+
+	/**
+	 * @param string $mountPoint
+	 * @param int $time
+	 */
+	protected function markDirty($mountPoint, $time = null) {
+		if ($time === null) {
+			$time = time();
+		}
+		$this->config->setAppValue('files_external', $mountPoint, $time);
+	}
+
+	/**
+	 * Update etags for mount points for known user
+	 * For global or group mount points, updating the etag for every user is not feasible
+	 * instead we mark the mount point as dirty and update the etag when the filesystem is loaded for the user
+	 *
+	 * @param array $params
+	 * @param int $time
+	 */
+	public function updateHook($params, $time = null) {
+		if ($time === null) {
+			$time = time();
+		}
+		$users = $params[Filesystem::signal_param_users];
+		$type = $params[Filesystem::signal_param_mount_type];
+		$mountPoint = $params[Filesystem::signal_param_path];
+		if ($type === \OC_Mount_Config::MOUNT_TYPE_GROUP or $users === 'all') {
+			$this->markDirty($mountPoint, $time);
+		} else {
+			$this->changePropagator->addChange($mountPoint);
+			$this->changePropagator->propagateChanges($time);
+		}
+	}
+}
diff --git a/apps/files_external/tests/etagpropagator.php b/apps/files_external/tests/etagpropagator.php
new file mode 100644
index 0000000..7fa1863
--- /dev/null
+++ b/apps/files_external/tests/etagpropagator.php
@@ -0,0 +1,328 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind at owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Tests\Files_External;
+
+use OC\Files\Filesystem;
+use OC\User\User;
+
+class EtagPropagator extends \PHPUnit_Framework_TestCase {
+	protected function getUser() {
+		return new User(uniqid(), null);
+	}
+
+	/**
+	 * @return \PHPUnit_Framework_MockObject_MockObject | \OC\Files\Cache\ChangePropagator
+	 */
+	protected function getChangePropagator() {
+		return $this->getMockBuilder('\OC\Files\Cache\ChangePropagator')
+			->disableOriginalConstructor()
+			->getMock();
+	}
+
+	/**
+	 * @return \PHPUnit_Framework_MockObject_MockObject | \OCP\IConfig
+	 */
+	protected function getConfig() {
+		$appConfig = array();
+		$userConfig = array();
+		$mock = $this->getMockBuilder('\OCP\IConfig')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$mock->expects($this->any())
+			->method('getAppValue')
+			->will($this->returnCallback(function ($appId, $key, $default = null) use (&$appConfig) {
+				if (isset($appConfig[$appId]) and isset($appConfig[$appId][$key])) {
+					return $appConfig[$appId][$key];
+				} else {
+					return $default;
+				}
+			}));
+		$mock->expects($this->any())
+			->method('setAppValue')
+			->will($this->returnCallback(function ($appId, $key, $value) use (&$appConfig) {
+				if (!isset($appConfig[$appId])) {
+					$appConfig[$appId] = array();
+				}
+				$appConfig[$appId][$key] = $value;
+			}));
+		$mock->expects($this->any())
+			->method('getAppKeys')
+			->will($this->returnCallback(function ($appId) use (&$appConfig) {
+				if (!isset($appConfig[$appId])) {
+					$appConfig[$appId] = array();
+				}
+				return array_keys($appConfig[$appId]);
+			}));
+
+		$mock->expects($this->any())
+			->method('getUserValue')
+			->will($this->returnCallback(function ($userId, $appId, $key, $default = null) use (&$userConfig) {
+				if (isset($userConfig[$userId]) and isset($userConfig[$userId][$appId]) and isset($userConfig[$userId][$appId][$key])) {
+					return $userConfig[$userId][$appId][$key];
+				} else {
+					return $default;
+				}
+			}));
+		$mock->expects($this->any())
+			->method('setUserValue')
+			->will($this->returnCallback(function ($userId, $appId, $key, $value) use (&$userConfig) {
+				if (!isset($userConfig[$userId])) {
+					$userConfig[$userId] = array();
+				}
+				if (!isset($userConfig[$userId][$appId])) {
+					$userConfig[$userId][$appId] = array();
+				}
+				$userConfig[$userId][$appId][$key] = $value;
+			}));
+
+		return $mock;
+	}
+
+	public function testSingleUserMount() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$changePropagator->expects($this->once())
+			->method('addChange')
+			->with('/test');
+		$changePropagator->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator->updateHook(array(
+			Filesystem::signal_param_path => '/test',
+			Filesystem::signal_param_mount_type => \OC_Mount_Config::MOUNT_TYPE_USER,
+			Filesystem::signal_param_users => $user->getUID(),
+		), $time);
+	}
+
+	public function testGlobalMountNoDirectUpdate() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		// not updated directly
+		$changePropagator->expects($this->never())
+			->method('addChange');
+		$changePropagator->expects($this->never())
+			->method('propagateChanges');
+
+		$propagator->updateHook(array(
+			Filesystem::signal_param_path => '/test',
+			Filesystem::signal_param_mount_type => \OC_Mount_Config::MOUNT_TYPE_USER,
+			Filesystem::signal_param_users => 'all',
+		), $time);
+
+		// mount point marked as dirty
+		$this->assertEquals(array('/test'), $config->getAppKeys('files_external'));
+		$this->assertEquals($time, $config->getAppValue('files_external', '/test'));
+	}
+
+	public function testGroupMountNoDirectUpdate() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		// not updated directly
+		$changePropagator->expects($this->never())
+			->method('addChange');
+		$changePropagator->expects($this->never())
+			->method('propagateChanges');
+
+		$propagator->updateHook(array(
+			Filesystem::signal_param_path => '/test',
+			Filesystem::signal_param_mount_type => \OC_Mount_Config::MOUNT_TYPE_GROUP,
+			Filesystem::signal_param_users => 'test',
+		), $time);
+
+		// mount point marked as dirty
+		$this->assertEquals(array('/test'), $config->getAppKeys('files_external'));
+		$this->assertEquals($time, $config->getAppValue('files_external', '/test'));
+	}
+
+	public function testGlobalMountNoDirtyMountPoint() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$changePropagator->expects($this->never())
+			->method('addChange');
+		$changePropagator->expects($this->never())
+			->method('propagateChanges');
+
+		$propagator->propagateDirtyMountPoints($time);
+
+		$this->assertEquals(0, $config->getUserValue($user->getUID(), 'files_external', '/test', 0));
+	}
+
+	public function testGlobalMountDirtyMountPointFirstTime() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$config->setAppValue('files_external', '/test', $time - 10);
+
+		$changePropagator->expects($this->once())
+			->method('addChange')
+			->with('/test');
+		$changePropagator->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
+	}
+
+	public function testGlobalMountNonDirtyMountPoint() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$config->setAppValue('files_external', '/test', $time - 10);
+		$config->setUserValue($user->getUID(), 'files_external', '/test', $time - 10);
+
+		$changePropagator->expects($this->never())
+			->method('addChange');
+		$changePropagator->expects($this->never())
+			->method('propagateChanges');
+
+		$propagator->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time - 10, $config->getUserValue($user->getUID(), 'files_external', '/test'));
+	}
+
+	public function testGlobalMountNonDirtyMountPointOtherUser() {
+		$time = time();
+		$user = $this->getUser();
+		$user2 = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$config->setAppValue('files_external', '/test', $time - 10);
+		$config->setUserValue($user2->getUID(), 'files_external', '/test', $time - 10);
+
+		$changePropagator->expects($this->once())
+			->method('addChange')
+			->with('/test');
+		$changePropagator->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
+	}
+
+	public function testGlobalMountDirtyMountPointSecondTime() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$config->setAppValue('files_external', '/test', $time - 10);
+		$config->setUserValue($user->getUID(), 'files_external', '/test', $time - 20);
+
+		$changePropagator->expects($this->once())
+			->method('addChange')
+			->with('/test');
+		$changePropagator->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
+	}
+
+	public function testGlobalMountMultipleUsers() {
+		$time = time();
+		$config = $this->getConfig();
+		$user1 = $this->getUser();
+		$user2 = $this->getUser();
+		$user3 = $this->getUser();
+		$changePropagator1 = $this->getChangePropagator();
+		$changePropagator2 = $this->getChangePropagator();
+		$changePropagator3 = $this->getChangePropagator();
+		$propagator1 = new \OCA\Files_External\EtagPropagator($user1, $changePropagator1, $config);
+		$propagator2 = new \OCA\Files_External\EtagPropagator($user2, $changePropagator2, $config);
+		$propagator3 = new \OCA\Files_External\EtagPropagator($user3, $changePropagator3, $config);
+
+		$config->setAppValue('files_external', '/test', $time - 10);
+
+		$changePropagator1->expects($this->once())
+			->method('addChange')
+			->with('/test');
+		$changePropagator1->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator1->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time, $config->getUserValue($user1->getUID(), 'files_external', '/test'));
+		$this->assertEquals(0, $config->getUserValue($user2->getUID(), 'files_external', '/test', 0));
+		$this->assertEquals(0, $config->getUserValue($user3->getUID(), 'files_external', '/test', 0));
+
+		$changePropagator2->expects($this->once())
+			->method('addChange')
+			->with('/test');
+		$changePropagator2->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator2->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time, $config->getUserValue($user1->getUID(), 'files_external', '/test'));
+		$this->assertEquals($time, $config->getUserValue($user2->getUID(), 'files_external', '/test', 0));
+		$this->assertEquals(0, $config->getUserValue($user3->getUID(), 'files_external', '/test', 0));
+	}
+
+	public function testGlobalMountMultipleDirtyMountPoints() {
+		$time = time();
+		$user = $this->getUser();
+		$config = $this->getConfig();
+		$changePropagator = $this->getChangePropagator();
+		$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
+
+		$config->setAppValue('files_external', '/test', $time - 10);
+		$config->setAppValue('files_external', '/foo', $time - 50);
+		$config->setAppValue('files_external', '/bar', $time - 70);
+
+		$config->setUserValue($user->getUID(), 'files_external', '/foo', $time - 70);
+		$config->setUserValue($user->getUID(), 'files_external', '/bar', $time - 70);
+
+		$changePropagator->expects($this->exactly(2))
+			->method('addChange');
+		$changePropagator->expects($this->once())
+			->method('propagateChanges')
+			->with($time);
+
+		$propagator->propagateDirtyMountPoints($time);
+
+		$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
+		$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/foo'));
+		$this->assertEquals($time - 70, $config->getUserValue($user->getUID(), 'files_external', '/bar'));
+	}
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git



More information about the Pkg-owncloud-commits mailing list