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;
|
||||
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use OC\Files\Filesystem;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\ICache;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\ILogger;
|
||||
|
@ -53,6 +56,8 @@ class UserMountCache implements IUserMountCache {
|
|||
*/
|
||||
private $logger;
|
||||
|
||||
private $cacheInfoCache = [];
|
||||
|
||||
/**
|
||||
* UserMountCache constructor.
|
||||
*
|
||||
|
@ -133,7 +138,7 @@ class UserMountCache implements IUserMountCache {
|
|||
$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)));
|
||||
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$query->execute();
|
||||
}
|
||||
|
@ -143,7 +148,7 @@ class UserMountCache implements IUserMountCache {
|
|||
|
||||
$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)));
|
||||
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
|
@ -178,7 +183,7 @@ class UserMountCache implements IUserMountCache {
|
|||
$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)));
|
||||
->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$rows = $query->execute()->fetchAll();
|
||||
|
||||
|
@ -193,13 +198,67 @@ class UserMountCache implements IUserMountCache {
|
|||
$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)));
|
||||
->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$rows = $query->execute()->fetchAll();
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -218,7 +277,7 @@ class UserMountCache implements IUserMountCache {
|
|||
|
||||
$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)));
|
||||
->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
|
@ -226,7 +285,7 @@ class UserMountCache implements IUserMountCache {
|
|||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ interface IUserMountCache {
|
|||
public function registerMounts(IUser $user, array $mounts);
|
||||
|
||||
/**
|
||||
* Get all cached mounts for a user
|
||||
*
|
||||
* @param IUser $user
|
||||
* @return ICachedMountInfo[]
|
||||
* @since 9.0.0
|
||||
|
@ -47,6 +49,8 @@ interface IUserMountCache {
|
|||
public function getMountsForUser(IUser $user);
|
||||
|
||||
/**
|
||||
* Get all cached mounts by storage
|
||||
*
|
||||
* @param int $numericStorageId
|
||||
* @return ICachedMountInfo[]
|
||||
* @since 9.0.0
|
||||
|
@ -54,12 +58,23 @@ interface IUserMountCache {
|
|||
public function getMountsForStorageId($numericStorageId);
|
||||
|
||||
/**
|
||||
* Get all cached mounts by root
|
||||
*
|
||||
* @param int $rootFileId
|
||||
* @return ICachedMountInfo[]
|
||||
* @since 9.0.0
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
namespace Test\Files\Config;
|
||||
|
||||
use OC\DB\QueryBuilder\Literal;
|
||||
use OC\Files\Mount\MountPoint;
|
||||
use OC\Files\Storage\Temporary;
|
||||
use OC\Log;
|
||||
use OC\User\Manager;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
|
@ -37,7 +37,10 @@ class UserMountCache extends TestCase {
|
|||
*/
|
||||
private $cache;
|
||||
|
||||
private $fileIds = [];
|
||||
|
||||
public function setUp() {
|
||||
$this->fileIds = [];
|
||||
$this->connection = \OC::$server->getDatabaseConnection();
|
||||
$this->userManager = new Manager(null);
|
||||
$userBackend = new Dummy();
|
||||
|
@ -51,6 +54,14 @@ class UserMountCache extends TestCase {
|
|||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$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) {
|
||||
|
@ -208,9 +219,7 @@ class UserMountCache extends TestCase {
|
|||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForStorageId(3);
|
||||
usort($cachedMounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
||||
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
||||
});
|
||||
$this->sortMounts($cachedMounts);
|
||||
|
||||
$this->assertCount(2, $cachedMounts);
|
||||
|
||||
|
@ -238,9 +247,7 @@ class UserMountCache extends TestCase {
|
|||
$this->clearCache();
|
||||
|
||||
$cachedMounts = $this->cache->getMountsForRootId(4);
|
||||
usort($cachedMounts, function (ICachedMountInfo $a, ICachedMountInfo $b) {
|
||||
return strcmp($a->getUser()->getUID(), $b->getUser()->getUID());
|
||||
});
|
||||
$this->sortMounts($cachedMounts);
|
||||
|
||||
$this->assertCount(2, $cachedMounts);
|
||||
|
||||
|
@ -254,4 +261,115 @@ class UserMountCache extends TestCase {
|
|||
$this->assertEquals(4, $cachedMounts[1]->getRootId());
|
||||
$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