Skip to content

Commit 9c07e5a

Browse files
author
Carl Schwan
committed
feat(trashbin): Use a lazy folder for roots of trashbin
Introduze a LazyMountPoint which is similar to LazyFile/LazyFolder and allow to avoid doing DB request when we just want the storage id and we already have it. Signed-off-by: Carl Schwan <carl.schwan@nextclound.com>
1 parent 7af54bf commit 9c07e5a

7 files changed

Lines changed: 143 additions & 7 deletions

File tree

apps/dav/lib/DAV/CustomPropertiesBackend.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ public function propFind($path, PropFind $propFind) {
224224
$node = $this->tree->getNodeForPath($path);
225225
if (($node instanceof Directory) && $propFind->getDepth() !== 0) {
226226
$this->cacheDirectory($path, $node->getNode());
227-
} else if ($node instanceof TrashRoot) {
227+
} elseif ($node instanceof TrashRoot) {
228228
$trashNodes = $node->getTrashRoots();
229229
foreach ($trashNodes as $trashNode) {
230230
$this->cacheDirectory($path, $trashNode);

apps/files_trashbin/lib/Sabre/TrashRoot.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@
1414
use OCA\Files_Trashbin\Trashbin;
1515
use OCP\Files\FileInfo;
1616
use OCP\Files\Folder;
17-
use OCP\Files\IRootFolder;
18-
use OCP\Files\NotFoundException;
19-
use OCP\Files\NotPermittedException;
2017
use OCP\IUser;
21-
use OCP\Server;
2218
use Sabre\DAV\Exception\Forbidden;
2319
use Sabre\DAV\Exception\NotFound;
2420
use Sabre\DAV\ICollection;

apps/files_trashbin/lib/Trash/LegacyTrashBackend.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
55
* SPDX-License-Identifier: AGPL-3.0-or-later
66
*/
7+
78
namespace OCA\Files_Trashbin\Trash;
89

910
use OC\Files\Filesystem;
11+
use OC\Files\Node\LazyFolder;
1012
use OC\Files\View;
1113
use OCA\Files_Trashbin\Helper;
1214
use OCA\Files_Trashbin\Storage;
@@ -16,8 +18,10 @@
1618
use OCP\Files\IRootFolder;
1719
use OCP\Files\NotFoundException;
1820
use OCP\Files\Storage\IStorage;
21+
use OCP\IDBConnection;
1922
use OCP\IUser;
2023
use OCP\IUserManager;
24+
use OCP\Server;
2125

2226
class LegacyTrashBackend implements ITrashBackend {
2327
/** @var array */
@@ -121,6 +125,27 @@ public function getTrashNodeById(IUser $user, int $fileId) {
121125

122126
public function getTrashRootsForUser(IUser $user): array {
123127
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
124-
return [$userFolder->getParent()->get('files_trashbin/files')];
128+
$connection = Server::get(IDBConnection::class);
129+
$qb = $connection->getQueryBuilder();
130+
$qb->select('fileid', 'storage')
131+
->from('filecache')
132+
->hintShardKey('storage', $userFolder->getMountPoint()->getNumericStorageId())
133+
->where($qb->expr()->eq('path_hash', $qb->createNamedParameter(md5('files_trashbin/files'))));
134+
$result = $qb->executeQuery()->fetchAll();
135+
136+
if (!$result || !count($result)) {
137+
return [];
138+
}
139+
140+
return [
141+
new LazyFolder(
142+
$this->rootFolder,
143+
fn () => $userFolder->getParent()->get('files_trashbin/files'),
144+
[
145+
'fileid' => $result[0]['fileid'],
146+
'mountpoint_numericStorageId' => $result[0]['storage'],
147+
]
148+
)
149+
];
125150
}
126151
}

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,7 @@
16641664
'OC\\Files\\Lock\\LockManager' => $baseDir . '/lib/private/Files/Lock/LockManager.php',
16651665
'OC\\Files\\Mount\\CacheMountProvider' => $baseDir . '/lib/private/Files/Mount/CacheMountProvider.php',
16661666
'OC\\Files\\Mount\\HomeMountPoint' => $baseDir . '/lib/private/Files/Mount/HomeMountPoint.php',
1667+
'OC\\Files\\Mount\\LazyMountPoint' => $baseDir . '/lib/private/Files/Mount/LazyMountPoint.php',
16671668
'OC\\Files\\Mount\\LocalHomeMountProvider' => $baseDir . '/lib/private/Files/Mount/LocalHomeMountProvider.php',
16681669
'OC\\Files\\Mount\\Manager' => $baseDir . '/lib/private/Files/Mount/Manager.php',
16691670
'OC\\Files\\Mount\\MountPoint' => $baseDir . '/lib/private/Files/Mount/MountPoint.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
17051705
'OC\\Files\\Lock\\LockManager' => __DIR__ . '/../../..' . '/lib/private/Files/Lock/LockManager.php',
17061706
'OC\\Files\\Mount\\CacheMountProvider' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/CacheMountProvider.php',
17071707
'OC\\Files\\Mount\\HomeMountPoint' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/HomeMountPoint.php',
1708+
'OC\\Files\\Mount\\LazyMountPoint' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/LazyMountPoint.php',
17081709
'OC\\Files\\Mount\\LocalHomeMountProvider' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/LocalHomeMountProvider.php',
17091710
'OC\\Files\\Mount\\Manager' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/Manager.php',
17101711
'OC\\Files\\Mount\\MountPoint' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/MountPoint.php',
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
6+
* SPDX-License-Identifier: AGPL-3.0-only
7+
*/
8+
namespace OC\Files\Mount;
9+
10+
use OCP\Files\Mount\IMountPoint;
11+
12+
class LazyMountPoint implements IMountPoint {
13+
private ?IMountPoint $mountPoint = null;
14+
15+
/**
16+
* @param \Closure(): IMountPoint $mountPointClosure
17+
*/
18+
public function __construct(
19+
private readonly \Closure $mountPointClosure,
20+
private readonly array $data,
21+
) {
22+
}
23+
24+
private function getRealMountPoint(): IMountPoint {
25+
if ($this->mountPoint === null) {
26+
$this->mountPoint = call_user_func($this->mountPointClosure);
27+
}
28+
return $this->mountPoint;
29+
}
30+
31+
public function __call($method, $args) {
32+
return call_user_func_array([$this->getRealMountPoint(), $method], $args);
33+
}
34+
35+
public function getMountPoint() {
36+
return $this->__call(__FUNCTION__, func_get_args());
37+
}
38+
39+
public function setMountPoint($mountPoint) {
40+
return $this->__call(__FUNCTION__, func_get_args());
41+
}
42+
43+
private function createStorage() {
44+
return $this->__call(__FUNCTION__, func_get_args());
45+
}
46+
47+
public function getStorage() {
48+
return $this->__call(__FUNCTION__, func_get_args());
49+
}
50+
51+
public function getStorageId(): ?string {
52+
return $this->__call(__FUNCTION__, func_get_args());
53+
}
54+
55+
public function getNumericStorageId(): int {
56+
if (isset($this->data['numericStorageId'])) {
57+
return $this->data['numericStorageId'];
58+
}
59+
return $this->__call(__FUNCTION__, func_get_args());
60+
}
61+
62+
public function getInternalPath($path) {
63+
return $this->__call(__FUNCTION__, func_get_args());
64+
}
65+
66+
public function wrapStorage($wrapper): void {
67+
$this->__call(__FUNCTION__, func_get_args());
68+
}
69+
70+
public function getOption($name, $default) {
71+
return $this->__call(__FUNCTION__, func_get_args());
72+
}
73+
74+
public function getOptions(): array {
75+
return $this->__call(__FUNCTION__, func_get_args());
76+
}
77+
78+
public function getStorageRootId(): int {
79+
return $this->__call(__FUNCTION__, func_get_args());
80+
}
81+
82+
public function getMountId() {
83+
return $this->__call(__FUNCTION__, func_get_args());
84+
}
85+
86+
public function getMountType() {
87+
return $this->__call(__FUNCTION__, func_get_args());
88+
}
89+
90+
public function getMountProvider(): string {
91+
return $this->__call(__FUNCTION__, func_get_args());
92+
}
93+
}

lib/private/Files/Node/LazyFolder.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace OC\Files\Node;
99

1010
use OC\Files\Filesystem;
11+
use OC\Files\Mount\LazyMountPoint;
1112
use OC\Files\Utils\PathHelper;
1213
use OCP\Constants;
1314
use OCP\Files\Folder;
@@ -366,11 +367,30 @@ public function isMounted() {
366367
return $this->__call(__FUNCTION__, func_get_args());
367368
}
368369

370+
// TODO remove when we can depend on php 8.4
371+
private static function _array_any(array $array, callable $callback): bool {
372+
foreach ($array as $key => $value) {
373+
if ($callback($value, $key)) {
374+
return true;
375+
}
376+
}
377+
378+
return false;
379+
}
380+
369381
/**
370382
* @inheritDoc
371383
*/
372384
public function getMountPoint() {
373-
return $this->__call(__FUNCTION__, func_get_args());
385+
if (self::_array_any(array_keys($this->data), fn ($key) => str_starts_with($key, 'mountpoint_'))) {
386+
return new LazyMountPoint(function () {
387+
return $this->__call('getMountPoint', func_get_args());
388+
}, [
389+
'numericStorageId' => $this->data['mountpoint_numericStorageId'],
390+
]);
391+
} else {
392+
return $this->__call(__FUNCTION__, func_get_args());
393+
}
374394
}
375395

376396
/**

0 commit comments

Comments
 (0)