summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2021-05-06 21:23:09 +0200
committerRobin Appelman <robin@icewind.nl>2021-06-14 16:11:32 +0200
commit27e50b24aab60112c05f88e570af099faeac0122 (patch)
treee43c71fd628027e5c348868848279f6b05a2e44d
parent5d1d53c42e9a8342f9fd2da815e6653a64203c0c (diff)
downloadnextcloud-server-27e50b24aab60112c05f88e570af099faeac0122.tar.gz
nextcloud-server-27e50b24aab60112c05f88e570af099faeac0122.zip
some cleanup and documentation
Signed-off-by: Robin Appelman <robin@icewind.nl>
-rw-r--r--lib/private/Files/Cache/QuerySearchHelper.php10
-rw-r--r--lib/private/Files/Node/Folder.php41
2 files changed, 22 insertions, 29 deletions
diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php
index 64a888f492c..393eb54e4fe 100644
--- a/lib/private/Files/Cache/QuerySearchHelper.php
+++ b/lib/private/Files/Cache/QuerySearchHelper.php
@@ -255,6 +255,11 @@ class QuerySearchHelper {
}
/**
+ * Perform a file system search in multiple caches
+ *
+ * the results will be grouped by the same array keys as the $caches argument to allow
+ * post-processing based on which cache the result came from
+ *
* @template T of array-key
* @param ISearchQuery $searchQuery
* @param array<T, ICache> $caches
@@ -304,10 +309,6 @@ class QuerySearchHelper {
}, $caches));
$query->andWhere($this->searchOperatorToDBExpr($builder, new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters)));
- if ($searchQuery->limitToHome() && ($this instanceof HomeCache)) {
- $query->andWhere($builder->expr()->like('path', $query->expr()->literal('files/%')));
- }
-
$this->addSearchOrdersToQuery($query, $searchQuery->getOrder());
if ($searchQuery->getLimit()) {
@@ -327,6 +328,7 @@ class QuerySearchHelper {
$result->closeCursor();
// loop trough all caches for each result to see if the result matches that storage
+ // results are grouped by the same array keys as the caches argument to allow the caller to distringuish the source of the results
$results = array_fill_keys(array_keys($caches), []);
foreach ($rawEntries as $rawEntry) {
foreach ($caches as $cacheKey => $cache) {
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index 82515feba03..eb4841c5719 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -234,18 +234,8 @@ class Folder extends Node implements \OCP\Files\Folder {
$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
}
- // Limit+offset for queries with ordering
- //
- // Because we currently can't do ordering between the results from different storages in sql
- // The only way to do ordering is requesting the $limit number of entries from all storages
- // sorting them and returning the first $limit entries.
- //
- // For offset we have the same problem, we don't know how many entries from each storage should be skipped
- // by a given $offset, so instead we query $offset + $limit from each storage and return entries $offset..($offset+$limit)
- // after merging and sorting them.
- //
- // This is suboptimal but because limit and offset tend to be fairly small in real world use cases it should
- // still be significantly better than disabling paging altogether
+ // search is handled by a single query covering all caches that this folder contains
+ // this is done by collect
$limitToHome = $query->limitToHome();
if ($limitToHome && count(explode('/', $this->path)) !== 3) {
@@ -257,11 +247,11 @@ class Folder extends Node implements \OCP\Files\Folder {
$storage = $mount->getStorage();
$internalPath = $mount->getInternalPath($this->path);
- $caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
- /** @var array{IMountPoint, string}[] $infoParams */
- $infoParams = [
- '' => [$mount, '']
- ];
+ // collect all caches for this folder, indexed by their mountpoint relative to this folder
+ // and save the mount which is needed later to construct the FileInfo objects
+
+ $caches = ['' => new CacheJail($storage->getCache(''), $internalPath)]; // a temporary CacheJail is used to handle filtering down the results to within this folder
+ $mountByMountPoint = ['' => $mount];
if (!$limitToHome) {
$mounts = $this->root->getMountsIn($this->path);
@@ -270,7 +260,7 @@ class Folder extends Node implements \OCP\Files\Folder {
if ($storage) {
$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
$caches[$relativeMountPoint] = $storage->getCache('');
- $infoParams[$relativeMountPoint] = [$mount, ''];
+ $mountByMountPoint[$relativeMountPoint] = $mount;
}
}
}
@@ -278,10 +268,12 @@ class Folder extends Node implements \OCP\Files\Folder {
/** @var QuerySearchHelper $searchHelper */
$searchHelper = \OC::$server->get(QuerySearchHelper::class);
$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
- $files = array_merge(...array_map(function(array $results, $relativeMountPoint) use ($infoParams) {
- $params = $infoParams[$relativeMountPoint];
- return array_map(function(ICacheEntry $result) use ($relativeMountPoint, $params) {
- return $this->cacheEntryToFileInfo($params[0], $relativeMountPoint, $params[1], $result);
+
+ // loop trough all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
+ $files = array_merge(...array_map(function(array $results, $relativeMountPoint) use ($mountByMountPoint) {
+ $mount = $mountByMountPoint[$relativeMountPoint];
+ return array_map(function(ICacheEntry $result) use ($relativeMountPoint, $mount) {
+ return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
}, $results);
}, array_values($resultsPerCache), array_keys($resultsPerCache)));
@@ -290,10 +282,9 @@ class Folder extends Node implements \OCP\Files\Folder {
}, $files);
}
- private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, string $trimRoot, ICacheEntry $cacheEntry): FileInfo {
- $trimLength = strlen($trimRoot);
+ private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
$cacheEntry['internalPath'] = $cacheEntry['path'];
- $cacheEntry['path'] = $appendRoot . substr($cacheEntry['path'], $trimLength);
+ $cacheEntry['path'] = $appendRoot . $cacheEntry->getPath();
return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
}