Skip to content

Commit 9cf6a2d

Browse files
Carl Schwansusnux
authored andcommitted
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 <carlschwan@kde.org>
1 parent 0e31a45 commit 9cf6a2d

10 files changed

Lines changed: 143 additions & 7 deletions

File tree

apps/dav/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@
268268
'OCA\\DAV\\Controller\\UpcomingEventsController' => $baseDir . '/../lib/Controller/UpcomingEventsController.php',
269269
'OCA\\DAV\\DAV\\CustomPropertiesBackend' => $baseDir . '/../lib/DAV/CustomPropertiesBackend.php',
270270
'OCA\\DAV\\DAV\\GroupPrincipalBackend' => $baseDir . '/../lib/DAV/GroupPrincipalBackend.php',
271+
'OCA\\DAV\\DAV\\ICacheableDirectory' => $baseDir . '/../lib/DAV/ICacheableDirectory.php',
271272
'OCA\\DAV\\DAV\\PublicAuth' => $baseDir . '/../lib/DAV/PublicAuth.php',
272273
'OCA\\DAV\\DAV\\RemoteUserPrincipalBackend' => $baseDir . '/../lib/DAV/RemoteUserPrincipalBackend.php',
273274
'OCA\\DAV\\DAV\\Security\\RateLimiting' => $baseDir . '/../lib/DAV/Security/RateLimiting.php',

apps/dav/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ class ComposerStaticInitDAV
283283
'OCA\\DAV\\Controller\\UpcomingEventsController' => __DIR__ . '/..' . '/../lib/Controller/UpcomingEventsController.php',
284284
'OCA\\DAV\\DAV\\CustomPropertiesBackend' => __DIR__ . '/..' . '/../lib/DAV/CustomPropertiesBackend.php',
285285
'OCA\\DAV\\DAV\\GroupPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/GroupPrincipalBackend.php',
286+
'OCA\\DAV\\DAV\\ICacheableDirectory' => __DIR__ . '/..' . '/../lib/DAV/ICacheableDirectory.php',
286287
'OCA\\DAV\\DAV\\PublicAuth' => __DIR__ . '/..' . '/../lib/DAV/PublicAuth.php',
287288
'OCA\\DAV\\DAV\\RemoteUserPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/RemoteUserPrincipalBackend.php',
288289
'OCA\\DAV\\DAV\\Security\\RateLimiting' => __DIR__ . '/..' . '/../lib/DAV/Security/RateLimiting.php',

apps/dav/lib/Connector/Sabre/Directory.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ class Directory extends Node implements
4848
\Sabre\DAV\IMoveTarget,
4949
\Sabre\DAV\ICopyTarget,
5050
INodeByPath,
51-
ICacheableDirectory
52-
{
51+
ICacheableDirectory {
5352
/**
5453
* Cached directory content
5554
* @var FileInfo[]

apps/dav/lib/DAV/ICacheableDirectory.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<?php
22

3+
declare (strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
39
namespace OCA\DAV\DAV;
410

511
use OCP\Files\Folder;

apps/files_trashbin/lib/Trash/ITrashBackend.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ public function getTrashNodeById(IUser $user, int $fileId);
7070

7171
/**
7272
* Returns a non-exhaustive list of folder which can then be used to pre-fetch some metadata
73-
* * for the trash root.
73+
* for the trash root.
7474
*
7575
* @return Folder[]
76-
* @since 32.0.0
76+
* @since 34.0.0
7777
*/
7878
public function getCacheableRootsForUser(IUser $user): array;
7979
}

apps/files_trashbin/lib/Trash/LegacyTrashBackend.php

Lines changed: 27 additions & 2 deletions
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 */
@@ -125,8 +129,29 @@ public function getTrashNodeById(IUser $user, int $fileId) {
125129
}
126130
}
127131

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

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,7 @@
17651765
'OC\\Files\\Lock\\LockManager' => $baseDir . '/lib/private/Files/Lock/LockManager.php',
17661766
'OC\\Files\\Mount\\CacheMountProvider' => $baseDir . '/lib/private/Files/Mount/CacheMountProvider.php',
17671767
'OC\\Files\\Mount\\HomeMountPoint' => $baseDir . '/lib/private/Files/Mount/HomeMountPoint.php',
1768+
'OC\\Files\\Mount\\LazyMountPoint' => $baseDir . '/lib/private/Files/Mount/LazyMountPoint.php',
17681769
'OC\\Files\\Mount\\LocalHomeMountProvider' => $baseDir . '/lib/private/Files/Mount/LocalHomeMountProvider.php',
17691770
'OC\\Files\\Mount\\Manager' => $baseDir . '/lib/private/Files/Mount/Manager.php',
17701771
'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
@@ -1806,6 +1806,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
18061806
'OC\\Files\\Lock\\LockManager' => __DIR__ . '/../../..' . '/lib/private/Files/Lock/LockManager.php',
18071807
'OC\\Files\\Mount\\CacheMountProvider' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/CacheMountProvider.php',
18081808
'OC\\Files\\Mount\\HomeMountPoint' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/HomeMountPoint.php',
1809+
'OC\\Files\\Mount\\LazyMountPoint' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/LazyMountPoint.php',
18091810
'OC\\Files\\Mount\\LocalHomeMountProvider' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/LocalHomeMountProvider.php',
18101811
'OC\\Files\\Mount\\Manager' => __DIR__ . '/../../..' . '/lib/private/Files/Mount/Manager.php',
18111812
'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: 10 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\Cache\ICacheEntry;
@@ -400,7 +401,15 @@ public function isMounted() {
400401
*/
401402
#[\Override]
402403
public function getMountPoint() {
403-
return $this->__call(__FUNCTION__, func_get_args());
404+
if (array_any(array_keys($this->data), fn ($key) => str_starts_with($key, 'mountpoint_'))) {
405+
return new LazyMountPoint(function () {
406+
return $this->__call('getMountPoint', func_get_args());
407+
}, [
408+
'numericStorageId' => $this->data['mountpoint_numericStorageId'],
409+
]);
410+
} else {
411+
return $this->__call(__FUNCTION__, func_get_args());
412+
}
404413
}
405414

406415
/**

0 commit comments

Comments
 (0)