aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Files/Cache
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2024-02-12 15:52:07 +0100
committerArthur Schiwon <blizzz@arthur-schiwon.de>2024-06-13 10:38:57 +0200
commit082c6c6e1d238c283ab951108a6f0930e6327cc6 (patch)
treefafb35ed030708c79c6612021512275c649524e2 /lib/private/Files/Cache
parent59c181b4cbc47821d0a7d35df747a8b1d012dfc7 (diff)
downloadnextcloud-server-082c6c6e1d238c283ab951108a6f0930e6327cc6.tar.gz
nextcloud-server-082c6c6e1d238c283ab951108a6f0930e6327cc6.zip
fix: get child ids for folder in a separate query during move
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib/private/Files/Cache')
-rw-r--r--lib/private/Files/Cache/Cache.php25
1 files changed, 21 insertions, 4 deletions
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php
index 96e840e4806..3c871fdf4dc 100644
--- a/lib/private/Files/Cache/Cache.php
+++ b/lib/private/Files/Cache/Cache.php
@@ -666,6 +666,11 @@ class Cache implements ICache {
if ($sourceData['mimetype'] === 'httpd/unix-directory') {
//update all child entries
$sourceLength = mb_strlen($sourcePath);
+
+ $childIds = $this->getChildIds($sourceStorageId, $sourcePath);
+
+ $childChunks = array_chunk($childIds, 1000);
+
$query = $this->connection->getQueryBuilder();
$fun = $query->func();
@@ -678,7 +683,7 @@ class Cache implements ICache {
->set('path_hash', $fun->md5($newPathFunction))
->set('path', $newPathFunction)
->where($query->expr()->eq('storage', $query->createNamedParameter($sourceStorageId, IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath) . '/%')));
+ ->andWhere($query->expr()->in('fileid', $query->createParameter('files')));
// when moving from an encrypted storage to a non-encrypted storage remove the `encrypted` mark
if ($sourceCache->hasEncryptionWrapper() && !$this->hasEncryptionWrapper()) {
@@ -691,12 +696,17 @@ class Cache implements ICache {
for ($i = 1; $i <= $retryLimit; $i++) {
try {
$this->connection->beginTransaction();
- $query->executeStatement();
+ foreach ($childChunks as $chunk) {
+ $query->setParameter('files', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
+ $query->executeStatement();
+ }
break;
} catch (\OC\DatabaseException $e) {
$this->connection->rollBack();
throw $e;
} catch (DbalException $e) {
+ $this->connection->rollBack();
+
if (!$e->isRetryable()) {
throw $e;
}
@@ -706,8 +716,6 @@ class Cache implements ICache {
throw $e;
}
- $this->connection->rollBack();
-
// Sleep a bit to give some time to the other transaction to finish.
usleep(100 * 1000 * $i);
}
@@ -749,6 +757,15 @@ class Cache implements ICache {
}
}
+ private function getChildIds(int $storageId, string $path): array {
+ $query = $this->connection->getQueryBuilder();
+ $query->select('fileid')
+ ->from('filecache')
+ ->where($query->expr()->eq('storage', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)))
+ ->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($path) . '/%')));
+ return $query->executeQuery()->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
/**
* remove all entries for files that are stored on the storage from the cache
*/