Skip to content

Commit 9df9b4a

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 9df9b4a

6 files changed

Lines changed: 149 additions & 7 deletions

File tree

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: 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,15 +18,17 @@
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 */
2428
private $deletedFiles = [];
2529

2630
public function __construct(
27-
private IRootFolder $rootFolder,
31+
private IRootFolder $rootFolder,
2832
private IUserManager $userManager,
2933
) {
3034
}
@@ -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: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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 OC\Files\Filesystem;
11+
use OC\Files\Node\LazyFolder;
12+
use OC\Files\Storage\Storage;
13+
use OC\Files\Storage\StorageFactory;
14+
use OCP\Files\Mount\IMountPoint;
15+
use Psr\Log\LoggerInterface;
16+
17+
class LazyMountPoint implements IMountPoint {
18+
private ?IMountPoint $mountPoint = null;
19+
20+
/**
21+
* @param \Closure(): IMountPoint $mountPointClosure
22+
*/
23+
public function __construct(
24+
private readonly \Closure $mountPointClosure,
25+
private readonly array $data,
26+
) {
27+
}
28+
29+
private function getRealMountPoint(): IMountPoint {
30+
if ($this->mountPoint === null) {
31+
$this->mountPoint = call_user_func($this->mountPointClosure);
32+
}
33+
return $this->mountPoint;
34+
}
35+
36+
public function __call($method, $args) {
37+
return call_user_func_array([$this->getRealMountPoint(), $method], $args);
38+
}
39+
40+
public function getMountPoint() {
41+
return $this->__call(__FUNCTION__, func_get_args());
42+
}
43+
44+
public function setMountPoint($mountPoint) {
45+
return $this->__call(__FUNCTION__, func_get_args());
46+
}
47+
48+
private function createStorage() {
49+
return $this->__call(__FUNCTION__, func_get_args());
50+
}
51+
52+
public function getStorage() {
53+
return $this->__call(__FUNCTION__, func_get_args());
54+
}
55+
56+
public function getStorageId(): ?string {
57+
return $this->__call(__FUNCTION__, func_get_args());
58+
}
59+
60+
public function getNumericStorageId(): int {
61+
if (isset($this->data['numericStorageId'])) {
62+
return $this->data['numericStorageId'];
63+
}
64+
return $this->__call(__FUNCTION__, func_get_args());
65+
}
66+
67+
public function getInternalPath($path) {
68+
return $this->__call(__FUNCTION__, func_get_args());
69+
}
70+
71+
public function wrapStorage($wrapper): void {
72+
$this->__call(__FUNCTION__, func_get_args());
73+
}
74+
75+
public function getOption($name, $default) {
76+
return $this->__call(__FUNCTION__, func_get_args());
77+
}
78+
79+
public function getOptions(): array {
80+
return $this->__call(__FUNCTION__, func_get_args());
81+
}
82+
83+
public function getStorageRootId(): int {
84+
return $this->__call(__FUNCTION__, func_get_args());
85+
}
86+
87+
public function getMountId() {
88+
return $this->__call(__FUNCTION__, func_get_args());
89+
}
90+
91+
public function getMountType() {
92+
return $this->__call(__FUNCTION__, func_get_args());
93+
}
94+
95+
public function getMountProvider(): string {
96+
return $this->__call(__FUNCTION__, func_get_args());
97+
}
98+
}

lib/private/Files/Node/LazyFolder.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
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;
1415
use OCP\Files\IRootFolder;
1516
use OCP\Files\Mount\IMountPoint;
1617
use OCP\Files\NotPermittedException;
18+
use function Amp\Promise\wrap;
1719

1820
/**
1921
* Class LazyFolder
@@ -366,11 +368,30 @@ public function isMounted() {
366368
return $this->__call(__FUNCTION__, func_get_args());
367369
}
368370

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

376397
/**

0 commit comments

Comments
 (0)