Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: improve getMountsForFileId memory usage and performance
Signed-off-by: Robin Appelman <[email protected]>
  • Loading branch information
icewind1991 committed Mar 19, 2025
commit 786fd2b31df1a87310bc12a0400d548b99789837
70 changes: 45 additions & 25 deletions lib/private/Files/Config/UserMountCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,34 +352,54 @@ public function getMountsForFileId($fileId, $user = null) {
} 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;
}
$internalMountPath = $mount->getRootInternalPath();
$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),
),
),
),
));

return $internalMountPath === '' || str_starts_with($internalPath, $internalMountPath . '/');
});
if ($user) {
$query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter($user)));
}

$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);
$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,
);
}
}

return $mounts;
}

/**
Expand Down