diff options
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Collaboration/Reference/File/FileReferenceProvider.php | 8 | ||||
-rw-r--r-- | lib/private/DirectEditing/Manager.php | 6 | ||||
-rw-r--r-- | lib/private/Files/Config/CachedMountInfo.php | 7 | ||||
-rw-r--r-- | lib/private/Files/Node/Folder.php | 6 | ||||
-rw-r--r-- | lib/private/Files/Node/LazyFolder.php | 6 | ||||
-rw-r--r-- | lib/private/Files/Node/LazyRoot.php | 5 | ||||
-rw-r--r-- | lib/private/Files/Node/LazyUserFolder.php | 12 | ||||
-rw-r--r-- | lib/private/Files/Node/NonExistingFolder.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Node/Root.php | 32 | ||||
-rw-r--r-- | lib/private/FilesMetadata/Job/UpdateSingleMetadata.php | 7 | ||||
-rw-r--r-- | lib/private/Server.php | 5 | ||||
-rw-r--r-- | lib/private/Share20/Manager.php | 6 | ||||
-rw-r--r-- | lib/private/Share20/Share.php | 14 | ||||
-rw-r--r-- | lib/private/SpeechToText/TranscriptionJob.php | 2 |
14 files changed, 75 insertions, 45 deletions
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php index 5f384213976..125649246df 100644 --- a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php +++ b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php @@ -31,7 +31,6 @@ use OCP\Collaboration\Reference\Reference; use OCP\Files\IMimeTypeDetector; use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; -use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OCP\IL10N; @@ -121,15 +120,12 @@ class FileReferenceProvider extends ADiscoverableReferenceProvider { try { $userFolder = $this->rootFolder->getUserFolder($this->userId); - $files = $userFolder->getById($fileId); + $file = $userFolder->getFirstNodeById($fileId); - if (empty($files)) { + if (!$file) { throw new NotFoundException(); } - /** @var Node $file */ - $file = array_shift($files); - $reference->setTitle($file->getName()); $reference->setDescription($file->getMimetype()); $reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId)); diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php index d1be1f50330..da4811589da 100644 --- a/lib/private/DirectEditing/Manager.php +++ b/lib/private/DirectEditing/Manager.php @@ -310,11 +310,11 @@ class Manager implements IManager { if ($filePath !== null) { return $userFolder->get($filePath); } - $files = $userFolder->getById($fileId); - if (count($files) === 0) { + $file = $userFolder->getFirstNodeById($fileId); + if (!$file) { throw new NotFoundException('File nound found by id ' . $fileId); } - return $files[0]; + return $file; } public function isEnabled(): bool { diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php index 7c97135a565..19fa87aa090 100644 --- a/lib/private/Files/Config/CachedMountInfo.php +++ b/lib/private/Files/Config/CachedMountInfo.php @@ -97,12 +97,7 @@ class CachedMountInfo implements ICachedMountInfo { // TODO injection etc Filesystem::initMountPoints($this->getUser()->getUID()); $userNode = \OC::$server->getUserFolder($this->getUser()->getUID()); - $nodes = $userNode->getParent()->getById($this->getRootId()); - if (count($nodes) > 0) { - return $nodes[0]; - } else { - return null; - } + return $userNode->getParent()->getFirstNodeById($this->getRootId()); } /** diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php index c7462572fed..014b66fdf63 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -307,12 +307,16 @@ class Folder extends Node implements \OCP\Files\Folder { /** * @param int $id - * @return \OC\Files\Node\Node[] + * @return \OCP\Files\Node[] */ public function getById($id) { return $this->root->getByIdInPath((int)$id, $this->getPath()); } + public function getFirstNodeById(int $id): ?\OCP\Files\Node { + return current($this->getById($id)) ?: null; + } + protected function getAppDataDirectoryName(): string { $instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid'); return 'appdata_' . $instanceId; diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php index e30cfea693e..4aae5cf9804 100644 --- a/lib/private/Files/Node/LazyFolder.php +++ b/lib/private/Files/Node/LazyFolder.php @@ -492,7 +492,11 @@ class LazyFolder implements Folder { * @inheritDoc */ public function getById($id) { - return $this->__call(__FUNCTION__, func_get_args()); + return $this->getRootFolder()->getByIdInPath((int)$id, $this->getPath()); + } + + public function getFirstNodeById(int $id): ?\OCP\Files\Node { + return $this->getRootFolder()->getFirstNodeByIdInPath($id, $this->getPath()); } /** diff --git a/lib/private/Files/Node/LazyRoot.php b/lib/private/Files/Node/LazyRoot.php index 680e80cb45e..dd1596319fa 100644 --- a/lib/private/Files/Node/LazyRoot.php +++ b/lib/private/Files/Node/LazyRoot.php @@ -25,6 +25,7 @@ namespace OC\Files\Node; use OCP\Files\Cache\ICacheEntry; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; +use OCP\Files\Node; use OCP\Files\Node as INode; /** @@ -56,6 +57,10 @@ class LazyRoot extends LazyFolder implements IRootFolder { return $this->__call(__FUNCTION__, func_get_args()); } + public function getFirstNodeByIdInPath(int $id, string $path): ?Node { + return $this->__call(__FUNCTION__, func_get_args()); + } + public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode { return $this->getRootFolder()->getNodeFromCacheEntryAndMount($cacheEntry, $mountPoint); } diff --git a/lib/private/Files/Node/LazyUserFolder.php b/lib/private/Files/Node/LazyUserFolder.php index 917ab80f366..3cb840ccb6d 100644 --- a/lib/private/Files/Node/LazyUserFolder.php +++ b/lib/private/Files/Node/LazyUserFolder.php @@ -68,18 +68,6 @@ class LazyUserFolder extends LazyFolder { ]); } - public function get($path) { - return $this->getRootFolder()->get('/' . $this->user->getUID() . '/files/' . ltrim($path, '/')); - } - - /** - * @param int $id - * @return \OCP\Files\Node[] - */ - public function getById($id) { - return $this->getRootFolder()->getByIdInPath((int)$id, $this->getPath()); - } - public function getMountPoint() { if ($this->folder !== null) { return $this->folder->getMountPoint(); diff --git a/lib/private/Files/Node/NonExistingFolder.php b/lib/private/Files/Node/NonExistingFolder.php index 34621b18f19..af0ad002f24 100644 --- a/lib/private/Files/Node/NonExistingFolder.php +++ b/lib/private/Files/Node/NonExistingFolder.php @@ -162,6 +162,10 @@ class NonExistingFolder extends Folder { throw new NotFoundException(); } + public function getFirstNodeById(int $id): ?\OCP\Files\Node { + throw new NotFoundException(); + } + public function getFreeSpace() { throw new NotFoundException(); } diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index 9bfb610199b..71bc7a6da6b 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -49,6 +49,8 @@ use OCP\Files\Mount\IMountPoint; use OCP\Files\Node as INode; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IUser; use OCP\IUserManager; use Psr\Log\LoggerInterface; @@ -81,6 +83,7 @@ class Root extends Folder implements IRootFolder { private LoggerInterface $logger; private IUserManager $userManager; private IEventDispatcher $eventDispatcher; + private ICache $pathByIdCache; /** * @param Manager $manager @@ -94,7 +97,8 @@ class Root extends Folder implements IRootFolder { IUserMountCache $userMountCache, LoggerInterface $logger, IUserManager $userManager, - IEventDispatcher $eventDispatcher + IEventDispatcher $eventDispatcher, + ICacheFactory $cacheFactory, ) { parent::__construct($this, $view, ''); $this->mountManager = $manager; @@ -107,6 +111,7 @@ class Root extends Folder implements IRootFolder { $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () { $this->userFolderCache = new CappedMemoryCache(); }); + $this->pathByIdCache = $cacheFactory->createLocal('path-by-id'); } /** @@ -405,6 +410,31 @@ class Root extends Folder implements IRootFolder { return $this->userMountCache; } + public function getFirstNodeByIdInPath(int $id, string $path): ?INode { + // scope the cache by user, so we don't return nodes for different users + if ($this->user) { + $cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id); + if ($cachedPath && str_starts_with($path, $cachedPath)) { + // getting the node by path is significantly cheaper than finding it by id + $node = $this->get($cachedPath); + // by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path + // if the cached path is invalid or a different file now we fall back to the uncached logic + if ($node && $node->getId() === $id) { + return $node; + } + } + } + $node = current($this->getByIdInPath($id, $path)); + if (!$node) { + return null; + } + + if ($this->user) { + $this->pathByIdCache->set($this->user->getUID() . '::' . $id, $node->getPath()); + } + return $node; + } + /** * @param int $id * @return Node[] diff --git a/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php b/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php index d18c8aa3680..3a3b35ce205 100644 --- a/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php +++ b/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php @@ -55,10 +55,9 @@ class UpdateSingleMetadata extends QueuedJob { [$userId, $fileId] = $argument; try { - $node = $this->rootFolder->getUserFolder($userId)->getById($fileId); - if (count($node) > 0) { - $file = array_shift($node); - $this->filesMetadataManager->refreshMetadata($file, IFilesMetadataManager::PROCESS_BACKGROUND); + $node = $this->rootFolder->getUserFolder($userId)->getFirstNodeById($fileId); + if ($node) { + $this->filesMetadataManager->refreshMetadata($node, IFilesMetadataManager::PROCESS_BACKGROUND); } } catch (\Exception $e) { $this->logger->warning('issue while running UpdateSingleMetadata', ['exception' => $e, 'userId' => $userId, 'fileId' => $fileId]); diff --git a/lib/private/Server.php b/lib/private/Server.php index df267839160..40c226bdf81 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -450,14 +450,17 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('RootFolder', function (ContainerInterface $c) { $manager = \OC\Files\Filesystem::getMountManager(); $view = new View(); + /** @var IUserSession $userSession */ + $userSession = $c->get(IUserSession::class); $root = new Root( $manager, $view, - null, + $userSession->getUser(), $c->get(IUserMountCache::class), $this->get(LoggerInterface::class), $this->get(IUserManager::class), $this->get(IEventDispatcher::class), + $this->get(ICacheFactory::class), ); $previewConnector = new \OC\Preview\WatcherConnector( diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 53f88cf14ce..c1abaff2ec0 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -311,8 +311,7 @@ class Manager implements IManager { $mount = $userMount->getMountPoint(); // When it's a reshare use the parent share permissions as maximum $userMountPointId = $mount->getStorageRootId(); - $userMountPoints = $userFolder->getById($userMountPointId); - $userMountPoint = array_shift($userMountPoints); + $userMountPoint = $userFolder->getFirstNodeById($userMountPointId); if ($userMountPoint === null) { throw new GenericShareException('Could not get proper user mount for ' . $userMountPointId . '. Failing since else the next calls are called with null'); @@ -1723,8 +1722,7 @@ class Manager implements IManager { //Get node for the owner and correct the owner in case of external storage $userFolder = $this->rootFolder->getUserFolder($owner); if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) { - $nodes = $userFolder->getById($path->getId()); - $path = array_shift($nodes); + $path = $userFolder->getFirstNodeById($path->getId()); if ($path === null || $path->getOwner() === null) { return []; } diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index c80d332e9db..19b36cb60e8 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -188,12 +188,12 @@ class Share implements IShare { $userFolder = $this->rootFolder->getUserFolder($this->sharedBy); } - $nodes = $userFolder->getById($this->fileId); - if (empty($nodes)) { + $node = $userFolder->getFirstNodeById($this->fileId); + if (!$node) { throw new NotFoundException('Node for share not found, fileid: ' . $this->fileId); } - $this->node = $nodes[0]; + $this->node = $node; } return $this->node; @@ -211,12 +211,16 @@ class Share implements IShare { /** * @inheritdoc */ - public function getNodeId() { + public function getNodeId(): int { if ($this->fileId === null) { $this->fileId = $this->getNode()->getId(); } - return $this->fileId; + if ($this->fileId === null) { + throw new NotFoundException("Share source not found"); + } else { + return $this->fileId; + } } /** diff --git a/lib/private/SpeechToText/TranscriptionJob.php b/lib/private/SpeechToText/TranscriptionJob.php index 8921d52ecd1..083cd129657 100644 --- a/lib/private/SpeechToText/TranscriptionJob.php +++ b/lib/private/SpeechToText/TranscriptionJob.php @@ -65,7 +65,7 @@ class TranscriptionJob extends QueuedJob { try { \OC_Util::setupFS($owner); $userFolder = $this->rootFolder->getUserFolder($owner); - $file = current($userFolder->getById($fileId)); + $file = $userFolder->getFirstNodeById($fileId); if (!($file instanceof File)) { $this->logger->warning('Transcription of file ' . $fileId . ' failed. The file could not be found'); $this->eventDispatcher->dispatchTyped( |