From b7d2a161c6de32460adb85b8abb3abf8fea9335c Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Tue, 13 Jan 2026 14:10:43 +0100 Subject: [PATCH 1/2] perf(files): Optimize CacheEntry creatoin Signed-off-by: Carl Schwan --- apps/files_sharing/tests/CacheTest.php | 28 ++++++------ lib/private/Files/Cache/Cache.php | 63 ++++++++++++-------------- lib/private/Files/Cache/CacheEntry.php | 10 ++-- 3 files changed, 47 insertions(+), 54 deletions(-) diff --git a/apps/files_sharing/tests/CacheTest.php b/apps/files_sharing/tests/CacheTest.php index d451a9c20619e..073b4e4a86e9e 100644 --- a/apps/files_sharing/tests/CacheTest.php +++ b/apps/files_sharing/tests/CacheTest.php @@ -9,6 +9,7 @@ use OC\Files\Cache\Cache; use OC\Files\Filesystem; +use OC\Files\SetupManager; use OC\Files\Storage\Storage; use OC\Files\Storage\Temporary; use OC\Files\Storage\Wrapper\Jail; @@ -16,6 +17,7 @@ use OCA\Files_Sharing\SharedStorage; use OCP\Constants; use OCP\Files\Cache\IWatcher; +use OCP\Files\IRootFolder; use OCP\IUserManager; use OCP\Server; use OCP\Share\IShare; @@ -424,8 +426,7 @@ public function testGetPathByIdDirectShare(): void { $share = $this->shareManager->createShare($share); $share->setStatus(IShare::STATUS_ACCEPTED); $this->shareManager->updateShare($share); - - \OC_Util::tearDownFS(); + Server::get(SetupManager::class)->tearDown(); self::loginHelper(self::TEST_FILES_SHARING_API_USER2); $this->assertTrue(Filesystem::file_exists('/test.txt')); @@ -456,7 +457,7 @@ public function testGetPathByIdShareSubFolder(): void { $share = $this->shareManager->createShare($share); $share->setStatus(IShare::STATUS_ACCEPTED); $this->shareManager->updateShare($share); - \OC_Util::tearDownFS(); + Server::get(SetupManager::class)->tearDown(); self::loginHelper(self::TEST_FILES_SHARING_API_USER2); $this->assertTrue(Filesystem::file_exists('/foo')); @@ -484,7 +485,7 @@ public function testNumericStorageId(): void { $share = $this->shareManager->createShare($share); $share->setStatus(IShare::STATUS_ACCEPTED); $this->shareManager->updateShare($share); - \OC_Util::tearDownFS(); + Server::get(SetupManager::class)->tearDown(); [$sourceStorage] = Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/foo'); @@ -521,7 +522,7 @@ public function testShareJailedStorage(): void { $share = $this->shareManager->createShare($share); $share->setStatus(IShare::STATUS_ACCEPTED); $this->shareManager->updateShare($share); - \OC_Util::tearDownFS(); + Server::get(SetupManager::class)->tearDown(); self::loginHelper(self::TEST_FILES_SHARING_API_USER2); $this->assertEquals('foo', Filesystem::file_get_contents('/sub/foo.txt')); @@ -560,7 +561,7 @@ public function testSearchShareJailedStorage(): void { $share = $this->shareManager->createShare($share); $share->setStatus(IShare::STATUS_ACCEPTED); $this->shareManager->updateShare($share); - \OC_Util::tearDownFS(); + Server::get(SetupManager::class)->tearDown(); self::loginHelper(self::TEST_FILES_SHARING_API_USER2); @@ -571,7 +572,7 @@ public function testSearchShareJailedStorage(): void { $this->assertCount(1, $results); } - public function testWatcherRootChange() { + public function testWatcherRootChange(): void { $sourceStorage = new Temporary(); $sourceStorage->mkdir('shared'); $sourceStorage->file_put_contents('shared/foo.txt', 'foo'); @@ -581,7 +582,8 @@ public function testWatcherRootChange() { self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + $rootFolder = Server::get(IRootFolder::class) + ->getUserFolder(self::TEST_FILES_SHARING_API_USER1); $node = $rootFolder->get('foo/shared'); $this->assertEquals(3, $node->getSize()); @@ -594,14 +596,14 @@ public function testWatcherRootChange() { $share = $this->shareManager->createShare($share); $share->setStatus(IShare::STATUS_ACCEPTED); $this->shareManager->updateShare($share); - \OC_Util::tearDownFS(); + Server::get(SetupManager::class)->tearDown(); self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $view = Filesystem::getView(); - - $sourceStorage->rmdir('shared'); + $this->assertTrue($sourceStorage->rmdir('shared')); - $this->assertFalse($view->getFileInfo('shared')); + $this->assertFalse(Server::get(IRootFolder::class) + ->getUserFolder(self::TEST_FILES_SHARING_API_USER2) + ->nodeExists('shared')); } } diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index e85d4793d8e3f..dea5f7ec5ba0a 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -148,41 +148,36 @@ public function get($file) { /** * Create a CacheEntry from database row - * - * @param array $data - * @param IMimeTypeLoader $mimetypeLoader - * @return CacheEntry */ - public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) { - //fix types - $data['name'] = (string)$data['name']; - $data['path'] = (string)$data['path']; - $data['fileid'] = (int)$data['fileid']; - $data['parent'] = (int)$data['parent']; - $data['size'] = Util::numericToNumber($data['size']); - $data['unencrypted_size'] = Util::numericToNumber($data['unencrypted_size'] ?? 0); - $data['mtime'] = (int)$data['mtime']; - $data['storage_mtime'] = (int)$data['storage_mtime']; - $data['encryptedVersion'] = (int)$data['encrypted']; - $data['encrypted'] = (bool)$data['encrypted']; - $data['storage_id'] = $data['storage']; - $data['storage'] = (int)$data['storage']; - $data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']); - $data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']); - if ($data['storage_mtime'] == 0) { - $data['storage_mtime'] = $data['mtime']; - } - if (isset($data['f_permissions'])) { - $data['scan_permissions'] ??= $data['f_permissions']; - } - $data['permissions'] = (int)$data['permissions']; - if (isset($data['creation_time'])) { - $data['creation_time'] = (int)$data['creation_time']; - } - if (isset($data['upload_time'])) { - $data['upload_time'] = (int)$data['upload_time']; - } - return new CacheEntry($data); + public static function cacheEntryFromData(array $data, IMimeTypeLoader $mimetypeLoader): CacheEntry { + return new CacheEntry([ + 'name' => (string)$data['name'], + 'etag' => (string)$data['etag'], + 'path' => (string)$data['path'], + 'path_hash' => (string)$data['path_hash'], + 'checksum' => (string)$data['checksum'], + 'fileid' => (int)$data['fileid'], + 'parent' => (int)$data['parent'], + 'size' => Util::numericToNumber($data['size']), + 'unencrypted_size' => Util::numericToNumber($data['unencrypted_size'] ?? 0), + 'mtime' => (int)$data['mtime'], + 'storage_mtime' => (int)($data['storage_mtime'] ?: $data['mtime']), + 'encryptedVersion' => (int)$data['encrypted'], + 'encrypted' => (bool)$data['encrypted'], + 'storage_id' => $data['storage'], + 'storage_string_id' => isset($data['storage_string_id']) ? (string)$data['storage_string_id'] : null, + 'storage' => (int)$data['storage'], + 'mimetype' => $mimetypeLoader->getMimetypeById($data['mimetype']), + 'mimepart' => $mimetypeLoader->getMimetypeById($data['mimepart']), + 'permissions' => (int)$data['permissions'], + 'creation_time' => isset($data['creation_time']) ? (int)$data['creation_time'] : null, + 'upload_time' => isset($data['upload_time']) ? (int)$data['upload_time'] : null, + 'metadata_etag' => isset($data['metadata_etag']) ? (string)$data['metadata_etag'] : null, + 'scan_permissions' => $data['scan_permissions'] ?? ($data['f_permissions'] ?? null), + 'metadata' => $data['metadata'] ?? null, + 'meta_json' => $data['meta_json'] ?? null, + 'meta_sync_token' => $data['meta_sync_token'] ?? null, + ]); } /** diff --git a/lib/private/Files/Cache/CacheEntry.php b/lib/private/Files/Cache/CacheEntry.php index c558ec7721e8f..ab1df46d68e28 100644 --- a/lib/private/Files/Cache/CacheEntry.php +++ b/lib/private/Files/Cache/CacheEntry.php @@ -13,13 +13,9 @@ * meta data for a file or folder */ class CacheEntry implements ICacheEntry { - /** - * @var array - */ - private $data; - - public function __construct(array $data) { - $this->data = $data; + public function __construct( + private array $data, + ) { } public function offsetSet($offset, $value): void { From a8b87192000e9a4eb6c91cdc663870e20b380edb Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 14 Jan 2026 10:51:31 +0100 Subject: [PATCH 2/2] fix(cache): Handle groupfolder specific entries in cacheEntryFromData Signed-off-by: Carl Schwan --- lib/private/Files/Cache/Cache.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index dea5f7ec5ba0a..d88121d130a6a 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -150,7 +150,7 @@ public function get($file) { * Create a CacheEntry from database row */ public static function cacheEntryFromData(array $data, IMimeTypeLoader $mimetypeLoader): CacheEntry { - return new CacheEntry([ + $normalized = [ 'name' => (string)$data['name'], 'etag' => (string)$data['etag'], 'path' => (string)$data['path'], @@ -177,7 +177,21 @@ public static function cacheEntryFromData(array $data, IMimeTypeLoader $mimetype 'metadata' => $data['metadata'] ?? null, 'meta_json' => $data['meta_json'] ?? null, 'meta_sync_token' => $data['meta_sync_token'] ?? null, - ]); + ]; + + if (isset($data['folder_id'])) { + // groupfolders specific fields + $normalized['folder_id'] = (int)$data['folder_id']; + $normalized['mount_point'] = (string)$data['mount_point']; + $normalized['quota'] = $data['quota']; + $normalized['acl'] = (int)$data['acl']; + $normalized['acl_default_no_permission'] = (int)$data['acl_default_no_permission']; + $normalized['storage_id'] = (int)$data['storage_id']; + $normalized['root_id'] = (int)$data['root_id']; + $normalized['options'] = (string)$data['options']; + } + + return new CacheEntry($normalized); } /**