From 786fd2b31df1a87310bc12a0400d548b99789837 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 6 Mar 2025 18:06:51 +0100 Subject: [PATCH] fix: improve getMountsForFileId memory usage and performance Signed-off-by: Robin Appelman --- lib/private/Files/Config/UserMountCache.php | 70 +++++++++++++-------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index fa7bbe9b9cd..1786dc8f0de 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -352,34 +352,54 @@ class UserMountCache implements IUserMountCache { } catch (NotFoundException $e) { return []; } - $mountsForStorage = $this->getMountsForStorageId($storageId, $user); - // filter mounts that are from the same storage but not a parent of the file we care about - $filteredMounts = array_filter($mountsForStorage, function (ICachedMountInfo $mount) use ($internalPath, $fileId) { - if ($fileId === $mount->getRootId()) { - return true; + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select('id', '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($storageId, IQueryBuilder::PARAM_INT))) + ->andWhere($builder->expr()->orX( + // filter mounts that are from the same storage but not a parent of the file we care about + $builder->expr()->eq('f.fileid', $builder->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)), + $builder->expr()->eq('f.path', $builder->createNamedParameter('')), + $builder->expr()->isNull('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), + ), + ), + ), + )); + + if ($user) { + $query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter($user))); + } + + $result = $query->executeQuery(); + $mounts = []; + while ($row = $result->fetch()) { + $user = $this->userManager->get($row['user_id']); + + if ($user) { + $mounts[] = new CachedMountFileInfo( + $user, + (int)$row['storage_id'], + (int)$row['root_id'], + $row['mount_point'], + $row['mount_id'] ? (int)$row['mount_id'] : null, + $row['mount_provider_class'] ?? '', + $row['path'] ?? '', + $internalPath, + ); } - $internalMountPath = $mount->getRootInternalPath(); + } - return $internalMountPath === '' || str_starts_with($internalPath, $internalMountPath . '/'); - }); - - $filteredMounts = array_values(array_filter($filteredMounts, function (ICachedMountInfo $mount) { - return $this->userManager->userExists($mount->getUser()->getUID()); - })); - - return array_map(function (ICachedMountInfo $mount) use ($internalPath) { - return new CachedMountFileInfo( - $mount->getUser(), - $mount->getStorageId(), - $mount->getRootId(), - $mount->getMountPoint(), - $mount->getMountId(), - $mount->getMountProvider(), - $mount->getRootInternalPath(), - $internalPath, - ); - }, $filteredMounts); + return $mounts; } /**