fix: get child ids for folder in a separate query during move

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2024-02-12 15:52:07 +01:00 committed by backportbot[bot]
parent c23002bd76
commit 4314997a2a

View file

@ -702,6 +702,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();
@ -714,7 +719,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()) {
@ -727,12 +732,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;
}
@ -742,8 +752,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);
}
@ -785,6 +793,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
*/