diff --git a/apps/files_trashbin/lib/Trash/TrashItem.php b/apps/files_trashbin/lib/Trash/TrashItem.php index 153625cfb4cc7..10d6d9ef95b46 100644 --- a/apps/files_trashbin/lib/Trash/TrashItem.php +++ b/apps/files_trashbin/lib/Trash/TrashItem.php @@ -99,6 +99,11 @@ public function getStorage() { return $this->fileInfo->getStorage(); } + #[\Override] + public function getStorageId(): int { + return $this->fileInfo->getStorageId(); + } + #[\Override] public function getId() { return $this->fileInfo->getId(); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index aaf5602ba47e4..c1ed5d4f36c07 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1925,7 +1925,6 @@ 'OC\\Files\\Cache\\Wrapper\\JailWatcher' => $baseDir . '/lib/private/Files/Cache/Wrapper/JailWatcher.php', 'OC\\Files\\Config\\CachedMountFileInfo' => $baseDir . '/lib/private/Files/Config/CachedMountFileInfo.php', 'OC\\Files\\Config\\CachedMountInfo' => $baseDir . '/lib/private/Files/Config/CachedMountInfo.php', - 'OC\\Files\\Config\\LazyPathCachedMountInfo' => $baseDir . '/lib/private/Files/Config/LazyPathCachedMountInfo.php', 'OC\\Files\\Config\\LazyStorageMountInfo' => $baseDir . '/lib/private/Files/Config/LazyStorageMountInfo.php', 'OC\\Files\\Config\\MountProviderCollection' => $baseDir . '/lib/private/Files/Config/MountProviderCollection.php', 'OC\\Files\\Config\\UserMountCache' => $baseDir . '/lib/private/Files/Config/UserMountCache.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index d07e0aaa6b3bd..ac2e2498bae7b 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1966,7 +1966,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Files\\Cache\\Wrapper\\JailWatcher' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Wrapper/JailWatcher.php', 'OC\\Files\\Config\\CachedMountFileInfo' => __DIR__ . '/../../..' . '/lib/private/Files/Config/CachedMountFileInfo.php', 'OC\\Files\\Config\\CachedMountInfo' => __DIR__ . '/../../..' . '/lib/private/Files/Config/CachedMountInfo.php', - 'OC\\Files\\Config\\LazyPathCachedMountInfo' => __DIR__ . '/../../..' . '/lib/private/Files/Config/LazyPathCachedMountInfo.php', 'OC\\Files\\Config\\LazyStorageMountInfo' => __DIR__ . '/../../..' . '/lib/private/Files/Config/LazyStorageMountInfo.php', 'OC\\Files\\Config\\MountProviderCollection' => __DIR__ . '/../../..' . '/lib/private/Files/Config/MountProviderCollection.php', 'OC\\Files\\Config\\UserMountCache' => __DIR__ . '/../../..' . '/lib/private/Files/Config/UserMountCache.php', diff --git a/lib/private/Files/Config/CachedMountFileInfo.php b/lib/private/Files/Config/CachedMountFileInfo.php index 4bc1093f2614e..4e0c023099f66 100644 --- a/lib/private/Files/Config/CachedMountFileInfo.php +++ b/lib/private/Files/Config/CachedMountFileInfo.php @@ -9,21 +9,67 @@ namespace OC\Files\Config; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Config\ICachedMountFileInfo; +use OCP\Files\Config\ICachedMountInfo; +use OCP\Files\Node; use OCP\IUser; -class CachedMountFileInfo extends CachedMountInfo implements ICachedMountFileInfo { +class CachedMountFileInfo implements ICachedMountFileInfo { public function __construct( - IUser $user, - int $storageId, - int $rootId, - string $mountPoint, - ?int $mountId, - string $mountProvider, - string $rootInternalPath, - private string $internalPath, + private readonly ICachedMountInfo $mountInfo, + private readonly string $internalPath, ) { - parent::__construct($user, $storageId, $rootId, $mountPoint, $mountProvider, $mountId, $rootInternalPath); + } + + #[\Override] + public function getUser(): IUser { + return $this->mountInfo->getUser(); + } + + #[\Override] + public function getStorageId(): int { + return $this->mountInfo->getStorageId(); + } + + #[\Override] + public function getRootId(): int { + return $this->mountInfo->getRootId(); + } + + #[\Override] + public function getMountPointNode(): ?Node { + return $this->mountInfo->getMountPointNode(); + } + + #[\Override] + public function getMountPoint(): string { + return $this->mountInfo->getMountPoint(); + } + + #[\Override] + public function getMountId(): ?int { + return $this->mountInfo->getMountId(); + } + + #[\Override] + public function getRootInternalPath(): string { + return $this->mountInfo->getRootInternalPath(); + } + + #[\Override] + public function getMountProvider(): string { + return $this->mountInfo->getMountProvider(); + } + + #[\Override] + public function getKey(): string { + return $this->mountInfo->getKey(); + } + + #[\Override] + public function getRootCacheEntry(): ICacheEntry { + return $this->mountInfo->getRootCacheEntry(); } #[\Override] diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php index 9968529dfeb22..5034154004f69 100644 --- a/lib/private/Files/Config/CachedMountInfo.php +++ b/lib/private/Files/Config/CachedMountInfo.php @@ -8,7 +8,7 @@ namespace OC\Files\Config; -use OC\Files\Filesystem; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Config\ICachedMountInfo; use OCP\Files\IRootFolder; use OCP\Files\Node; @@ -25,7 +25,7 @@ public function __construct( protected string $mountPoint, protected string $mountProvider, protected ?int $mountId = null, - protected string $rootInternalPath = '', + protected ICacheEntry $rootCacheEntry, ) { if (strlen($this->mountProvider) > 128) { throw new \Exception("Mount provider $this->mountProvider name exceeds the limit of 128 characters"); @@ -60,7 +60,6 @@ public function getRootId(): int { #[\Override] public function getMountPointNode(): ?Node { // TODO injection etc - Filesystem::initMountPoints($this->getUser()->getUID()); $userFolder = Server::get(IRootFolder::class)->getUserFolder($this->getUser()->getUID()); return $userFolder->getParent()->getFirstNodeById($this->getRootId()); } @@ -91,7 +90,7 @@ public function getMountId(): ?int { */ #[\Override] public function getRootInternalPath(): string { - return $this->rootInternalPath; + return $this->getRootCacheEntry()->getPath(); } #[\Override] @@ -103,4 +102,9 @@ public function getMountProvider(): string { public function getKey(): string { return $this->key; } + + #[\Override] + public function getRootCacheEntry(): ICacheEntry { + return $this->rootCacheEntry; + } } diff --git a/lib/private/Files/Config/LazyPathCachedMountInfo.php b/lib/private/Files/Config/LazyPathCachedMountInfo.php deleted file mode 100644 index 556610cc56319..0000000000000 --- a/lib/private/Files/Config/LazyPathCachedMountInfo.php +++ /dev/null @@ -1,50 +0,0 @@ -rootInternalPathCallback = $rootInternalPathCallback; - } - - #[\Override] - public function getRootInternalPath(): string { - if ($this->rootInternalPath === self::PATH_PLACEHOLDER) { - $this->rootInternalPath = ($this->rootInternalPathCallback)($this); - } - return $this->rootInternalPath; - } -} diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php index 1b1e1c119fe3b..dcb40f8e36954 100644 --- a/lib/private/Files/Config/LazyStorageMountInfo.php +++ b/lib/private/Files/Config/LazyStorageMountInfo.php @@ -8,16 +8,25 @@ namespace OC\Files\Config; +use OCP\Files\Cache\ICacheEntry; +use OCP\Files\Cache\IScanner; +use OCP\Files\Config\ICachedMountInfo; +use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; +use OCP\Files\Node; use OCP\IUser; +use OCP\Server; + +class LazyStorageMountInfo implements ICachedMountInfo { + private ?string $key = null; + private ?int $storageId = null; + private ?int $rootId = null; + private ?ICacheEntry $rootCacheEntry = null; -class LazyStorageMountInfo extends CachedMountInfo { public function __construct( - IUser $user, - private IMountPoint $mount, + private readonly IUser $user, + private readonly IMountPoint $mount, ) { - parent::__construct($user, 0, 0, '', ''); - $this->key = ''; } /** @@ -25,10 +34,10 @@ public function __construct( */ #[\Override] public function getStorageId(): int { - if (!$this->storageId) { + if ($this->storageId === null) { $this->storageId = $this->mount->getNumericStorageId(); } - return parent::getStorageId(); + return $this->storageId; } /** @@ -36,10 +45,10 @@ public function getStorageId(): int { */ #[\Override] public function getRootId(): int { - if (!$this->rootId) { + if ($this->rootId === null) { $this->rootId = $this->mount->getStorageRootId(); } - return parent::getRootId(); + return $this->rootId; } /** @@ -47,10 +56,7 @@ public function getRootId(): int { */ #[\Override] public function getMountPoint(): string { - if (!$this->mountPoint) { - $this->mountPoint = $this->mount->getMountPoint(); - } - return parent::getMountPoint(); + return $this->mount->getMountPoint(); } #[\Override] @@ -75,9 +81,38 @@ public function getMountProvider(): string { #[\Override] public function getKey(): string { - if (!$this->key) { + if ($this->key === null) { $this->key = $this->getRootId() . '::' . $this->getMountPoint(); } return $this->key; } + + #[\Override] + public function getUser(): IUser { + return $this->user; + } + + #[\Override] + public function getMountPointNode(): ?Node { + $userFolder = Server::get(IRootFolder::class)->getUserFolder($this->getUser()->getUID()); + return $userFolder->getParent()->getFirstNodeById($this->getRootId()); + } + + #[\Override] + public function getRootCacheEntry(): ICacheEntry { + if ($this->rootCacheEntry === null) { + $storage = $this->mount->getStorage(); + $entry = $storage->getCache()->get($this->getRootInternalPath()); + if (!$entry) { + $storage->getScanner()->scan($this->getRootInternalPath(), IScanner::SCAN_SHALLOW); + $entry = $storage->getCache()->get($this->getRootInternalPath()); + } + if (!$entry) { + throw new \RuntimeException('Root of mount not found in cache, even after scanning'); + } + $this->rootCacheEntry = $entry; + } + return $this->rootCacheEntry; + } + } diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index 1430ab469eff3..2b63ddac96c69 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -9,6 +9,7 @@ namespace OC\Files\Config; use OC\DB\Exceptions\DbalException; +use OC\Files\Cache\Cache; use OC\User\LazyUser; use OCP\Cache\CappedMemoryCache; use OCP\DB\QueryBuilder\IQueryBuilder; @@ -21,6 +22,7 @@ use OCP\Files\Config\ICachedMountFileInfo; use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IUserMountCache; +use OCP\Files\IMimeTypeLoader; use OCP\Files\NotFoundException; use OCP\IDBConnection; use OCP\IUser; @@ -38,12 +40,6 @@ class UserMountCache implements IUserMountCache { * @var CappedMemoryCache **/ private CappedMemoryCache $mountsForUsers; - /** - * fileid => internal path mapping for cached mount info. - * - * @var CappedMemoryCache - **/ - private CappedMemoryCache $internalPathCache; /** @var CappedMemoryCache */ private CappedMemoryCache $cacheInfoCache; @@ -51,14 +47,14 @@ class UserMountCache implements IUserMountCache { * UserMountCache constructor. */ public function __construct( - private IDBConnection $connection, - private IUserManager $userManager, - private LoggerInterface $logger, - private IEventLogger $eventLogger, - private IEventDispatcher $eventDispatcher, + private readonly IDBConnection $connection, + private readonly IUserManager $userManager, + private readonly LoggerInterface $logger, + private readonly IEventLogger $eventLogger, + private readonly IEventDispatcher $eventDispatcher, + private readonly IMimeTypeLoader $mimeTypeLoader, ) { $this->cacheInfoCache = new CappedMemoryCache(); - $this->internalPathCache = new CappedMemoryCache(); $this->mountsForUsers = new CappedMemoryCache(); } @@ -214,36 +210,23 @@ private function removeFromCache(ICachedMountInfo $mount) { /** * @param array $row - * @param (callable(CachedMountInfo): string)|null $pathCallback - * @return CachedMountInfo + * @return ICachedMountInfo */ - private function dbRowToMountInfo(array $row, ?callable $pathCallback = null): ICachedMountInfo { + private function dbRowToMountInfo(array $row): ICachedMountInfo { $user = new LazyUser($row['user_id'], $this->userManager); $mount_id = $row['mount_id']; if (!is_null($mount_id)) { $mount_id = (int)$mount_id; } - if ($pathCallback) { - return new LazyPathCachedMountInfo( - $user, - (int)$row['storage_id'], - (int)$row['root_id'], - $row['mount_point'], - $row['mount_provider_class'] ?? '', - $mount_id, - $pathCallback, - ); - } else { - return new CachedMountInfo( - $user, - (int)$row['storage_id'], - (int)$row['root_id'], - $row['mount_point'], - $row['mount_provider_class'] ?? '', - $mount_id, - $row['path'] ?? '', - ); - } + return new CachedMountInfo( + $user, + (int)$row['storage_id'], + (int)$row['root_id'], + $row['mount_point'], + $row['mount_provider_class'] ?? '', + $mount_id, + Cache::cacheEntryFromData($row, $this->mimeTypeLoader), + ); } /** @@ -257,10 +240,8 @@ public function getMountsForUser(IUser $user) { return []; } if (!isset($this->mountsForUsers[$userUID])) { - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'mount_provider_class') - ->from('mounts', 'm') - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userUID))); + $query = $this->getSelectQuery(); + $query = $query->where($query->expr()->eq('user_id', $query->createNamedParameter($userUID))); $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); @@ -269,69 +250,49 @@ public function getMountsForUser(IUser $user) { /** @var array $mounts */ $mounts = []; foreach ($rows as $row) { - $mount = $this->dbRowToMountInfo($row, [$this, 'getInternalPathForMountInfo']); - if ($mount !== null) { - $mounts[$mount->getKey()] = $mount; - } + $mount = $this->dbRowToMountInfo($row); + $mounts[$mount->getKey()] = $mount; } $this->mountsForUsers[$userUID] = $mounts; } return $this->mountsForUsers[$userUID]; } - public function getInternalPathForMountInfo(CachedMountInfo $info): string { - $cached = $this->internalPathCache->get($info->getRootId()); - if ($cached !== null) { - return $cached; - } - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('path') - ->from('filecache') - ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($info->getRootId()))); - return $query->executeQuery()->fetchOne() ?: ''; - } - /** * @param int $numericStorageId * @param string|null $user limit the results to a single user - * @return CachedMountInfo[] + * @return ICachedMountInfo[] */ #[\Override] public function getMountsForStorageId($numericStorageId, $user = null) { - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class') - ->from('mounts', 'm') - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) - ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($numericStorageId, IQueryBuilder::PARAM_INT))); + $query = $this->getSelectQuery(); + $query->where($query->expr()->eq('storage_id', $query->createNamedParameter($numericStorageId, IQueryBuilder::PARAM_INT))); if ($user) { - $query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter($user))); + $query->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($user))); } $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); $result->closeCursor(); - return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); + return array_filter(array_map($this->dbRowToMountInfo(...), $rows)); } /** * @param int $rootFileId - * @return CachedMountInfo[] + * @return ICachedMountInfo[] */ #[\Override] public function getMountsForRootId($rootFileId) { - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class') - ->from('mounts', 'm') - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) - ->where($builder->expr()->eq('root_id', $builder->createNamedParameter($rootFileId, IQueryBuilder::PARAM_INT))); + $query = $this->getSelectQuery(); + $query->where($query->expr()->eq('root_id', $query->createNamedParameter($rootFileId, IQueryBuilder::PARAM_INT))); $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); $result->closeCursor(); - return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); + return array_filter(array_map($this->dbRowToMountInfo(...), $rows)); } /** @@ -377,24 +338,21 @@ public function getMountsForFileId($fileId, $user = null) { return []; } - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class') - ->from('mounts', 'm') - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) - ->where($builder->expr()->eq('m.storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) - ->andWhere($builder->expr()->eq('f.storage', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) + $query = $this->getSelectQuery(); + $query->where($query->expr()->eq('m.storage_id', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) + ->andWhere($query->expr()->eq('f.storage', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) ->andWhere( - $builder->expr()->orX( - $builder->expr()->eq('f.fileid', $builder->createNamedParameter($fileId)), - $builder->expr()->emptyString('f.path'), - $builder->expr()->eq( - $builder->func()->concat('f.path', $builder->createNamedParameter('/')), - $builder->func()->substring( - $builder->createNamedParameter($internalPath), - $builder->createNamedParameter(1, IQueryBuilder::PARAM_INT), - $builder->func()->add( - $builder->func()->charLength('f.path'), - $builder->createNamedParameter(1, IQueryBuilder::PARAM_INT), + $query->expr()->orX( + $query->expr()->eq('f.fileid', $query->createNamedParameter($fileId)), + $query->expr()->emptyString('f.path'), + $query->expr()->eq( + $query->func()->concat('f.path', $query->createNamedParameter('/')), + $query->func()->substring( + $query->createNamedParameter($internalPath), + $query->createNamedParameter(1, IQueryBuilder::PARAM_INT), + $query->func()->add( + $query->func()->charLength('f.path'), + $query->createNamedParameter(1, IQueryBuilder::PARAM_INT), ), ), ), @@ -402,26 +360,14 @@ public function getMountsForFileId($fileId, $user = null) { ); if ($user !== null) { - $query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter($user))); + $query->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($user))); } $result = $query->executeQuery(); $mounts = []; while ($row = $result->fetchAssociative()) { - if ($user === null && !$this->userManager->userExists($row['user_id'])) { - continue; - } - - $mounts[] = new CachedMountFileInfo( - new LazyUser($row['user_id'], $this->userManager), - (int)$row['storage_id'], - (int)$row['root_id'], - $row['mount_point'], - $row['mount_id'] === null ? null : (int)$row['mount_id'], - $row['mount_provider_class'] ?? '', - $row['path'] ?? '', - $internalPath, - ); + $mount = $this->dbRowToMountInfo($row); + $mounts[] = new CachedMountFileInfo($mount, $internalPath); } return $mounts; @@ -521,12 +467,9 @@ public function getMountForPath(IUser $user, string $path): ICachedMountInfo { } else { $searchPathHashes = array_map(static fn (string $path) => hash('xxh128', $path), $searchPaths); - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class') - ->from('mounts', 'm') - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($user->getUID()))) - ->andWhere($builder->expr()->in('mount_point_hash', $builder->createNamedParameter($searchPathHashes, IQueryBuilder::PARAM_STR_ARRAY))); + $query = $this->getSelectQuery(); + $query = $query->where($query->expr()->eq('user_id', $query->createNamedParameter($user->getUID()))) + ->andWhere($query->expr()->in('mount_point_hash', $query->createNamedParameter($searchPathHashes, IQueryBuilder::PARAM_STR_ARRAY))); foreach ($query->executeQuery()->fetchAll() as $row) { $mount = $this->dbRowToMountInfo($row); @@ -609,7 +552,6 @@ public function addMount( */ public function flush(): void { $this->cacheInfoCache = new CappedMemoryCache(); - $this->internalPathCache = new CappedMemoryCache(); $this->mountsForUsers = new CappedMemoryCache(); } @@ -624,15 +566,21 @@ public function getMountAtPath(IUser $user, string $mountPoint): ?ICachedMountIn return null; } - $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class') - ->from('mounts', 'm') - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($user->getUID()))) - ->andWhere($builder->expr()->eq('mount_point_hash', $builder->createNamedParameter(hash('xxh128', $mountPoint)))) + $query = $this->getSelectQuery(); + $query->where($query->expr()->eq('user_id', $query->createNamedParameter($user->getUID()))) + ->andWhere($query->expr()->eq('mount_point_hash', $query->createNamedParameter(hash('xxh128', $mountPoint)))) ->setMaxResults(1); $row = $query->executeQuery()->fetch(); return $row ? $this->dbRowToMountInfo($row) : null; } + + private function getSelectQuery(): IQueryBuilder { + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'mount_provider_class') + ->addSelect('f.name', 'f.etag', 'f.path', 'f.path_hash', 'f.checksum', 'f.fileid', 'f.parent', 'f.size', 'f.unencrypted_size', 'f.mtime', 'f.storage_mtime', 'f.encrypted', 'f.storage', 'f.mimetype', 'f.mimepart', 'f.permissions') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')); + return $builder; + } } diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php index 92505907584bf..63953084b936c 100644 --- a/lib/private/Files/FileInfo.php +++ b/lib/private/Files/FileInfo.php @@ -162,6 +162,11 @@ public function getMimePart() { return $this->data['mimepart']; } + #[\Override] + public function getStorageId(): int { + return $this->getMountPoint()->getNumericStorageId(); + } + /** * @return string */ diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php index 22a36fd583472..a63b6daa2caba 100644 --- a/lib/private/Files/Mount/MountPoint.php +++ b/lib/private/Files/Mount/MountPoint.php @@ -159,14 +159,14 @@ public function getStorage() { } /** - * @return string|null + * @return string */ #[\Override] public function getStorageId() { if (!$this->storageId) { $storage = $this->getStorage(); if (is_null($storage)) { - return null; + return 'invalid'; } $this->storageId = $storage->getId(); if (strlen($this->storageId) > 64) { diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php index afa875e6e8388..abfa90f91c713 100644 --- a/lib/private/Files/Node/LazyFolder.php +++ b/lib/private/Files/Node/LazyFolder.php @@ -165,6 +165,11 @@ public function getStorage() { return $this->__call(__FUNCTION__, func_get_args()); } + #[\Override] + public function getStorageId(): int { + return $this->__call(__FUNCTION__, func_get_args()); + } + /** * @inheritDoc */ diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php index 0de86b92efd8e..a2841f9a4c0a7 100644 --- a/lib/private/Files/Node/Node.php +++ b/lib/private/Files/Node/Node.php @@ -152,6 +152,11 @@ public function getStorage() { return $storage; } + #[\Override] + public function getStorageId(): int { + return $this->getMountPoint()->getNumericStorageId(); + } + /** * @return string */ diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index af5d466a63d4b..6f99618828e2e 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -204,6 +204,11 @@ public function getStorage() { throw new NotFoundException(); } + #[\Override] + public function getStorageId(): int { + throw new NotFoundException(); + } + /** * @return string */ diff --git a/lib/public/Files/Config/ICachedMountFileInfo.php b/lib/public/Files/Config/ICachedMountFileInfo.php index 921598c16241a..3d9c851bd0d20 100644 --- a/lib/public/Files/Config/ICachedMountFileInfo.php +++ b/lib/public/Files/Config/ICachedMountFileInfo.php @@ -7,11 +7,14 @@ namespace OCP\Files\Config; +use OCP\AppFramework\Attribute\Consumable; + /** * Holds information about a mount for a user * * @since 13.0.0 */ +#[Consumable(since: '13.0.0')] interface ICachedMountFileInfo extends ICachedMountInfo { /** * Return the path for the file within the cached mount diff --git a/lib/public/Files/Config/ICachedMountInfo.php b/lib/public/Files/Config/ICachedMountInfo.php index cd96806199326..e55d4fddd46f2 100644 --- a/lib/public/Files/Config/ICachedMountInfo.php +++ b/lib/public/Files/Config/ICachedMountInfo.php @@ -8,6 +8,7 @@ namespace OCP\Files\Config; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Node; use OCP\IUser; @@ -78,4 +79,10 @@ public function getMountProvider(): string; * @since 28.0.0 */ public function getKey(): string; + + /** + * @return ICacheEntry + * @since 36.0.0 + */ + public function getRootCacheEntry(): ICacheEntry; } diff --git a/lib/public/Files/FileInfo.php b/lib/public/Files/FileInfo.php index 4d93e57601447..058e02f65ba55 100644 --- a/lib/public/Files/FileInfo.php +++ b/lib/public/Files/FileInfo.php @@ -127,6 +127,15 @@ public function getMimePart(); */ public function getStorage(); + /** + * Get the numeric storage id for the storage backend the file or folder is stored on + * + * @return int + * @throws NotFoundException + * @since 36.0.0 + */ + public function getStorageId(): int; + /** * Get the file id of the file or folder * diff --git a/lib/public/Files/Mount/IMountPoint.php b/lib/public/Files/Mount/IMountPoint.php index ff06021ca888b..171e6aac541c1 100644 --- a/lib/public/Files/Mount/IMountPoint.php +++ b/lib/public/Files/Mount/IMountPoint.php @@ -40,7 +40,7 @@ public function getStorage(); /** * Get the id of the storages * - * @return string|null + * @return string * @since 8.0.0 */ public function getStorageId(); @@ -48,7 +48,7 @@ public function getStorageId(); /** * Get the id of the storages * - * @return int|null + * @return int * @since 9.1.0 */ public function getNumericStorageId(); diff --git a/lib/public/Files/Node.php b/lib/public/Files/Node.php index 727cb2f4da1c0..e45678259ff2a 100644 --- a/lib/public/Files/Node.php +++ b/lib/public/Files/Node.php @@ -75,6 +75,16 @@ public function touch($mtime = null); #[\Override] public function getStorage(); + /** + * Get the numeric storage id for the storage backend the file or folder is stored on + * + * @return int + * @throws NotFoundException + * @since 36.0.0 + */ + #[\Override] + public function getStorageId(): int; + /** * Get the full path of the file or folder * diff --git a/tests/lib/Files/Config/UserMountCacheTest.php b/tests/lib/Files/Config/UserMountCacheTest.php index ce5f318aa71aa..b10699aebe13c 100644 --- a/tests/lib/Files/Config/UserMountCacheTest.php +++ b/tests/lib/Files/Config/UserMountCacheTest.php @@ -23,6 +23,7 @@ use OCP\Files\Config\Event\UserMountRemovedEvent; use OCP\Files\Config\Event\UserMountUpdatedEvent; use OCP\Files\Config\ICachedMountInfo; +use OCP\Files\IMimeTypeLoader; use OCP\ICacheFactory; use OCP\IConfig; use OCP\IDBConnection; @@ -74,6 +75,7 @@ protected function setUp(): void { $this->createMock(LoggerInterface::class), $this->createMock(IEventLogger::class), $this->eventDispatcher, + $this->createMock(IMimeTypeLoader::class), ); } @@ -557,12 +559,15 @@ public function testGetUsedSpaceForUsers(): void { $user1 = $this->userManager->get('u1'); $user2 = $this->userManager->get('u2'); + $query = $this->connection->getQueryBuilder(); + $query->delete('filecache') + ->where($query->expr()->eq('storage', $query->createNamedParameter(2))); + $query->executeStatement(); + /** @var Storage $storage1 */ [$storage1, $rootId] = $this->getStorage(2); - $folderId = $this->createCacheEntry('files', 2, 100); - $fileId = $this->createCacheEntry('files/foo', 2, 7); - $storage1->getCache()->put($folderId, ['size' => 100]); - $storage1->getCache()->update($fileId, ['size' => 70]); + $this->createCacheEntry('files', 2, 100); + $this->createCacheEntry('files/foo', 2, 7); $mount1 = $this->getMockBuilder(MountPoint::class) ->setConstructorArgs([$storage1, '/u1/']) diff --git a/tests/lib/Files/Mount/MountPointTest.php b/tests/lib/Files/Mount/MountPointTest.php index bcbcc96e3a346..80b43da1be78b 100644 --- a/tests/lib/Files/Mount/MountPointTest.php +++ b/tests/lib/Files/Mount/MountPointTest.php @@ -64,7 +64,7 @@ public function testInvalidStorage(): void { // call it again to make sure the init code only ran once $this->assertNull($mountPoint->getStorage()); - $this->assertNull($mountPoint->getStorageId()); + $this->assertEquals('invalid', $mountPoint->getStorageId()); // wrapping doesn't fail $mountPoint->wrapStorage($wrapper); diff --git a/tests/lib/Files/Node/FolderTest.php b/tests/lib/Files/Node/FolderTest.php index 55632711b1883..1f6af8c155935 100644 --- a/tests/lib/Files/Node/FolderTest.php +++ b/tests/lib/Files/Node/FolderTest.php @@ -519,7 +519,7 @@ public function testGetById(): void { $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); - $fileInfo = new CacheEntry(['path' => 'foo/qwerty', 'mimetype' => 'text/plain'], null); + $fileInfo = new CacheEntry(['path' => 'foo/qwerty', 'mimetype' => 'text/plain']); $storage->method('getCache') ->willReturn($cache); @@ -536,7 +536,7 @@ public function testGetById(): void { '/bar/', 'test', 1, - '' + $fileInfo )]); $cache->method('get') @@ -570,7 +570,7 @@ public function testGetByIdMountRoot(): void { $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); - $fileInfo = new CacheEntry(['path' => '', 'mimetype' => 'text/plain'], null); + $fileInfo = new CacheEntry(['path' => '', 'mimetype' => 'text/plain']); $storage->method('getCache') ->willReturn($cache); @@ -587,7 +587,7 @@ public function testGetByIdMountRoot(): void { '/bar/', 'test', 1, - '' + $fileInfo )]); $cache->method('get') @@ -617,7 +617,7 @@ public function testGetByIdOutsideFolder(): void { $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); - $fileInfo = new CacheEntry(['path' => 'foobar', 'mimetype' => 'text/plain'], null); + $fileInfo = new CacheEntry(['path' => 'foobar', 'mimetype' => 'text/plain']); $storage->method('getCache') ->willReturn($cache); @@ -634,7 +634,7 @@ public function testGetByIdOutsideFolder(): void { '/bar/', 'test', 1, - '' + $fileInfo )]); $cache->method('get') @@ -664,7 +664,7 @@ public function testGetByIdMultipleStorages(): void { $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); - $fileInfo = new CacheEntry(['path' => 'foo/qwerty', 'mimetype' => 'text/plain'], null); + $fileInfo = new CacheEntry(['path' => 'foo/qwerty', 'mimetype' => 'text/plain']); $storage->method('getCache') ->willReturn($cache); @@ -681,7 +681,7 @@ public function testGetByIdMultipleStorages(): void { '/bar/', 'test', 1, - '' + $fileInfo ), new CachedMountInfo( $this->user, @@ -690,7 +690,7 @@ public function testGetByIdMultipleStorages(): void { '/bar/foo/asd/', 'test', 1, - '' + $fileInfo ), ]);