aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/Command/Info/FileUtils.php13
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php4
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php4
-rw-r--r--lib/private/Files/Config/UserMountCache.php126
-rw-r--r--lib/private/Files/Node/Root.php4
-rw-r--r--lib/private/Files/SetupManager.php22
6 files changed, 100 insertions, 73 deletions
diff --git a/core/Command/Info/FileUtils.php b/core/Command/Info/FileUtils.php
index 6c490d31c3d..fb9b5add080 100644
--- a/core/Command/Info/FileUtils.php
+++ b/core/Command/Info/FileUtils.php
@@ -46,13 +46,12 @@ class FileUtils {
$mounts = $this->userMountCache->getMountsForFileId($id);
$result = [];
- foreach ($mounts as $mount) {
- if (isset($result[$mount->getUser()->getUID()])) {
- continue;
- }
-
- $userFolder = $this->rootFolder->getUserFolder($mount->getUser()->getUID());
- $result[$mount->getUser()->getUID()] = $userFolder->getById($id);
+ foreach ($mounts as $cachedMount) {
+ $mount = $this->rootFolder->getMount($cachedMount->getMountPoint());
+ $cache = $mount->getStorage()->getCache();
+ $cacheEntry = $cache->get($id);
+ $node = $this->rootFolder->getNodeFromCacheEntryAndMount($cacheEntry, $mount);
+ $result[$cachedMount->getUser()->getUID()][] = $node;
}
return $result;
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php
index a8dc4d8cf14..d8536a9fc65 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php
@@ -80,12 +80,12 @@ class OCIFunctionBuilder extends FunctionBuilder {
public function octetLength($field, $alias = ''): IQueryFunction {
$alias = $alias ? (' AS ' . $this->helper->quoteColumnName($alias)) : '';
$quotedName = $this->helper->quoteColumnName($field);
- return new QueryFunction('LENGTHB(' . $quotedName . ')' . $alias);
+ return new QueryFunction('COALESCE(LENGTHB(' . $quotedName . '), 0)' . $alias);
}
public function charLength($field, $alias = ''): IQueryFunction {
$alias = $alias ? (' AS ' . $this->helper->quoteColumnName($alias)) : '';
$quotedName = $this->helper->quoteColumnName($field);
- return new QueryFunction('LENGTH(' . $quotedName . ')' . $alias);
+ return new QueryFunction('COALESCE(LENGTH(' . $quotedName . '), 0)' . $alias);
}
}
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index 0e103690b6b..d120e59b766 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -238,4 +238,8 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
public function getProviders(): array {
return $this->providers;
}
+
+ public function getHomeProviders(): array {
+ return $this->homeProviders;
+ }
}
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index 67b2cad7ea2..1786dc8f0de 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -5,10 +5,12 @@
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
+
namespace OC\Files\Config;
use OC\User\LazyUser;
use OCP\Cache\CappedMemoryCache;
+use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Diagnostics\IEventLogger;
use OCP\Files\Config\ICachedMountFileInfo;
@@ -29,11 +31,13 @@ class UserMountCache implements IUserMountCache {
/**
* Cached mount info.
+ *
* @var CappedMemoryCache<ICachedMountInfo[]>
**/
private CappedMemoryCache $mountsForUsers;
/**
* fileid => internal path mapping for cached mount info.
+ *
* @var CappedMemoryCache<string>
**/
private CappedMemoryCache $internalPathCache;
@@ -191,6 +195,19 @@ class UserMountCache implements IUserMountCache {
}
/**
+ * @param IResult $result
+ * @return CachedMountInfo[]
+ */
+ private function fetchMountInfo(IResult $result, ?callable $pathCallback = null): array {
+ $mounts = [];
+ while ($row = $result->fetch()) {
+ $mount = $this->dbRowToMountInfo($row, $pathCallback);
+ $mounts[] = $mount;
+ }
+ return $mounts;
+ }
+
+ /**
* @param array $row
* @param (callable(CachedMountInfo): string)|null $pathCallback
* @return CachedMountInfo
@@ -239,19 +256,11 @@ class UserMountCache implements IUserMountCache {
->from('mounts', 'm')
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userUID)));
- $result = $query->execute();
- $rows = $result->fetchAll();
- $result->closeCursor();
-
- /** @var array<string, ICachedMountInfo> $mounts */
- $mounts = [];
- foreach ($rows as $row) {
- $mount = $this->dbRowToMountInfo($row, [$this, 'getInternalPathForMountInfo']);
- if ($mount !== null) {
- $mounts[$mount->getKey()] = $mount;
- }
- }
- $this->mountsForUsers[$userUID] = $mounts;
+ $mounts = $this->fetchMountInfo($query->execute(), [$this, 'getInternalPathForMountInfo']);
+ $keys = array_map(function (ICachedMountInfo $mount) {
+ return $mount->getKey();
+ }, $mounts);
+ $this->mountsForUsers[$userUID] = array_combine($keys, $mounts);
}
return $this->mountsForUsers[$userUID];
}
@@ -274,8 +283,9 @@ class UserMountCache implements IUserMountCache {
* @return CachedMountInfo[]
*/
public function getMountsForStorageId($numericStorageId, $user = null) {
+ $mounts = [];
$builder = $this->connection->getQueryBuilder();
- $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
+ $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($numericStorageId, IQueryBuilder::PARAM_INT)));
@@ -284,11 +294,7 @@ class UserMountCache implements IUserMountCache {
$query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter($user)));
}
- $result = $query->execute();
- $rows = $result->fetchAll();
- $result->closeCursor();
-
- return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows));
+ return $this->fetchMountInfo($query->executeQuery());
}
/**
@@ -302,11 +308,7 @@ class UserMountCache implements IUserMountCache {
->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
->where($builder->expr()->eq('root_id', $builder->createNamedParameter($rootFileId, IQueryBuilder::PARAM_INT)));
- $result = $query->execute();
- $rows = $result->fetchAll();
- $result->closeCursor();
-
- return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows));
+ return $this->fetchMountInfo($query->executeQuery());
}
/**
@@ -329,7 +331,7 @@ class UserMountCache implements IUserMountCache {
$this->cacheInfoCache[$fileId] = [
(int)$row['storage'],
(string)$row['path'],
- (int)$row['mimetype']
+ (int)$row['mimetype'],
];
} else {
throw new NotFoundException('File with id "' . $fileId . '" not found');
@@ -350,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;
- }
- $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;
}
/**
@@ -421,7 +443,7 @@ class UserMountCache implements IUserMountCache {
$mountPoint = $builder->func()->concat(
$builder->func()->concat($slash, 'user_id'),
- $slash
+ $slash,
);
$userIds = array_map(function (IUser $user) {
@@ -433,7 +455,7 @@ class UserMountCache implements IUserMountCache {
->innerJoin('m', 'filecache', 'f',
$builder->expr()->andX(
$builder->expr()->eq('m.storage_id', 'f.storage'),
- $builder->expr()->eq('f.path_hash', $builder->createNamedParameter(md5('files')))
+ $builder->expr()->eq('f.path_hash', $builder->createNamedParameter(md5('files'))),
))
->where($builder->expr()->eq('m.mount_point', $mountPoint))
->andWhere($builder->expr()->in('m.user_id', $builder->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY)));
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index 5fb4013cfc9..1563e858bba 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -513,9 +513,9 @@ class Root extends Folder implements IRootFolder {
$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
$view = new View('');
if ($isDir) {
- return new Folder($this, $view, $path, $info, $parent);
+ return new Folder($this, $view, $fullPath, $info, $parent);
} else {
- return new File($this, $view, $path, $info, $parent);
+ return new File($this, $view, $fullPath, $info, $parent);
}
}
}
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 4d1e379ea58..51b68d06166 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -271,18 +271,20 @@ class SetupManager {
private function afterUserFullySetup(IUser $user, array $previouslySetupProviders): void {
$this->eventLogger->start('fs:setup:user:full:post', 'Housekeeping after user is setup');
$userRoot = '/' . $user->getUID() . '/';
- $mounts = $this->mountManager->getAll();
- $mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
- return str_starts_with($mount->getMountPoint(), $userRoot);
- });
- $allProviders = array_map(function (IMountProvider $provider) {
+ $allProviders = array_map(function ($provider) {
return get_class($provider);
- }, $this->mountProviderCollection->getProviders());
+ }, array_merge($this->mountProviderCollection->getProviders(), $this->mountProviderCollection->getHomeProviders()));
$newProviders = array_diff($allProviders, $previouslySetupProviders);
- $mounts = array_filter($mounts, function (IMountPoint $mount) use ($previouslySetupProviders) {
- return !in_array($mount->getMountProvider(), $previouslySetupProviders);
- });
- $this->userMountCache->registerMounts($user, $mounts, $newProviders);
+ if (count($newProviders) > 0) {
+ $mounts = $this->mountManager->getAll();
+ $mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot, $previouslySetupProviders) {
+ if (!str_starts_with($mount->getMountPoint(), $userRoot)) {
+ return false;
+ }
+ return !in_array($mount->getMountProvider(), $previouslySetupProviders);
+ });
+ $this->userMountCache->registerMounts($user, $mounts, $newProviders);
+ }
$cacheDuration = $this->config->getSystemValueInt('fs_mount_cache_duration', 5 * 60);
if ($cacheDuration > 0) {