Merge pull request #21858 from owncloud/getMountsForFileId
add IUserMountCache->getMountsForFileId
This commit is contained in:
commit
b7710ab6d7
|
@ -22,9 +22,12 @@
|
||||||
namespace OC\Files\Config;
|
namespace OC\Files\Config;
|
||||||
|
|
||||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||||
|
use OC\Files\Filesystem;
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\Files\Config\ICachedMountInfo;
|
use OCP\Files\Config\ICachedMountInfo;
|
||||||
use OCP\Files\Config\IUserMountCache;
|
use OCP\Files\Config\IUserMountCache;
|
||||||
use OCP\Files\Mount\IMountPoint;
|
use OCP\Files\Mount\IMountPoint;
|
||||||
|
use OCP\Files\NotFoundException;
|
||||||
use OCP\ICache;
|
use OCP\ICache;
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
|
@ -53,6 +56,8 @@ class UserMountCache implements IUserMountCache {
|
||||||
*/
|
*/
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
|
private $cacheInfoCache = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserMountCache constructor.
|
* UserMountCache constructor.
|
||||||
*
|
*
|
||||||
|
@ -133,7 +138,7 @@ class UserMountCache implements IUserMountCache {
|
||||||
$query = $builder->update('mounts')
|
$query = $builder->update('mounts')
|
||||||
->set('mount_point', $builder->createNamedParameter($mount->getMountPoint()))
|
->set('mount_point', $builder->createNamedParameter($mount->getMountPoint()))
|
||||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
|
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
|
||||||
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), \PDO::PARAM_INT)));
|
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)));
|
||||||
|
|
||||||
$query->execute();
|
$query->execute();
|
||||||
}
|
}
|
||||||
|
@ -143,7 +148,7 @@ class UserMountCache implements IUserMountCache {
|
||||||
|
|
||||||
$query = $builder->delete('mounts')
|
$query = $builder->delete('mounts')
|
||||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
|
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
|
||||||
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), \PDO::PARAM_INT)));
|
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)));
|
||||||
$query->execute();
|
$query->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +183,7 @@ class UserMountCache implements IUserMountCache {
|
||||||
$builder = $this->connection->getQueryBuilder();
|
$builder = $this->connection->getQueryBuilder();
|
||||||
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
||||||
->from('mounts')
|
->from('mounts')
|
||||||
->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, \PDO::PARAM_INT)));
|
->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, IQueryBuilder::PARAM_INT)));
|
||||||
|
|
||||||
$rows = $query->execute()->fetchAll();
|
$rows = $query->execute()->fetchAll();
|
||||||
|
|
||||||
|
@ -193,13 +198,67 @@ class UserMountCache implements IUserMountCache {
|
||||||
$builder = $this->connection->getQueryBuilder();
|
$builder = $this->connection->getQueryBuilder();
|
||||||
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
$query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point')
|
||||||
->from('mounts')
|
->from('mounts')
|
||||||
->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, \PDO::PARAM_INT)));
|
->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, IQueryBuilder::PARAM_INT)));
|
||||||
|
|
||||||
$rows = $query->execute()->fetchAll();
|
$rows = $query->execute()->fetchAll();
|
||||||
|
|
||||||
return array_map([$this, 'dbRowToMountInfo'], $rows);
|
return array_map([$this, 'dbRowToMountInfo'], $rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fileId
|
||||||
|
* @return array
|
||||||
|
* @throws \OCP\Files\NotFoundException
|
||||||
|
*/
|
||||||
|
private function getCacheInfoFromFileId($fileId) {
|
||||||
|
if (!isset($this->cacheInfoCache[$fileId])) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->select('storage', 'path')
|
||||||
|
->from('filecache')
|
||||||
|
->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
|
||||||
|
|
||||||
|
$row = $query->execute()->fetch();
|
||||||
|
if (is_array($row)) {
|
||||||
|
$this->cacheInfoCache[$fileId] = [
|
||||||
|
(int)$row['storage'],
|
||||||
|
$row['path']
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
throw new NotFoundException('File with id "' . $fileId . '" not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->cacheInfoCache[$fileId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $fileId
|
||||||
|
* @return ICachedMountInfo[]
|
||||||
|
* @since 9.0.0
|
||||||
|
*/
|
||||||
|
public function getMountsForFileId($fileId) {
|
||||||
|
try {
|
||||||
|
list($storageId, $internalPath) = $this->getCacheInfoFromFileId($fileId);
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$mountsForStorage = $this->getMountsForStorageId($storageId);
|
||||||
|
|
||||||
|
// filter mounts that are from the same storage but a different directory
|
||||||
|
return array_filter($mountsForStorage, function (ICachedMountInfo $mount) use ($internalPath, $fileId) {
|
||||||
|
if ($fileId === $mount->getRootId()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
list(, $internalMountPath) = $this->getCacheInfoFromFileId($mount->getRootId());
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/';
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all cached mounts for a user
|
* Remove all cached mounts for a user
|
||||||
*
|
*
|
||||||
|
@ -218,7 +277,7 @@ class UserMountCache implements IUserMountCache {
|
||||||
|
|
||||||
$query = $builder->delete('mounts')
|
$query = $builder->delete('mounts')
|
||||||
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userId)))
|
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userId)))
|
||||||
->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, \PDO::PARAM_INT)));
|
->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
|
||||||
$query->execute();
|
$query->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +285,7 @@ class UserMountCache implements IUserMountCache {
|
||||||
$builder = $this->connection->getQueryBuilder();
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
$query = $builder->delete('mounts')
|
$query = $builder->delete('mounts')
|
||||||
->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, \PDO::PARAM_INT)));
|
->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
|
||||||
$query->execute();
|
$query->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ interface IUserMountCache {
|
||||||
public function registerMounts(IUser $user, array $mounts);
|
public function registerMounts(IUser $user, array $mounts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get all cached mounts for a user
|
||||||
|
*
|
||||||
* @param IUser $user
|
* @param IUser $user
|
||||||
* @return ICachedMountInfo[]
|
* @return ICachedMountInfo[]
|
||||||
* @since 9.0.0
|
* @since 9.0.0
|
||||||
|
@ -47,6 +49,8 @@ interface IUserMountCache {
|
||||||
public function getMountsForUser(IUser $user);
|
public function getMountsForUser(IUser $user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get all cached mounts by storage
|
||||||
|
*
|
||||||
* @param int $numericStorageId
|
* @param int $numericStorageId
|
||||||
* @return ICachedMountInfo[]
|
* @return ICachedMountInfo[]
|
||||||
* @since 9.0.0
|
* @since 9.0.0
|
||||||
|
@ -54,12 +58,23 @@ interface IUserMountCache {
|
||||||
public function getMountsForStorageId($numericStorageId);
|
public function getMountsForStorageId($numericStorageId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get all cached mounts by root
|
||||||
|
*
|
||||||
* @param int $rootFileId
|
* @param int $rootFileId
|
||||||
* @return ICachedMountInfo[]
|
* @return ICachedMountInfo[]
|
||||||
* @since 9.0.0
|
* @since 9.0.0
|
||||||
*/
|
*/
|
||||||
public function getMountsForRootId($rootFileId);
|
public function getMountsForRootId($rootFileId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all cached mounts that contain a file
|
||||||
|
*
|
||||||
|
* @param int $fileId
|
||||||
|
* @return ICachedMountInfo[]
|
||||||
|
* @since 9.0.0
|
||||||
|
*/
|
||||||
|
public function getMountsForFileId($fileId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all cached mounts for a user
|
* Remove all cached mounts for a user
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
namespace Test\Files\Config;
|
namespace Test\Files\Config;
|
||||||
|
|
||||||
|
use OC\DB\QueryBuilder\Literal;
|
||||||
use OC\Files\Mount\MountPoint;
|
use OC\Files\Mount\MountPoint;
|
||||||
use OC\Files\Storage\Temporary;
|
|
||||||
use OC\Log;
|
use OC\Log;
|
||||||
use OC\User\Manager;
|
use OC\User\Manager;
|
||||||
use OCP\Files\Config\ICachedMountInfo;
|
use OCP\Files\Config\ICachedMountInfo;
|
||||||
|
@ -37,7 +37,10 @@ class UserMountCache extends TestCase {
|
||||||
*/
|
*/
|
||||||
private $cache;
|
private $cache;
|
||||||
|
|
||||||
|
private $fileIds = [];
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
|
$this->fileIds = [];
|
||||||
$this->connection = \OC::$server->getDatabaseConnection();
|
$this->connection = \OC::$server->getDatabaseConnection();
|
||||||
$this->userManager = new Manager(null);
|
$this->userManager = new Manager(null);
|
||||||
$userBackend = new Dummy();
|
$userBackend = new Dummy();
|
||||||
|
@ -51,6 +54,14 @@ class UserMountCache extends TestCase {
|
||||||
$builder = $this->connection->getQueryBuilder();
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
$builder->delete('mounts')->execute();
|
$builder->delete('mounts')->execute();
|
||||||
|
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
|
foreach ($this->fileIds as $fileId) {
|
||||||
|
$builder->delete('filecache')
|
||||||
|
->where($builder->expr()->eq('fileid', new Literal($fileId)))
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getStorage($storageId, $rootId) {
|
private function getStorage($storageId, $rootId) {
|
||||||
|
@ -208,9 +219,7 @@ class UserMountCache extends TestCase {
|
||||||
$this->clearCache();
|
$this->clearCache();
|
||||||
|
|
||||||
$cachedMounts = $this->cache->getMountsForStorageId(3);
|
$cachedMounts = $this->cache->getMountsForStorageId(3);
|
||||||
usort($cachedMounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
$this->sortMounts($cachedMounts);
|
||||||
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->assertCount(2, $cachedMounts);
|
$this->assertCount(2, $cachedMounts);
|
||||||
|
|
||||||
|
@ -238,9 +247,7 @@ class UserMountCache extends TestCase {
|
||||||
$this->clearCache();
|
$this->clearCache();
|
||||||
|
|
||||||
$cachedMounts = $this->cache->getMountsForRootId(4);
|
$cachedMounts = $this->cache->getMountsForRootId(4);
|
||||||
usort($cachedMounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
$this->sortMounts($cachedMounts);
|
||||||
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->assertCount(2, $cachedMounts);
|
$this->assertCount(2, $cachedMounts);
|
||||||
|
|
||||||
|
@ -254,4 +261,115 @@ class UserMountCache extends TestCase {
|
||||||
$this->assertEquals(4, $cachedMounts[1]->getRootId());
|
$this->assertEquals(4, $cachedMounts[1]->getRootId());
|
||||||
$this->assertEquals(3, $cachedMounts[1]->getStorageId());
|
$this->assertEquals(3, $cachedMounts[1]->getStorageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function sortMounts(&$mounts) {
|
||||||
|
usort($mounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
||||||
|
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createCacheEntry($internalPath, $storageId) {
|
||||||
|
$this->connection->insertIfNotExist('*PREFIX*filecache', [
|
||||||
|
'storage' => $storageId,
|
||||||
|
'path' => $internalPath,
|
||||||
|
'path_hash' => md5($internalPath),
|
||||||
|
'parent' => -1,
|
||||||
|
'name' => basename($internalPath),
|
||||||
|
'mimetype' => 0,
|
||||||
|
'mimepart' => 0,
|
||||||
|
'size' => 0,
|
||||||
|
'storage_mtime' => 0,
|
||||||
|
'encrypted' => 0,
|
||||||
|
'unencrypted_size' => 0,
|
||||||
|
'etag' => '',
|
||||||
|
'permissions' => 31
|
||||||
|
], ['storage', 'path_hash']);
|
||||||
|
$id = (int)$this->connection->lastInsertId('*PREFIX*filecache');
|
||||||
|
$this->fileIds[] = $id;
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMountsForFileIdRootId() {
|
||||||
|
$user1 = $this->userManager->get('u1');
|
||||||
|
|
||||||
|
$rootId = $this->createCacheEntry('', 2);
|
||||||
|
|
||||||
|
$mount1 = new MountPoint($this->getStorage(2, $rootId), '/foo/');
|
||||||
|
|
||||||
|
$this->cache->registerMounts($user1, [$mount1]);
|
||||||
|
|
||||||
|
$this->clearCache();
|
||||||
|
|
||||||
|
$cachedMounts = $this->cache->getMountsForFileId($rootId);
|
||||||
|
|
||||||
|
$this->assertCount(1, $cachedMounts);
|
||||||
|
|
||||||
|
$this->assertEquals('/foo/', $cachedMounts[0]->getMountPoint());
|
||||||
|
$this->assertEquals($user1, $cachedMounts[0]->getUser());
|
||||||
|
$this->assertEquals($rootId, $cachedMounts[0]->getRootId());
|
||||||
|
$this->assertEquals(2, $cachedMounts[0]->getStorageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMountsForFileIdSubFolder() {
|
||||||
|
$user1 = $this->userManager->get('u1');
|
||||||
|
|
||||||
|
$rootId = $this->createCacheEntry('', 2);
|
||||||
|
$fileId = $this->createCacheEntry('/foo/bar', 2);
|
||||||
|
|
||||||
|
$mount1 = new MountPoint($this->getStorage(2, $rootId), '/foo/');
|
||||||
|
|
||||||
|
$this->cache->registerMounts($user1, [$mount1]);
|
||||||
|
|
||||||
|
$this->clearCache();
|
||||||
|
|
||||||
|
$cachedMounts = $this->cache->getMountsForFileId($fileId);
|
||||||
|
|
||||||
|
$this->assertCount(1, $cachedMounts);
|
||||||
|
|
||||||
|
$this->assertEquals('/foo/', $cachedMounts[0]->getMountPoint());
|
||||||
|
$this->assertEquals($user1, $cachedMounts[0]->getUser());
|
||||||
|
$this->assertEquals($rootId, $cachedMounts[0]->getRootId());
|
||||||
|
$this->assertEquals(2, $cachedMounts[0]->getStorageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMountsForFileIdSubFolderMount() {
|
||||||
|
$user1 = $this->userManager->get('u1');
|
||||||
|
|
||||||
|
$this->createCacheEntry('', 2);
|
||||||
|
$folderId = $this->createCacheEntry('/foo', 2);
|
||||||
|
$fileId = $this->createCacheEntry('/foo/bar', 2);
|
||||||
|
|
||||||
|
$mount1 = new MountPoint($this->getStorage(2, $folderId), '/foo/');
|
||||||
|
|
||||||
|
$this->cache->registerMounts($user1, [$mount1]);
|
||||||
|
|
||||||
|
$this->clearCache();
|
||||||
|
|
||||||
|
$cachedMounts = $this->cache->getMountsForFileId($fileId);
|
||||||
|
|
||||||
|
$this->assertCount(1, $cachedMounts);
|
||||||
|
|
||||||
|
$this->assertEquals('/foo/', $cachedMounts[0]->getMountPoint());
|
||||||
|
$this->assertEquals($user1, $cachedMounts[0]->getUser());
|
||||||
|
$this->assertEquals($folderId, $cachedMounts[0]->getRootId());
|
||||||
|
$this->assertEquals(2, $cachedMounts[0]->getStorageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMountsForFileIdSubFolderMountOutside() {
|
||||||
|
$user1 = $this->userManager->get('u1');
|
||||||
|
|
||||||
|
$this->createCacheEntry('', 2);
|
||||||
|
$folderId = $this->createCacheEntry('/foo', 2);
|
||||||
|
$fileId = $this->createCacheEntry('/bar/asd', 2);
|
||||||
|
|
||||||
|
$mount1 = new MountPoint($this->getStorage(2, $folderId), '/foo/');
|
||||||
|
|
||||||
|
$this->cache->registerMounts($user1, [$mount1]);
|
||||||
|
|
||||||
|
$this->clearCache();
|
||||||
|
|
||||||
|
$cachedMounts = $this->cache->getMountsForFileId($fileId);
|
||||||
|
|
||||||
|
$this->assertCount(0, $cachedMounts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue