From 19ec79b3134bb2b78d900c05d62a913500eec282 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 3 Oct 2024 17:35:56 +0200 Subject: [PATCH] fix: smuggle storage id to metadata insert queries Signed-off-by: Robin Appelman --- apps/dav/lib/Connector/Sabre/FilesPlugin.php | 3 +++ .../lib/Listener/SyncLivePhotosListener.php | 5 +++++ .../FilesMetadata/FilesMetadataManager.php | 5 ++++- .../FilesMetadata/Model/FilesMetadata.php | 9 +++++++++ .../Service/MetadataRequestService.php | 20 +++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index 3855f51c65a..dbd4e522517 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -8,6 +8,7 @@ namespace OCA\DAV\Connector\Sabre; use OC\AppFramework\Http\Request; +use OC\FilesMetadata\Model\FilesMetadata; use OCA\DAV\Connector\Sabre\Exception\InvalidPath; use OCP\Constants; use OCP\Files\ForbiddenException; @@ -575,7 +576,9 @@ class FilesPlugin extends ServerPlugin { $propPatch->handle( $mutation, function (mixed $value) use ($accessRight, $knownMetadata, $node, $mutation, $filesMetadataManager): bool { + /** @var FilesMetadata $metadata */ $metadata = $filesMetadataManager->getMetadata((int)$node->getFileId(), true); + $metadata->setStorageId($node->getNode()->getStorage()->getCache()->getNumericStorageId()); $metadataKey = substr($mutation, strlen(self::FILE_METADATA_PREFIX)); // confirm metadata key is editable via PROPPATCH diff --git a/apps/files/lib/Listener/SyncLivePhotosListener.php b/apps/files/lib/Listener/SyncLivePhotosListener.php index 049d7319b64..34789187644 100644 --- a/apps/files/lib/Listener/SyncLivePhotosListener.php +++ b/apps/files/lib/Listener/SyncLivePhotosListener.php @@ -8,6 +8,7 @@ declare(strict_types=1); namespace OCA\Files\Listener; +use OC\FilesMetadata\Model\FilesMetadata; use OCA\Files\Service\LivePhotosService; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; @@ -154,10 +155,14 @@ class SyncLivePhotosListener implements IEventListener { * We have everything to update metadata and keep the link between the 2 copies. */ $newPeerFile = $peerFile->copy($targetParent->getPath() . '/' . $peerTargetName); + /** @var FilesMetadata $targetMetadata */ $targetMetadata = $this->filesMetadataManager->getMetadata($targetFile->getId(), true); + $targetMetadata->setStorageId($targetFile->getStorage()->getCache()->getNumericStorageId()); $targetMetadata->setString('files-live-photo', (string)$newPeerFile->getId()); $this->filesMetadataManager->saveMetadata($targetMetadata); + /** @var FilesMetadata $peerMetadata */ $peerMetadata = $this->filesMetadataManager->getMetadata($newPeerFile->getId(), true); + $peerMetadata->setStorageId($newPeerFile->getStorage()->getCache()->getNumericStorageId()); $peerMetadata->setString('files-live-photo', (string)$targetFile->getId()); $this->filesMetadataManager->saveMetadata($peerMetadata); } diff --git a/lib/private/FilesMetadata/FilesMetadataManager.php b/lib/private/FilesMetadata/FilesMetadataManager.php index f2ea6cb11a7..b0a08c4f119 100644 --- a/lib/private/FilesMetadata/FilesMetadataManager.php +++ b/lib/private/FilesMetadata/FilesMetadataManager.php @@ -77,10 +77,13 @@ class FilesMetadataManager implements IFilesMetadataManager { int $process = self::PROCESS_LIVE, string $namedEvent = '', ): IFilesMetadata { + $storageId = $node->getStorage()->getCache()->getNumericStorageId(); try { + /** @var FilesMetadata $metadata */ $metadata = $this->metadataRequestService->getMetadataFromFileId($node->getId()); + $metadata->setStorageId($storageId); } catch (FilesMetadataNotFoundException) { - $metadata = new FilesMetadata($node->getId()); + $metadata = new FilesMetadata($node->getId(), $storageId); } // if $process is LIVE, we enforce LIVE diff --git a/lib/private/FilesMetadata/Model/FilesMetadata.php b/lib/private/FilesMetadata/Model/FilesMetadata.php index d338bdbba8f..d35e4a375e3 100644 --- a/lib/private/FilesMetadata/Model/FilesMetadata.php +++ b/lib/private/FilesMetadata/Model/FilesMetadata.php @@ -30,6 +30,7 @@ class FilesMetadata implements IFilesMetadata { public function __construct( private int $fileId = 0, + private ?int $storageId = null, ) { } @@ -42,6 +43,14 @@ class FilesMetadata implements IFilesMetadata { return $this->fileId; } + public function getStorageId(): ?int { + return $this->storageId; + } + + public function setStorageId(int $storageId): void { + $this->storageId = $storageId; + } + /** * @inheritDoc * @return int timestamp diff --git a/lib/private/FilesMetadata/Service/MetadataRequestService.php b/lib/private/FilesMetadata/Service/MetadataRequestService.php index 5fc02c5d00b..4d36655cffa 100644 --- a/lib/private/FilesMetadata/Service/MetadataRequestService.php +++ b/lib/private/FilesMetadata/Service/MetadataRequestService.php @@ -28,6 +28,24 @@ class MetadataRequestService { ) { } + private function getStorageId(IFilesMetadata $filesMetadata): int { + if ($filesMetadata instanceof FilesMetadata && $filesMetadata->getStorageId()) { + return $filesMetadata->getStorageId(); + } + // all code paths that lead to saving metadata *should* have the storage id set + // this fallback is there just in case + $query = $this->dbConnection->getQueryBuilder(); + $query->select('storage') + ->from('filecache') + ->where($query->expr()->eq('fileid', $query->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT))); + $storageId = $query->executeQuery()->fetchColumn(); + + if ($filesMetadata instanceof FilesMetadata) { + $filesMetadata->setStorageId($storageId); + } + return $storageId; + } + /** * store metadata into database * @@ -38,6 +56,7 @@ class MetadataRequestService { public function store(IFilesMetadata $filesMetadata): void { $qb = $this->dbConnection->getQueryBuilder(); $qb->insert(self::TABLE_METADATA) + ->hintShardKey('storage', $this->getStorageId($filesMetadata)) ->setValue('file_id', $qb->createNamedParameter($filesMetadata->getFileId(), IQueryBuilder::PARAM_INT)) ->setValue('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize()))) ->setValue('sync_token', $qb->createNamedParameter($this->generateSyncToken())) @@ -134,6 +153,7 @@ class MetadataRequestService { $expr = $qb->expr(); $qb->update(self::TABLE_METADATA) + ->hintShardKey('files_metadata', $this->getStorageId($filesMetadata)) ->set('json', $qb->createNamedParameter(json_encode($filesMetadata->jsonSerialize()))) ->set('sync_token', $qb->createNamedParameter($this->generateSyncToken())) ->set('last_update', $qb->createFunction('NOW()')) -- 2.39.5