Merge pull request #21858 from owncloud/getMountsForFileId

add IUserMountCache->getMountsForFileId
This commit is contained in:
Thomas Müller 2016-01-28 11:20:42 +01:00
commit b7710ab6d7
3 changed files with 205 additions and 13 deletions

View File

@ -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();
}
}

View File

@ -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
*

View File

@ -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);
}
}