Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorris Jobke <morris.jobke@gmail.com>2013-11-11 18:16:51 +0400
committerMorris Jobke <morris.jobke@gmail.com>2013-11-11 18:16:51 +0400
commit55331479cdd607089ad898676bedc84ea66cafce (patch)
treea360b9aef4cdb100edd58d0db78144e75c3714dd
parente431ba5ce8b9c340ba123a221342d0b1398e2b69 (diff)
parentda126f1692cffa30817f99e0d23fa25db6952801 (diff)
Merge pull request #5701 from owncloud/sharing-updateownerfoldersizes
Fixed watcher to also update the owner's folder sizes
-rw-r--r--apps/files_sharing/lib/sharedstorage.php4
-rw-r--r--apps/files_sharing/lib/watcher.php27
-rw-r--r--apps/files_sharing/tests/api.php111
-rw-r--r--apps/files_sharing/tests/base.php143
-rw-r--r--apps/files_sharing/tests/watcher.php161
-rw-r--r--lib/private/files/cache/watcher.php9
6 files changed, 341 insertions, 114 deletions
diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php
index 257da89c84e..6141d832199 100644
--- a/apps/files_sharing/lib/sharedstorage.php
+++ b/apps/files_sharing/lib/sharedstorage.php
@@ -43,7 +43,7 @@ class Shared extends \OC\Files\Storage\Common {
* @param string Shared target file path
* @return Returns array with the keys path, permissions, and owner or false if not found
*/
- private function getFile($target) {
+ public function getFile($target) {
if (!isset($this->files[$target])) {
// Check for partial files
if (pathinfo($target, PATHINFO_EXTENSION) === 'part') {
@@ -66,7 +66,7 @@ class Shared extends \OC\Files\Storage\Common {
* @param string Shared target file path
* @return string source file path or false if not found
*/
- private function getSourcePath($target) {
+ public function getSourcePath($target) {
$source = $this->getFile($target);
if ($source) {
if (!isset($source['fullPath'])) {
diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php
index 6fdfc1db36d..c40cf6911b8 100644
--- a/apps/files_sharing/lib/watcher.php
+++ b/apps/files_sharing/lib/watcher.php
@@ -32,9 +32,32 @@ class Shared_Watcher extends Watcher {
* @param string $path
*/
public function checkUpdate($path) {
- if ($path != '') {
- parent::checkUpdate($path);
+ if ($path != '' && parent::checkUpdate($path)) {
+ // since checkUpdate() 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;
}
+ return false;
}
/**
diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php
index 44fc4d8b7b3..1278e0c4d1f 100644
--- a/apps/files_sharing/tests/api.php
+++ b/apps/files_sharing/tests/api.php
@@ -20,90 +20,33 @@
*
*/
-require_once __DIR__ . '/../../../lib/base.php';
+require_once __DIR__ . '/base.php';
use OCA\Files\Share;
/**
* Class Test_Files_Sharing_Api
*/
-class Test_Files_Sharing_Api extends \PHPUnit_Framework_TestCase {
-
- const TEST_FILES_SHARING_API_USER1 = "test-share-user1";
- const TEST_FILES_SHARING_API_USER2 = "test-share-user2";
- const TEST_FILES_SHARING_API_USER3 = "test-share-user3";
-
- public $stateFilesEncryption;
- public $filename;
- public $data;
- /**
- * @var OC_FilesystemView
- */
- public $view;
- public $folder;
-
- public static function setUpBeforeClass() {
- // reset backend
- \OC_User::clearBackends();
- \OC_User::useBackend('database');
-
- // clear share hooks
- \OC_Hook::clear('OCP\\Share');
- \OC::registerShareHooks();
- \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
-
- // create users
- self::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1, true);
- self::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, true);
- self::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER3, true);
-
- }
+class Test_Files_Sharing_Api extends Test_Files_Sharing_Base {
function setUp() {
-
- //login as user1
- \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1);
-
- $this->data = 'foobar';
- $this->view = new \OC_FilesystemView('/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1 . '/files');
+ parent::setUp();
$this->folder = '/folder_share_api_test';
$this->filename = 'share-api-test.txt';
- // remember files_encryption state
- $this->stateFilesEncryption = \OC_App::isEnabled('files_encryption');
-
- //we don't want to tests with app files_encryption enabled
- \OC_App::disable('files_encryption');
-
-
- $this->assertTrue(!\OC_App::isEnabled('files_encryption'));
-
// save file with content
$this->view->file_put_contents($this->filename, $this->data);
$this->view->mkdir($this->folder);
$this->view->file_put_contents($this->folder.'/'.$this->filename, $this->data);
-
}
function tearDown() {
$this->view->unlink($this->filename);
$this->view->deleteAll($this->folder);
- // reset app files_encryption
- if ($this->stateFilesEncryption) {
- \OC_App::enable('files_encryption');
- } else {
- \OC_App::disable('files_encryption');
- }
- }
-
- public static function tearDownAfterClass() {
- // cleanup users
- \OC_User::deleteUser(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1);
- \OC_User::deleteUser(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2);
- \OC_User::deleteUser(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER3);
+ parent::tearDown();
}
/**
@@ -548,50 +491,4 @@ class Test_Files_Sharing_Api extends \PHPUnit_Framework_TestCase {
$this->assertTrue(empty($itemsAfterDelete));
}
-
- /**
- * @param $user
- * @param bool $create
- * @param bool $password
- */
- private static function loginHelper($user, $create = false, $password = false) {
- if ($create) {
- \OC_User::createUser($user, $user);
- }
-
- if ($password === false) {
- $password = $user;
- }
-
- \OC_Util::tearDownFS();
- \OC_User::setUserId('');
- \OC\Files\Filesystem::tearDown();
- \OC_Util::setupFS($user);
- \OC_User::setUserId($user);
-
- $params['uid'] = $user;
- $params['password'] = $password;
- }
-
- /**
- * @brief get some information from a given share
- * @param int $shareID
- * @return array with: item_source, share_type, share_with, item_type, permissions
- */
- private function getShareFromId($shareID) {
- $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?';
- $args = array($shareID);
- $query = \OCP\DB::prepare($sql);
- $result = $query->execute($args);
-
- $share = Null;
-
- if ($result && $result->numRows() > 0) {
- $share = $result->fetchRow();
- }
-
- return $share;
-
- }
-
}
diff --git a/apps/files_sharing/tests/base.php b/apps/files_sharing/tests/base.php
new file mode 100644
index 00000000000..689c80cb9e6
--- /dev/null
+++ b/apps/files_sharing/tests/base.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bjoern Schiessle
+ * @copyright 2013 Bjoern Schiessle <schiessle@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+require_once __DIR__ . '/../../../lib/base.php';
+
+use OCA\Files\Share;
+
+/**
+ * Class Test_Files_Sharing_Base
+ *
+ * Base class for sharing tests.
+ */
+abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase {
+
+ const TEST_FILES_SHARING_API_USER1 = "test-share-user1";
+ const TEST_FILES_SHARING_API_USER2 = "test-share-user2";
+ const TEST_FILES_SHARING_API_USER3 = "test-share-user3";
+
+ public $stateFilesEncryption;
+ public $filename;
+ public $data;
+ /**
+ * @var OC_FilesystemView
+ */
+ public $view;
+ public $folder;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // clear share hooks
+ \OC_Hook::clear('OCP\\Share');
+ \OC::registerShareHooks();
+ \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
+
+ // create users
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1, true);
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER2, true);
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER3, true);
+
+ }
+
+ function setUp() {
+
+ //login as user1
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ $this->data = 'foobar';
+ $this->view = new \OC_FilesystemView('/' . self::TEST_FILES_SHARING_API_USER1 . '/files');
+ // remember files_encryption state
+ $this->stateFilesEncryption = \OC_App::isEnabled('files_encryption');
+
+ //we don't want to tests with app files_encryption enabled
+ \OC_App::disable('files_encryption');
+
+
+ $this->assertTrue(!\OC_App::isEnabled('files_encryption'));
+ }
+
+ function tearDown() {
+ // reset app files_encryption
+ if ($this->stateFilesEncryption) {
+ \OC_App::enable('files_encryption');
+ } else {
+ \OC_App::disable('files_encryption');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+
+ // cleanup users
+ \OC_User::deleteUser(self::TEST_FILES_SHARING_API_USER1);
+ \OC_User::deleteUser(self::TEST_FILES_SHARING_API_USER2);
+ \OC_User::deleteUser(self::TEST_FILES_SHARING_API_USER3);
+ }
+
+ /**
+ * @param $user
+ * @param bool $create
+ * @param bool $password
+ */
+ protected static function loginHelper($user, $create = false, $password = false) {
+ if ($create) {
+ \OC_User::createUser($user, $user);
+ }
+
+ if ($password === false) {
+ $password = $user;
+ }
+
+ \OC_Util::tearDownFS();
+ \OC_User::setUserId('');
+ \OC\Files\Filesystem::tearDown();
+ \OC_Util::setupFS($user);
+ \OC_User::setUserId($user);
+
+ $params['uid'] = $user;
+ $params['password'] = $password;
+ }
+
+ /**
+ * @brief get some information from a given share
+ * @param int $shareID
+ * @return array with: item_source, share_type, share_with, item_type, permissions
+ */
+ protected function getShareFromId($shareID) {
+ $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?';
+ $args = array($shareID);
+ $query = \OCP\DB::prepare($sql);
+ $result = $query->execute($args);
+
+ $share = Null;
+
+ if ($result && $result->numRows() > 0) {
+ $share = $result->fetchRow();
+ }
+
+ return $share;
+
+ }
+
+}
diff --git a/apps/files_sharing/tests/watcher.php b/apps/files_sharing/tests/watcher.php
new file mode 100644
index 00000000000..1a9a54cbcf8
--- /dev/null
+++ b/apps/files_sharing/tests/watcher.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Vincent Petry
+ * @copyright 2013 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+require_once __DIR__ . '/base.php';
+
+class Test_Files_Sharing_Watcher extends Test_Files_Sharing_Base {
+
+ function setUp() {
+ parent::setUp();
+
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ // prepare user1's dir structure
+ $textData = "dummy file data\n";
+ $this->view->mkdir('container');
+ $this->view->mkdir('container/shareddir');
+ $this->view->mkdir('container/shareddir/subdir');
+
+ list($this->ownerStorage, $internalPath) = $this->view->resolvePath('');
+ $this->ownerCache = $this->ownerStorage->getCache();
+ $this->ownerStorage->getScanner()->scan('');
+
+ // share "shareddir" with user2
+ $fileinfo = $this->view->getFileInfo('container/shareddir');
+ \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2, 31);
+
+ // login as user2
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
+
+ // retrieve the shared storage
+ $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2);
+ list($this->sharedStorage, $internalPath) = $secondView->resolvePath('files/Shared/shareddir');
+ $this->sharedCache = $this->sharedStorage->getCache();
+ }
+
+ function tearDown() {
+ $this->sharedCache->clear();
+
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ $fileinfo = $this->view->getFileInfo('container/shareddir');
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2);
+
+ $this->view->deleteAll('container');
+
+ $this->ownerCache->clear();
+
+ parent::tearDown();
+ }
+
+ /**
+ * Tests that writing a file using the shared storage will propagate the file
+ * size to the owner's parent folders.
+ */
+ function testFolderSizePropagationToOwnerStorage() {
+ $initialSizes = self::getOwnerDirSizes('files/container/shareddir');
+
+ $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $dataLen = strlen($textData);
+ $this->sharedCache->put('shareddir/bar.txt', array('storage_mtime' => 10));
+ $this->sharedStorage->file_put_contents('shareddir/bar.txt', $textData);
+ $this->sharedCache->put('shareddir', array('storage_mtime' => 10));
+
+ // run the propagation code
+ $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir');
+
+ $this->assertTrue($result);
+
+ // the owner's parent dirs must have increase size
+ $newSizes = self::getOwnerDirSizes('files/container/shareddir');
+ $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']);
+ $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']);
+ $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']);
+ $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']);
+
+ // no more updates
+ $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir');
+
+ $this->assertFalse($result);
+ }
+
+ /**
+ * Tests that writing a file using the shared storage will propagate the file
+ * size to the owner's parent folders.
+ */
+ function testSubFolderSizePropagationToOwnerStorage() {
+ $initialSizes = self::getOwnerDirSizes('files/container/shareddir/subdir');
+
+ $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $dataLen = strlen($textData);
+ $this->sharedCache->put('shareddir/subdir/bar.txt', array('storage_mtime' => 10));
+ $this->sharedStorage->file_put_contents('shareddir/subdir/bar.txt', $textData);
+ $this->sharedCache->put('shareddir/subdir', array('storage_mtime' => 10));
+
+ // run the propagation code
+ $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir/subdir');
+
+ $this->assertTrue($result);
+
+ // the owner's parent dirs must have increase size
+ $newSizes = self::getOwnerDirSizes('files/container/shareddir/subdir');
+ $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']);
+ $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']);
+ $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']);
+ $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']);
+ $this->assertEquals($initialSizes['files/container/shareddir/subdir'] + $dataLen, $newSizes['files/container/shareddir/subdir']);
+
+ // no more updates
+ $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir/subdir');
+
+ $this->assertFalse($result);
+ }
+
+ function testNoUpdateOnRoot() {
+ // no updates when called for root path
+ $result = $this->sharedStorage->getWatcher()->checkUpdate('');
+
+ $this->assertFalse($result);
+
+ // FIXME: for some reason when running this "naked" test,
+ // there will be remaining nonsensical entries in the
+ // database with a path "test-share-user1/container/..."
+ }
+
+ /**
+ * Returns the sizes of the path and its parent dirs in a hash
+ * where the key is the path and the value is the size.
+ */
+ function getOwnerDirSizes($path) {
+ $result = array();
+
+ while ($path != '' && $path != '' && $path != '.') {
+ $cachedData = $this->ownerCache->get($path);
+ $result[$path] = $cachedData['size'];
+ $path = dirname($path);
+ }
+ $cachedData = $this->ownerCache->get('');
+ $result[''] = $cachedData['size'];
+ return $result;
+ }
+}
diff --git a/lib/private/files/cache/watcher.php b/lib/private/files/cache/watcher.php
index 8bfd4602f3a..58f624c8990 100644
--- a/lib/private/files/cache/watcher.php
+++ b/lib/private/files/cache/watcher.php
@@ -15,17 +15,17 @@ class Watcher {
/**
* @var \OC\Files\Storage\Storage $storage
*/
- private $storage;
+ protected $storage;
/**
* @var Cache $cache
*/
- private $cache;
+ protected $cache;
/**
* @var Scanner $scanner;
*/
- private $scanner;
+ protected $scanner;
/**
* @param \OC\Files\Storage\Storage $storage
@@ -40,6 +40,7 @@ class Watcher {
* check $path for updates
*
* @param string $path
+ * @return boolean true if path was updated, false otherwise
*/
public function checkUpdate($path) {
$cachedEntry = $this->cache->get($path);
@@ -53,7 +54,9 @@ class Watcher {
$this->cleanFolder($path);
}
$this->cache->correctFolderSize($path);
+ return true;
}
+ return false;
}
/**