Merge pull request #20768 from owncloud/mount-cache
cache mountpoints in the db
This commit is contained in:
commit
1410120758
|
@ -26,6 +26,7 @@
|
|||
namespace OCA\Files_External\AppInfo;
|
||||
|
||||
use \OCP\AppFramework\App;
|
||||
use OCP\AppFramework\IAppContainer;
|
||||
use \OCP\IContainer;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
|
||||
|
@ -33,9 +34,13 @@ use \OCA\Files_External\Service\BackendService;
|
|||
* @package OCA\Files_External\Appinfo
|
||||
*/
|
||||
class Application extends App {
|
||||
public function __construct(array $urlParams=array()) {
|
||||
public function __construct(array $urlParams = array()) {
|
||||
parent::__construct('files_external', $urlParams);
|
||||
|
||||
$this->getContainer()->registerService('OCP\Files\Config\IUserMountCache', function (IAppContainer $c) {
|
||||
return $c->getServer()->query('UserMountCache');
|
||||
});
|
||||
|
||||
$this->loadBackends();
|
||||
$this->loadAuthMechanisms();
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ use OCA\Files_external\Service\LegacyStoragesService;
|
|||
use OCA\Files_external\Service\StoragesService;
|
||||
use OCA\Files_external\Service\UserLegacyStoragesService;
|
||||
use OCA\Files_external\Service\UserStoragesService;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\ILogger;
|
||||
|
@ -64,6 +65,9 @@ class StorageMigrator {
|
|||
*/
|
||||
private $logger;
|
||||
|
||||
/** @var IUserMountCache */
|
||||
private $userMountCache;
|
||||
|
||||
/**
|
||||
* StorageMigrator constructor.
|
||||
*
|
||||
|
@ -72,19 +76,22 @@ class StorageMigrator {
|
|||
* @param IConfig $config
|
||||
* @param IDBConnection $connection
|
||||
* @param ILogger $logger
|
||||
* @param IUserMountCache $userMountCache
|
||||
*/
|
||||
public function __construct(
|
||||
BackendService $backendService,
|
||||
DBConfigService $dbConfig,
|
||||
IConfig $config,
|
||||
IDBConnection $connection,
|
||||
ILogger $logger
|
||||
ILogger $logger,
|
||||
IUserMountCache $userMountCache
|
||||
) {
|
||||
$this->backendService = $backendService;
|
||||
$this->dbConfig = $dbConfig;
|
||||
$this->config = $config;
|
||||
$this->connection = $connection;
|
||||
$this->logger = $logger;
|
||||
$this->userMountCache = $userMountCache;
|
||||
}
|
||||
|
||||
private function migrate(LegacyStoragesService $legacyService, StoragesService $storageService) {
|
||||
|
@ -107,7 +114,7 @@ class StorageMigrator {
|
|||
*/
|
||||
public function migrateGlobal() {
|
||||
$legacyService = new GlobalLegacyStoragesService($this->backendService);
|
||||
$storageService = new GlobalStoragesService($this->backendService, $this->dbConfig);
|
||||
$storageService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->userMountCache);
|
||||
|
||||
$this->migrate($legacyService, $storageService);
|
||||
}
|
||||
|
@ -125,7 +132,7 @@ class StorageMigrator {
|
|||
if (version_compare($userVersion, '0.5.0', '<')) {
|
||||
$this->config->setUserValue($userId, 'files_external', 'config_version', '0.5.0');
|
||||
$legacyService = new UserLegacyStoragesService($this->backendService, $dummySession);
|
||||
$storageService = new UserStoragesService($this->backendService, $this->dbConfig, $dummySession);
|
||||
$storageService = new UserStoragesService($this->backendService, $this->dbConfig, $dummySession, $this->userMountCache);
|
||||
|
||||
$this->migrate($legacyService, $storageService);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ use \OCA\Files_external\Lib\StorageConfig;
|
|||
use \OCA\Files_external\NotFoundException;
|
||||
use \OCA\Files_External\Lib\Backend\Backend;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use \OCP\Files\StorageNotAvailableException;
|
||||
|
||||
/**
|
||||
|
@ -46,13 +47,20 @@ abstract class StoragesService {
|
|||
*/
|
||||
protected $dbConfig;
|
||||
|
||||
/**
|
||||
* @var IUserMountCache
|
||||
*/
|
||||
protected $userMountCache;
|
||||
|
||||
/**
|
||||
* @param BackendService $backendService
|
||||
* @param DBConfigService $dbConfigService
|
||||
* @param IUserMountCache $userMountCache
|
||||
*/
|
||||
public function __construct(BackendService $backendService, DBConfigService $dbConfigService) {
|
||||
public function __construct(BackendService $backendService, DBConfigService $dbConfigService, IUserMountCache $userMountCache) {
|
||||
$this->backendService = $backendService;
|
||||
$this->dbConfig = $dbConfigService;
|
||||
$this->userMountCache = $userMountCache;
|
||||
}
|
||||
|
||||
protected function readDBConfig() {
|
||||
|
@ -416,6 +424,15 @@ abstract class StoragesService {
|
|||
|
||||
$this->triggerChangeHooks($oldStorage, $updatedStorage);
|
||||
|
||||
if (($wasGlobal && !$isGlobal) || count($removedGroups) > 0) { // to expensive to properly handle these on the fly
|
||||
$this->userMountCache->remoteStorageMounts($this->getStorageId($updatedStorage));
|
||||
} else {
|
||||
$storageId = $this->getStorageId($updatedStorage);
|
||||
foreach ($removedUsers as $userId) {
|
||||
$this->userMountCache->removeUserStorageMount($storageId, $userId);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getStorage($id);
|
||||
}
|
||||
|
||||
|
@ -480,4 +497,25 @@ abstract class StoragesService {
|
|||
return $storageImpl->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the storage implementation
|
||||
*
|
||||
* @param StorageConfig $storageConfig
|
||||
* @return int
|
||||
*/
|
||||
private function getStorageId(StorageConfig $storageConfig) {
|
||||
try {
|
||||
$class = $storageConfig->getBackend()->getStorageClass();
|
||||
/** @var \OC\Files\Storage\Storage $storage */
|
||||
$storage = new $class($storageConfig->getBackendOptions());
|
||||
|
||||
// auth mechanism should fire first
|
||||
$storage = $storageConfig->getBackend()->wrapStorage($storage);
|
||||
$storage = $storageConfig->getAuthMechanism()->wrapStorage($storage);
|
||||
|
||||
return $storage->getStorageCache()->getNumericId();
|
||||
} catch (\Exception $e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace OCA\Files_External\Service;
|
|||
|
||||
use \OCA\Files_external\Service\GlobalStoragesService;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use \OCP\IUserSession;
|
||||
use \OCP\IGroupManager;
|
||||
use \OCA\Files_External\Service\UserTrait;
|
||||
|
@ -46,14 +47,16 @@ class UserGlobalStoragesService extends GlobalStoragesService {
|
|||
* @param DBConfigService $dbConfig
|
||||
* @param IUserSession $userSession
|
||||
* @param IGroupManager $groupManager
|
||||
* @param IUserMountCache $userMountCache
|
||||
*/
|
||||
public function __construct(
|
||||
BackendService $backendService,
|
||||
DBConfigService $dbConfig,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager
|
||||
IGroupManager $groupManager,
|
||||
IUserMountCache $userMountCache
|
||||
) {
|
||||
parent::__construct($backendService, $dbConfig);
|
||||
parent::__construct($backendService, $dbConfig, $userMountCache);
|
||||
$this->userSession = $userSession;
|
||||
$this->groupManager = $groupManager;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
namespace OCA\Files_external\Service;
|
||||
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use \OCP\IUserSession;
|
||||
use \OC\Files\Filesystem;
|
||||
|
||||
|
@ -44,14 +45,16 @@ class UserStoragesService extends StoragesService {
|
|||
* @param BackendService $backendService
|
||||
* @param DBConfigService $dbConfig
|
||||
* @param IUserSession $userSession user session
|
||||
* @param IUserMountCache $userMountCache
|
||||
*/
|
||||
public function __construct(
|
||||
BackendService $backendService,
|
||||
DBConfigService $dbConfig,
|
||||
IUserSession $userSession
|
||||
IUserSession $userSession,
|
||||
IUserMountCache $userMountCache
|
||||
) {
|
||||
$this->userSession = $userSession;
|
||||
parent::__construct($backendService, $dbConfig);
|
||||
parent::__construct($backendService, $dbConfig, $userMountCache);
|
||||
}
|
||||
|
||||
protected function readDBConfig() {
|
||||
|
|
|
@ -34,7 +34,7 @@ use \OCA\Files_external\Lib\StorageConfig;
|
|||
class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig);
|
||||
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
|
|
|
@ -76,6 +76,11 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
|||
*/
|
||||
protected static $hookCalls;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\OCP\Files\Config\IUserMountCache
|
||||
*/
|
||||
protected $mountCache;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->dbConfig = new CleaningDBConfig(\OC::$server->getDatabaseConnection());
|
||||
|
@ -87,6 +92,8 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
|||
);
|
||||
\OC_Mount_Config::$skipTest = true;
|
||||
|
||||
$this->mountCache = $this->getMock('OCP\Files\Config\IUserMountCache');
|
||||
|
||||
// prepare BackendService mock
|
||||
$this->backendService =
|
||||
$this->getMockBuilder('\OCA\Files_External\Service\BackendService')
|
||||
|
|
|
@ -94,7 +94,8 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
|||
$this->backendService,
|
||||
$this->dbConfig,
|
||||
$userSession,
|
||||
$this->groupManager
|
||||
$this->groupManager,
|
||||
$this->mountCache
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
|||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig);
|
||||
$this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache);
|
||||
|
||||
$this->userId = $this->getUniqueID('user_');
|
||||
$this->createUser($this->userId, $this->userId);
|
||||
|
@ -62,7 +62,7 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
|||
->method('getUser')
|
||||
->will($this->returnValue($this->user));
|
||||
|
||||
$this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession);
|
||||
$this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache);
|
||||
}
|
||||
|
||||
private function makeTestStorageData() {
|
||||
|
|
|
@ -127,6 +127,93 @@
|
|||
|
||||
</table>
|
||||
|
||||
<!-- a list of all mounted storage per user, populated on filesystem setup -->
|
||||
<table>
|
||||
|
||||
<name>*dbprefix*mounts</name>
|
||||
|
||||
<declaration>
|
||||
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>storage_id</name>
|
||||
<type>integer</type>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<!-- fileid of the root of the mount, foreign key: oc_filecache.fileid -->
|
||||
<field>
|
||||
<name>root_id</name>
|
||||
<type>integer</type>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>mount_point</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>4000</length>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>mounts_user_index</name>
|
||||
<unique>false</unique>
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
<index>
|
||||
<name>mounts_storage_index</name>
|
||||
<unique>false</unique>
|
||||
<field>
|
||||
<name>storage_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
<index>
|
||||
<name>mounts_root_index</name>
|
||||
<unique>false</unique>
|
||||
<field>
|
||||
<name>root_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
<index>
|
||||
<name>mounts_user_root_index</name>
|
||||
<unique>true</unique>
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
<field>
|
||||
<name>root_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
</declaration>
|
||||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Files\Config;
|
||||
|
||||
use OC\Files\Filesystem;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\Files\Node;
|
||||
use OCP\IUser;
|
||||
|
||||
class CachedMountInfo implements ICachedMountInfo {
|
||||
/**
|
||||
* @var IUser
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $storageId;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $rootId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $mountPoint;
|
||||
|
||||
/**
|
||||
* CachedMountInfo constructor.
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param int $storageId
|
||||
* @param int $rootId
|
||||
* @param string $mountPoint
|
||||
*/
|
||||
public function __construct(IUser $user, $storageId, $rootId, $mountPoint) {
|
||||
$this->user = $user;
|
||||
$this->storageId = $storageId;
|
||||
$this->rootId = $rootId;
|
||||
$this->mountPoint = $mountPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IUser
|
||||
*/
|
||||
public function getUser() {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int the numeric storage id of the mount
|
||||
*/
|
||||
public function getStorageId() {
|
||||
return $this->storageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int the fileid of the root of the mount
|
||||
*/
|
||||
public function getRootId() {
|
||||
return $this->rootId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node the root node of the mount
|
||||
*/
|
||||
public function getMountPointNode() {
|
||||
// TODO injection etc
|
||||
Filesystem::initMountPoints($this->user->getUID());
|
||||
$userNode = \OC::$server->getUserFolder($this->user->getUID());
|
||||
$nodes = $userNode->getById($this->rootId);
|
||||
if (count($nodes) > 0) {
|
||||
return $nodes[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the mount point of the mount for the user
|
||||
*/
|
||||
public function getMountPoint() {
|
||||
return $this->mountPoint;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@ use OC\Hooks\Emitter;
|
|||
use OC\Hooks\EmitterTrait;
|
||||
use OCP\Files\Config\IMountProviderCollection;
|
||||
use OCP\Files\Config\IMountProvider;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCP\IUser;
|
||||
|
||||
|
@ -43,10 +45,17 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
private $loader;
|
||||
|
||||
/**
|
||||
* @param \OCP\Files\Storage\IStorageFactory $loader
|
||||
* @var \OCP\Files\Config\IUserMountCache
|
||||
*/
|
||||
public function __construct(IStorageFactory $loader) {
|
||||
private $mountCache;
|
||||
|
||||
/**
|
||||
* @param \OCP\Files\Storage\IStorageFactory $loader
|
||||
* @param IUserMountCache $mountCache
|
||||
*/
|
||||
public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) {
|
||||
$this->loader = $loader;
|
||||
$this->mountCache = $mountCache;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,4 +86,23 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
$this->providers[] = $provider;
|
||||
$this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache mounts for user
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param IMountPoint[] $mountPoints
|
||||
*/
|
||||
public function registerMounts(IUser $user, array $mountPoints) {
|
||||
$this->mountCache->registerMounts($user, $mountPoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mount cache which can be used to search for mounts without setting up the filesystem
|
||||
*
|
||||
* @return IUserMountCache
|
||||
*/
|
||||
public function getMountCache() {
|
||||
return $this->mountCache;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Files\Config;
|
||||
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\ICache;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\ILogger;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
|
||||
/**
|
||||
* Cache mounts points per user in the cache so we can easilly look them up
|
||||
*/
|
||||
class UserMountCache implements IUserMountCache {
|
||||
/**
|
||||
* @var IDBConnection
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* @var IUserManager
|
||||
*/
|
||||
private $userManager;
|
||||
|
||||
/** @var ICachedMountInfo[][] [$userId => [$cachedMountInfo, ....], ...] */
|
||||
private $mountsForUsers = [];
|
||||
|
||||
/**
|
||||
* @var ILogger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* UserMountCache constructor.
|
||||
*
|
||||
* @param IDBConnection $connection
|
||||
* @param IUserManager $userManager
|
||||
* @param ILogger $logger
|
||||
*/
|
||||
public function __construct(IDBConnection $connection, IUserManager $userManager, ILogger $logger) {
|
||||
$this->connection = $connection;
|
||||
$this->userManager = $userManager;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function registerMounts(IUser $user, array $mounts) {
|
||||
// filter out non-proper storages coming from unit tests
|
||||
$mounts = array_filter($mounts, function (IMountPoint $mount) {
|
||||
return $mount->getStorage()->getCache();
|
||||
});
|
||||
/** @var ICachedMountInfo[] $newMounts */
|
||||
$newMounts = array_map(function (IMountPoint $mount) use ($user) {
|
||||
$storage = $mount->getStorage();
|
||||
$rootId = (int)$storage->getCache()->getId('');
|
||||
$storageId = (int)$storage->getStorageCache()->getNumericId();
|
||||
// filter out any storages which aren't scanned yet since we aren't interested in files from those storages (yet)
|
||||
if ($rootId === -1) {
|
||||
return null;
|
||||
} else {
|
||||
return new CachedMountInfo($user, $storageId, $rootId, $mount->getMountPoint());
|
||||
}
|
||||
}, $mounts);
|
||||
$newMounts = array_values(array_filter($newMounts));
|
||||
|
||||
$cachedMounts = $this->getMountsForUser($user);
|
||||
$mountDiff = function (ICachedMountInfo $mount1, ICachedMountInfo $mount2) {
|
||||
// since we are only looking for mounts for a specific user comparing on root id is enough
|
||||
return $mount1->getRootId() - $mount2->getRootId();
|
||||
};
|
||||
|
||||
/** @var ICachedMountInfo[] $addedMounts */
|
||||
$addedMounts = array_udiff($newMounts, $cachedMounts, $mountDiff);
|
||||
/** @var ICachedMountInfo[] $removedMounts */
|
||||
$removedMounts = array_udiff($cachedMounts, $newMounts, $mountDiff);
|
||||
|
||||
$changedMounts = array_uintersect($newMounts, $cachedMounts, function (ICachedMountInfo $mount1, ICachedMountInfo $mount2) {
|
||||
// filter mounts with the same root id and different mountpoints
|
||||
if ($mount1->getRootId() !== $mount2->getRootId()) {
|
||||
return -1;
|
||||
}
|
||||
return ($mount1->getMountPoint() !== $mount2->getMountPoint()) ? 0 : 1;
|
||||
});
|
||||
|
||||
foreach ($addedMounts as $mount) {
|
||||
$this->addToCache($mount);
|
||||
$this->mountsForUsers[$user->getUID()][] = $mount;
|
||||
}
|
||||
foreach ($removedMounts as $mount) {
|
||||
$this->removeFromCache($mount);
|
||||
$index = array_search($mount, $this->mountsForUsers[$user->getUID()]);
|
||||
unset($this->mountsForUsers[$user->getUID()][$index]);
|
||||
}
|
||||
foreach ($changedMounts as $mount) {
|
||||
$this->setMountPoint($mount);
|
||||
}
|
||||
}
|
||||
|
||||
private function addToCache(ICachedMountInfo $mount) {
|
||||
$this->connection->insertIfNotExist('*PREFIX*mounts', [
|
||||
'storage_id' => $mount->getStorageId(),
|
||||
'root_id' => $mount->getRootId(),
|
||||
'user_id' => $mount->getUser()->getUID(),
|
||||
'mount_point' => $mount->getMountPoint()
|
||||
]);
|
||||
}
|
||||
|
||||
private function setMountPoint(ICachedMountInfo $mount) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->update('mounts')
|
||||
->set('mount_point', $builder->createNamedParameter($mount->getMountPoint()))
|
||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
|
||||
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), \PDO::PARAM_INT)));
|
||||
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
private function removeFromCache(ICachedMountInfo $mount) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->delete('mounts')
|
||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
|
||||
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), \PDO::PARAM_INT)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
private function dbRowToMountInfo(array $row) {
|
||||
$user = $this->userManager->get($row['user_id']);
|
||||
return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @return ICachedMountInfo[]
|
||||
*/
|
||||
public function getMountsForUser(IUser $user) {
|
||||
if (!isset($this->mountsForUsers[$user->getUID()])) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
||||
->from('mounts')
|
||||
->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID())));
|
||||
|
||||
$rows = $query->execute()->fetchAll();
|
||||
|
||||
$this->mountsForUsers[$user->getUID()] = array_map([$this, 'dbRowToMountInfo'], $rows);
|
||||
}
|
||||
return $this->mountsForUsers[$user->getUID()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $numericStorageId
|
||||
* @return CachedMountInfo[]
|
||||
*/
|
||||
public function getMountsForStorageId($numericStorageId) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
||||
->from('mounts')
|
||||
->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, \PDO::PARAM_INT)));
|
||||
|
||||
$rows = $query->execute()->fetchAll();
|
||||
|
||||
return array_map([$this, 'dbRowToMountInfo'], $rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $rootFileId
|
||||
* @return CachedMountInfo[]
|
||||
*/
|
||||
public function getMountsForRootId($rootFileId) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
||||
->from('mounts')
|
||||
->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, \PDO::PARAM_INT)));
|
||||
|
||||
$rows = $query->execute()->fetchAll();
|
||||
|
||||
return array_map([$this, 'dbRowToMountInfo'], $rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all cached mounts for a user
|
||||
*
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function removeUserMounts(IUser $user) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->delete('mounts')
|
||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($user->getUID())));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
public function removeUserStorageMount($storageId, $userId) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->delete('mounts')
|
||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userId)))
|
||||
->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, \PDO::PARAM_INT)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
public function remoteStorageMounts($storageId) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->delete('mounts')
|
||||
->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, \PDO::PARAM_INT)));
|
||||
$query->execute();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Files\Config;
|
||||
|
||||
use OC\User\Manager;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
|
||||
/**
|
||||
* Listen to hooks and update the mount cache as needed
|
||||
*/
|
||||
class UserMountCacheListener {
|
||||
/**
|
||||
* @var IUserMountCache
|
||||
*/
|
||||
private $userMountCache;
|
||||
|
||||
/**
|
||||
* UserMountCacheListener constructor.
|
||||
*
|
||||
* @param IUserMountCache $userMountCache
|
||||
*/
|
||||
public function __construct(IUserMountCache $userMountCache) {
|
||||
$this->userMountCache = $userMountCache;
|
||||
}
|
||||
|
||||
public function listen(Manager $manager) {
|
||||
$manager->listen('\OC\User', 'postDelete', [$this->userMountCache, 'removeUserMounts']);
|
||||
}
|
||||
}
|
|
@ -59,8 +59,10 @@
|
|||
namespace OC\Files;
|
||||
|
||||
use OC\Files\Config\MountProviderCollection;
|
||||
use OC\Files\Mount\MountPoint;
|
||||
use OC\Files\Storage\StorageFactory;
|
||||
use OCP\Files\Config\IMountProvider;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IUserManager;
|
||||
|
||||
|
@ -412,7 +414,8 @@ class Filesystem {
|
|||
$homeStorage['arguments']['legacy'] = true;
|
||||
}
|
||||
|
||||
self::mount($homeStorage['class'], $homeStorage['arguments'], $user);
|
||||
$mount = new MountPoint($homeStorage['class'], '/' . $user, $homeStorage['arguments'], self::getLoader());
|
||||
self::getMountManager()->addMount($mount);
|
||||
|
||||
$home = \OC\Files\Filesystem::getStorage($user);
|
||||
|
||||
|
@ -424,6 +427,8 @@ class Filesystem {
|
|||
if ($userObject) {
|
||||
$mounts = $mountConfigManager->getMountsForUser($userObject);
|
||||
array_walk($mounts, array(self::$mounts, 'addMount'));
|
||||
$mounts[] = $mount;
|
||||
$mountConfigManager->registerMounts($userObject, $mounts);
|
||||
}
|
||||
|
||||
self::listenForNewMountProviders($mountConfigManager, $userManager);
|
||||
|
|
|
@ -47,6 +47,8 @@ use OC\Diagnostics\EventLogger;
|
|||
use OC\Diagnostics\NullEventLogger;
|
||||
use OC\Diagnostics\NullQueryLogger;
|
||||
use OC\Diagnostics\QueryLogger;
|
||||
use OC\Files\Config\UserMountCache;
|
||||
use OC\Files\Config\UserMountCacheListener;
|
||||
use OC\Files\Node\HookConnector;
|
||||
use OC\Files\Node\Root;
|
||||
use OC\Files\View;
|
||||
|
@ -136,7 +138,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
return new Encryption\Keys\Storage($view, $util);
|
||||
});
|
||||
$this->registerService('TagMapper', function(Server $c) {
|
||||
$this->registerService('TagMapper', function (Server $c) {
|
||||
return new TagMapper($c->getDatabaseConnection());
|
||||
});
|
||||
$this->registerService('TagManager', function (Server $c) {
|
||||
|
@ -276,13 +278,13 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$this->registerService('MemCacheFactory', function (Server $c) {
|
||||
$config = $c->getConfig();
|
||||
|
||||
if($config->getSystemValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
|
||||
if ($config->getSystemValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
|
||||
$v = \OC_App::getAppVersions();
|
||||
$v['core'] = md5(file_get_contents(\OC::$SERVERROOT . '/version.php'));
|
||||
$version = implode(',', $v);
|
||||
$instanceId = \OC_Util::getInstanceId();
|
||||
$path = \OC::$SERVERROOT;
|
||||
$prefix = md5($instanceId.'-'.$version.'-'.$path);
|
||||
$prefix = md5($instanceId . '-' . $version . '-' . $path);
|
||||
return new \OC\Memcache\Factory($prefix, $c->getLogger(),
|
||||
$config->getSystemValue('memcache.local', null),
|
||||
$config->getSystemValue('memcache.distributed', null),
|
||||
|
@ -393,7 +395,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$c->getConfig()
|
||||
);
|
||||
});
|
||||
$this->registerService('AppManager', function(Server $c) {
|
||||
$this->registerService('AppManager', function (Server $c) {
|
||||
return new \OC\App\AppManager(
|
||||
$c->getUserSession(),
|
||||
$c->getAppConfig(),
|
||||
|
@ -401,13 +403,13 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$c->getMemCacheFactory()
|
||||
);
|
||||
});
|
||||
$this->registerService('DateTimeZone', function(Server $c) {
|
||||
$this->registerService('DateTimeZone', function (Server $c) {
|
||||
return new DateTimeZone(
|
||||
$c->getConfig(),
|
||||
$c->getSession()
|
||||
);
|
||||
});
|
||||
$this->registerService('DateTimeFormatter', function(Server $c) {
|
||||
$this->registerService('DateTimeFormatter', function (Server $c) {
|
||||
$language = $c->getConfig()->getUserValue($c->getSession()->get('user_id'), 'core', 'lang', null);
|
||||
|
||||
return new DateTimeFormatter(
|
||||
|
@ -415,9 +417,16 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$c->getL10N('lib', $language)
|
||||
);
|
||||
});
|
||||
$this->registerService('MountConfigManager', function () {
|
||||
$this->registerService('UserMountCache', function (Server $c) {
|
||||
$mountCache = new UserMountCache($c->getDatabaseConnection(), $c->getUserManager(), $c->getLogger());
|
||||
$listener = new UserMountCacheListener($mountCache);
|
||||
$listener->listen($c->getUserManager());
|
||||
return $mountCache;
|
||||
});
|
||||
$this->registerService('MountConfigManager', function (Server $c) {
|
||||
$loader = \OC\Files\Filesystem::getLoader();
|
||||
return new \OC\Files\Config\MountProviderCollection($loader);
|
||||
$mountCache = $c->query('UserMountCache');
|
||||
return new \OC\Files\Config\MountProviderCollection($loader, $mountCache);
|
||||
});
|
||||
$this->registerService('IniWrapper', function ($c) {
|
||||
return new IniGetWrapper();
|
||||
|
@ -489,14 +498,14 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$stream
|
||||
);
|
||||
});
|
||||
$this->registerService('Mailer', function(Server $c) {
|
||||
$this->registerService('Mailer', function (Server $c) {
|
||||
return new Mailer(
|
||||
$c->getConfig(),
|
||||
$c->getLogger(),
|
||||
new \OC_Defaults()
|
||||
);
|
||||
});
|
||||
$this->registerService('OcsClient', function(Server $c) {
|
||||
$this->registerService('OcsClient', function (Server $c) {
|
||||
return new OCSClient(
|
||||
$this->getHTTPClientService(),
|
||||
$this->getConfig(),
|
||||
|
@ -518,24 +527,24 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$this->registerService('MountManager', function () {
|
||||
return new \OC\Files\Mount\Manager();
|
||||
});
|
||||
$this->registerService('MimeTypeDetector', function(Server $c) {
|
||||
$this->registerService('MimeTypeDetector', function (Server $c) {
|
||||
return new \OC\Files\Type\Detection(
|
||||
$c->getURLGenerator(),
|
||||
\OC::$SERVERROOT . '/config/',
|
||||
\OC::$SERVERROOT . '/resources/config/'
|
||||
);
|
||||
);
|
||||
});
|
||||
$this->registerService('MimeTypeLoader', function(Server $c) {
|
||||
$this->registerService('MimeTypeLoader', function (Server $c) {
|
||||
return new \OC\Files\Type\Loader(
|
||||
$c->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
$this->registerService('NotificationManager', function() {
|
||||
$this->registerService('NotificationManager', function () {
|
||||
return new Manager();
|
||||
});
|
||||
$this->registerService('CapabilitiesManager', function (Server $c) {
|
||||
$manager = new \OC\CapabilitiesManager();
|
||||
$manager->registerCapability(function() use ($c) {
|
||||
$manager->registerCapability(function () use ($c) {
|
||||
return new \OC\OCS\CoreCapabilities($c->getConfig());
|
||||
});
|
||||
return $manager;
|
||||
|
@ -547,7 +556,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$factory = new $factoryClass($this);
|
||||
return $factory->getManager();
|
||||
});
|
||||
$this->registerService('EventDispatcher', function() {
|
||||
$this->registerService('EventDispatcher', function () {
|
||||
return new EventDispatcher();
|
||||
});
|
||||
$this->registerService('CryptoWrapper', function (Server $c) {
|
||||
|
@ -932,6 +941,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
/**
|
||||
* Returns an instance of the db facade
|
||||
*
|
||||
* @deprecated use getDatabaseConnection, will be removed in ownCloud 10
|
||||
* @return \OCP\IDb
|
||||
*/
|
||||
|
@ -941,6 +951,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
/**
|
||||
* Returns an instance of the HTTP helper class
|
||||
*
|
||||
* @deprecated Use getHTTPClientService()
|
||||
* @return \OC\HTTPHelper
|
||||
*/
|
||||
|
@ -1066,7 +1077,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
/**
|
||||
* @return \OCP\Files\Config\IMountProviderCollection
|
||||
*/
|
||||
public function getMountProviderCollection(){
|
||||
public function getMountProviderCollection() {
|
||||
return $this->query('MountConfigManager');
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1093,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
/**
|
||||
* @return \OCP\Command\IBus
|
||||
*/
|
||||
public function getCommandBus(){
|
||||
public function getCommandBus() {
|
||||
return $this->query('AsyncCommandBus');
|
||||
}
|
||||
|
||||
|
@ -1182,6 +1193,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
/**
|
||||
* Not a public API as of 8.2, wait for 9.0
|
||||
*
|
||||
* @return \OCA\Files_External\Service\BackendService
|
||||
*/
|
||||
public function getStoragesBackendService() {
|
||||
|
@ -1190,6 +1202,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
/**
|
||||
* Not a public API as of 8.2, wait for 9.0
|
||||
*
|
||||
* @return \OCA\Files_External\Service\GlobalStoragesService
|
||||
*/
|
||||
public function getGlobalStoragesService() {
|
||||
|
@ -1198,6 +1211,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
/**
|
||||
* Not a public API as of 8.2, wait for 9.0
|
||||
*
|
||||
* @return \OCA\Files_External\Service\UserGlobalStoragesService
|
||||
*/
|
||||
public function getUserGlobalStoragesService() {
|
||||
|
@ -1206,6 +1220,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
/**
|
||||
* Not a public API as of 8.2, wait for 9.0
|
||||
*
|
||||
* @return \OCA\Files_External\Service\UserStoragesService
|
||||
*/
|
||||
public function getUserStoragesService() {
|
||||
|
@ -1219,4 +1234,5 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
public function getShareManager() {
|
||||
return $this->query('ShareManager');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCP\Files\Config;
|
||||
|
||||
use OCP\Files\Node;
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
* Holds information about a mount for a user
|
||||
*
|
||||
* @since 9.0.0
|
||||
*/
|
||||
interface ICachedMountInfo {
|
||||
/**
|
||||
* @return IUser
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getUser();
|
||||
|
||||
/**
|
||||
* @return int the numeric storage id of the mount
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getStorageId();
|
||||
|
||||
/**
|
||||
* @return int the fileid of the root of the mount
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getRootId();
|
||||
|
||||
/**
|
||||
* @return Node the root node of the mount
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getMountPointNode();
|
||||
|
||||
/**
|
||||
* @return string the mount point of the mount for the user
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getMountPoint();
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
namespace OCP\Files\Config;
|
||||
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
|
@ -45,4 +46,12 @@ interface IMountProviderCollection {
|
|||
* @since 8.0.0
|
||||
*/
|
||||
public function registerProvider(IMountProvider $provider);
|
||||
|
||||
/**
|
||||
* Get the mount cache which can be used to search for mounts without setting up the filesystem
|
||||
*
|
||||
* @return IUserMountCache
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getMountCache();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCP\Files\Config;
|
||||
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
* Cache mounts points per user in the cache so we can easily look them up
|
||||
*
|
||||
* @since 9.0.0
|
||||
*/
|
||||
interface IUserMountCache {
|
||||
/**
|
||||
* Register mounts for a user to the cache
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param IMountPoint[] $mounts
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function registerMounts(IUser $user, array $mounts);
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @return ICachedMountInfo[]
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getMountsForUser(IUser $user);
|
||||
|
||||
/**
|
||||
* @param int $numericStorageId
|
||||
* @return ICachedMountInfo[]
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getMountsForStorageId($numericStorageId);
|
||||
|
||||
/**
|
||||
* @param int $rootFileId
|
||||
* @return ICachedMountInfo[]
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function getMountsForRootId($rootFileId);
|
||||
|
||||
/**
|
||||
* Remove all cached mounts for a user
|
||||
*
|
||||
* @param IUser $user
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function removeUserMounts(IUser $user);
|
||||
|
||||
/**
|
||||
* Remove all mounts for a user and storage
|
||||
*
|
||||
* @param $storageId
|
||||
* @param string $userId
|
||||
* @return mixed
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function removeUserStorageMount($storageId, $userId);
|
||||
|
||||
/**
|
||||
* Remove all cached mounts for a storage
|
||||
*
|
||||
* @param $storageId
|
||||
* @return mixed
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function remoteStorageMounts($storageId);
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace Test\Files\Config;
|
||||
|
||||
use OC\Files\Mount\MountPoint;
|
||||
use OC\Files\Storage\Temporary;
|
||||
use OC\Log;
|
||||
use OC\User\Manager;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUserManager;
|
||||
use Test\TestCase;
|
||||
use Test\Util\User\Dummy;
|
||||
|
||||
/**
|
||||
* @group DB
|
||||
*/
|
||||
class UserMountCache extends TestCase {
|
||||
/**
|
||||
* @var IDBConnection
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* @var IUserManager
|
||||
*/
|
||||
private $userManager;
|
||||
|
||||
/**
|
||||
* @var \OC\Files\Config\UserMountCache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
public function setUp() {
|
||||
$this->connection = \OC::$server->getDatabaseConnection();
|
||||
$this->userManager = new Manager(null);
|
||||
$userBackend = new Dummy();
|
||||
$userBackend->createUser('u1', '');
|
||||
$userBackend->createUser('u2', '');
|
||||
$this->userManager->registerBackend($userBackend);
|
||||
$this->cache = new \OC\Files\Config\UserMountCache($this->connection, $this->userManager, $this->getMock('\OC\Log'));
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$builder->delete('mounts')->execute();
|
||||
}
|
||||
|
||||
private function getStorage($storageId, $rootId) {
|
||||
$storageCache = $this->getMockBuilder('\OC\Files\Cache\Storage')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$storageCache->expects($this->any())
|
||||
->method('getNumericId')
|
||||
->will($this->returnValue($storageId));
|
||||
|
||||
$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$cache->expects($this->any())
|
||||
->method('getId')
|
||||
->will($this->returnValue($rootId));
|
||||
|
||||
$storage = $this->getMockBuilder('\OC\Files\Storage\Storage')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$storage->expects($this->any())
|
||||
->method('getStorageCache')
|
||||
->will($this->returnValue($storageCache));
|
||||
$storage->expects($this->any())
|
||||
->method('getCache')
|
||||
->will($this->returnValue($cache));
|
||||
|
||||
return $storage;
|
||||
}
|
||||
|
||||
private function clearCache() {
|
||||
$this->invokePrivate($this->cache, 'mountsForUsers', [[]]);
|
||||
}
|
||||
|
||||
public function testNewMounts() {
|
||||
$user = $this->userManager->get('u1');
|
||||
|
||||
$storage = $this->getStorage(10, 20);
|
||||
$mount = new MountPoint($storage, '/asd/');
|
||||
|
||||
$this->cache->registerMounts($user, [$mount]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForUser($user);
|
||||
|
||||
$this->assertCount(1, $cachedMounts);
|
||||
$cachedMount = $cachedMounts[0];
|
||||
$this->assertEquals('/asd/', $cachedMount->getMountPoint());
|
||||
$this->assertEquals($user, $cachedMount->getUser());
|
||||
$this->assertEquals($storage->getCache()->getId(''), $cachedMount->getRootId());
|
||||
$this->assertEquals($storage->getStorageCache()->getNumericId(), $cachedMount->getStorageId());
|
||||
}
|
||||
|
||||
public function testSameMounts() {
|
||||
$user = $this->userManager->get('u1');
|
||||
|
||||
$storage = $this->getStorage(10, 20);
|
||||
$mount = new MountPoint($storage, '/asd/');
|
||||
|
||||
$this->cache->registerMounts($user, [$mount]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$this->cache->registerMounts($user, [$mount]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForUser($user);
|
||||
|
||||
$this->assertCount(1, $cachedMounts);
|
||||
$cachedMount = $cachedMounts[0];
|
||||
$this->assertEquals('/asd/', $cachedMount->getMountPoint());
|
||||
$this->assertEquals($user, $cachedMount->getUser());
|
||||
$this->assertEquals($storage->getCache()->getId(''), $cachedMount->getRootId());
|
||||
$this->assertEquals($storage->getStorageCache()->getNumericId(), $cachedMount->getStorageId());
|
||||
}
|
||||
|
||||
public function testRemoveMounts() {
|
||||
$user = $this->userManager->get('u1');
|
||||
|
||||
$storage = $this->getStorage(10, 20);
|
||||
$mount = new MountPoint($storage, '/asd/');
|
||||
|
||||
$this->cache->registerMounts($user, [$mount]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$this->cache->registerMounts($user, []);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForUser($user);
|
||||
|
||||
$this->assertCount(0, $cachedMounts);
|
||||
}
|
||||
|
||||
public function testChangeMounts() {
|
||||
$user = $this->userManager->get('u1');
|
||||
|
||||
$storage = $this->getStorage(10, 20);
|
||||
$mount = new MountPoint($storage, '/foo/');
|
||||
|
||||
$this->cache->registerMounts($user, [$mount]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$this->cache->registerMounts($user, [$mount]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForUser($user);
|
||||
|
||||
$this->assertCount(1, $cachedMounts);
|
||||
$cachedMount = $cachedMounts[0];
|
||||
$this->assertEquals('/foo/', $cachedMount->getMountPoint());
|
||||
}
|
||||
|
||||
public function testGetMountsForUser() {
|
||||
$user1 = $this->userManager->get('u1');
|
||||
$user2 = $this->userManager->get('u2');
|
||||
|
||||
$mount1 = new MountPoint($this->getStorage(1, 2), '/foo/');
|
||||
$mount2 = new MountPoint($this->getStorage(3, 4), '/bar/');
|
||||
|
||||
$this->cache->registerMounts($user1, [$mount1, $mount2]);
|
||||
$this->cache->registerMounts($user2, [$mount2]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForUser($user1);
|
||||
|
||||
$this->assertCount(2, $cachedMounts);
|
||||
$this->assertEquals('/foo/', $cachedMounts[0]->getMountPoint());
|
||||
$this->assertEquals($user1, $cachedMounts[0]->getUser());
|
||||
$this->assertEquals(2, $cachedMounts[0]->getRootId());
|
||||
$this->assertEquals(1, $cachedMounts[0]->getStorageId());
|
||||
|
||||
$this->assertEquals('/bar/', $cachedMounts[1]->getMountPoint());
|
||||
$this->assertEquals($user1, $cachedMounts[1]->getUser());
|
||||
$this->assertEquals(4, $cachedMounts[1]->getRootId());
|
||||
$this->assertEquals(3, $cachedMounts[1]->getStorageId());
|
||||
}
|
||||
|
||||
public function testGetMountsByStorageId() {
|
||||
$user1 = $this->userManager->get('u1');
|
||||
$user2 = $this->userManager->get('u2');
|
||||
|
||||
$mount1 = new MountPoint($this->getStorage(1, 2), '/foo/');
|
||||
$mount2 = new MountPoint($this->getStorage(3, 4), '/bar/');
|
||||
|
||||
$this->cache->registerMounts($user1, [$mount1, $mount2]);
|
||||
$this->cache->registerMounts($user2, [$mount2]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForStorageId(3);
|
||||
usort($cachedMounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
||||
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
||||
});
|
||||
|
||||
$this->assertCount(2, $cachedMounts);
|
||||
|
||||
$this->assertEquals('/bar/', $cachedMounts[0]->getMountPoint());
|
||||
$this->assertEquals($user1, $cachedMounts[0]->getUser());
|
||||
$this->assertEquals(4, $cachedMounts[0]->getRootId());
|
||||
$this->assertEquals(3, $cachedMounts[0]->getStorageId());
|
||||
|
||||
$this->assertEquals('/bar/', $cachedMounts[1]->getMountPoint());
|
||||
$this->assertEquals($user2, $cachedMounts[1]->getUser());
|
||||
$this->assertEquals(4, $cachedMounts[1]->getRootId());
|
||||
$this->assertEquals(3, $cachedMounts[1]->getStorageId());
|
||||
}
|
||||
|
||||
public function testGetMountsByRootId() {
|
||||
$user1 = $this->userManager->get('u1');
|
||||
$user2 = $this->userManager->get('u2');
|
||||
|
||||
$mount1 = new MountPoint($this->getStorage(1, 2), '/foo/');
|
||||
$mount2 = new MountPoint($this->getStorage(3, 4), '/bar/');
|
||||
|
||||
$this->cache->registerMounts($user1, [$mount1, $mount2]);
|
||||
$this->cache->registerMounts($user2, [$mount2]);
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForRootId(4);
|
||||
usort($cachedMounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
||||
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
||||
});
|
||||
|
||||
$this->assertCount(2, $cachedMounts);
|
||||
|
||||
$this->assertEquals('/bar/', $cachedMounts[0]->getMountPoint());
|
||||
$this->assertEquals($user1, $cachedMounts[0]->getUser());
|
||||
$this->assertEquals(4, $cachedMounts[0]->getRootId());
|
||||
$this->assertEquals(3, $cachedMounts[0]->getStorageId());
|
||||
|
||||
$this->assertEquals('/bar/', $cachedMounts[1]->getMountPoint());
|
||||
$this->assertEquals($user2, $cachedMounts[1]->getUser());
|
||||
$this->assertEquals(4, $cachedMounts[1]->getRootId());
|
||||
$this->assertEquals(3, $cachedMounts[1]->getStorageId());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue