summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis <louis@chmn.me>2024-10-31 15:55:32 +0100
committerGitHub <noreply@github.com>2024-10-31 15:55:32 +0100
commit8b42f46c3d4886a15c83f854ca9ee295c4a88674 (patch)
tree32433b5519b2c3060985619abd858f23f077d162
parent6bf15d8f8d83c9b8a9ee81ca74377f46acef15ba (diff)
parent74438f7f9652436243b7884bc375ef15d1356439 (diff)
downloadnextcloud-server-8b42f46c3d4886a15c83f854ca9ee295c4a88674.tar.gz
nextcloud-server-8b42f46c3d4886a15c83f854ca9ee295c4a88674.zip
Merge pull request #48998 from nextcloud/backport/47986/stable29
[stable29] perf(ObjectStoreStorage): Improve (slow) move on same object bucket
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreStorage.php5
-rw-r--r--tests/lib/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php41
-rw-r--r--tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php33
-rw-r--r--tests/lib/Files/Storage/StoragesTest.php108
4 files changed, 187 insertions, 0 deletions
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
index c49139424c6..5a2aaa4dc50 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
@@ -625,6 +625,11 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil
public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, ?ICacheEntry $sourceCacheEntry = null): bool {
$sourceCache = $sourceStorage->getCache();
+ if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class) && $sourceStorage->getObjectStore()->getStorageId() === $this->getObjectStore()->getStorageId()) {
+ $this->getCache()->moveFromCache($sourceCache, $sourceInternalPath, $targetInternalPath);
+ // Do not import any data when source and target bucket are identical.
+ return true;
+ }
if (!$sourceCacheEntry) {
$sourceCacheEntry = $sourceCache->get($sourceInternalPath);
}
diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php
new file mode 100644
index 00000000000..a0e18a5557b
--- /dev/null
+++ b/tests/lib/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Files\ObjectStore;
+
+use OC\Files\ObjectStore\StorageObjectStore;
+use OC\Files\Storage\Temporary;
+use Test\Files\Storage\StoragesTest;
+
+/**
+ * @group DB
+ */
+class ObjectStoreStoragesDifferentBucketTest extends StoragesTest {
+ /**
+ * @var \OCP\Files\ObjectStore\IObjectStore
+ */
+ private $objectStore1;
+
+ /**
+ * @var \OCP\Files\ObjectStore\IObjectStore
+ */
+ private $objectStore2;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $baseStorage1 = new Temporary();
+ $this->objectStore1 = new StorageObjectStore($baseStorage1);
+ $config['objectstore'] = $this->objectStore1;
+ $this->storage1 = new ObjectStoreStorageOverwrite($config);
+
+ $baseStorage2 = new Temporary();
+ $this->objectStore2 = new StorageObjectStore($baseStorage2);
+ $config['objectstore'] = $this->objectStore2;
+ $this->storage2 = new ObjectStoreStorageOverwrite($config);
+ }
+}
diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php
new file mode 100644
index 00000000000..19a1f4b7bc5
--- /dev/null
+++ b/tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Files\ObjectStore;
+
+use OC\Files\ObjectStore\StorageObjectStore;
+use OC\Files\Storage\Temporary;
+use Test\Files\Storage\StoragesTest;
+
+/**
+ * @group DB
+ */
+class ObjectStoreStoragesSameBucketTest extends StoragesTest {
+ /**
+ * @var \OCP\Files\ObjectStore\IObjectStore
+ */
+ private $objectStore;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $baseStorage = new Temporary();
+ $this->objectStore = new StorageObjectStore($baseStorage);
+ $config['objectstore'] = $this->objectStore;
+ // storage1 and storage2 share the same object store.
+ $this->storage1 = new ObjectStoreStorageOverwrite($config);
+ $this->storage2 = new ObjectStoreStorageOverwrite($config);
+ }
+}
diff --git a/tests/lib/Files/Storage/StoragesTest.php b/tests/lib/Files/Storage/StoragesTest.php
new file mode 100644
index 00000000000..d157d288f2c
--- /dev/null
+++ b/tests/lib/Files/Storage/StoragesTest.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Files\Storage;
+
+use Test\TestCase;
+
+abstract class StoragesTest extends TestCase {
+ /**
+ * @var \OC\Files\Storage\Storage
+ */
+ protected $storage1;
+
+ /**
+ * @var \OC\Files\Storage\Storage
+ */
+ protected $storage2;
+
+ protected function tearDown(): void {
+ if (is_null($this->storage1) && is_null($this->storage2)) {
+ return;
+ }
+ $this->storage1->getCache()->clear();
+ $this->storage2->getCache()->clear();
+
+ parent::tearDown();
+ }
+
+ public function testMoveFileFromStorage() {
+ $source = 'source.txt';
+ $target = 'target.txt';
+ $this->storage2->file_put_contents($source, 'foo');
+
+ $this->storage1->moveFromStorage($this->storage2, $source, $target);
+
+ $this->assertTrue($this->storage1->file_exists($target), $target.' was not created');
+ $this->assertFalse($this->storage2->file_exists($source), $source.' still exists');
+ $this->assertEquals('foo', $this->storage1->file_get_contents($target));
+ }
+
+ public function testMoveDirectoryFromStorage() {
+ $this->storage2->mkdir('source');
+ $this->storage2->file_put_contents('source/test1.txt', 'foo');
+ $this->storage2->file_put_contents('source/test2.txt', 'qwerty');
+ $this->storage2->mkdir('source/subfolder');
+ $this->storage2->file_put_contents('source/subfolder/test.txt', 'bar');
+
+ $this->storage1->moveFromStorage($this->storage2, 'source', 'target');
+
+ $this->assertTrue($this->storage1->file_exists('target'));
+ $this->assertTrue($this->storage1->file_exists('target/test1.txt'));
+ $this->assertTrue($this->storage1->file_exists('target/test2.txt'));
+ $this->assertTrue($this->storage1->file_exists('target/subfolder'));
+ $this->assertTrue($this->storage1->file_exists('target/subfolder/test.txt'));
+
+ $this->assertFalse($this->storage2->file_exists('source'));
+ $this->assertFalse($this->storage2->file_exists('source/test1.txt'));
+ $this->assertFalse($this->storage2->file_exists('source/test2.txt'));
+ $this->assertFalse($this->storage2->file_exists('source/subfolder'));
+ $this->assertFalse($this->storage2->file_exists('source/subfolder/test.txt'));
+
+ $this->assertEquals('foo', $this->storage1->file_get_contents('target/test1.txt'));
+ $this->assertEquals('qwerty', $this->storage1->file_get_contents('target/test2.txt'));
+ $this->assertEquals('bar', $this->storage1->file_get_contents('target/subfolder/test.txt'));
+ }
+
+ public function testCopyFileFromStorage() {
+ $source = 'source.txt';
+ $target = 'target.txt';
+ $this->storage2->file_put_contents($source, 'foo');
+
+ $this->storage1->copyFromStorage($this->storage2, $source, $target);
+
+ $this->assertTrue($this->storage1->file_exists($target), $target.' was not created');
+ $this->assertTrue($this->storage2->file_exists($source), $source.' was deleted');
+ $this->assertEquals('foo', $this->storage1->file_get_contents($target));
+ }
+
+ public function testCopyDirectoryFromStorage() {
+ $this->storage2->mkdir('source');
+ $this->storage2->file_put_contents('source/test1.txt', 'foo');
+ $this->storage2->file_put_contents('source/test2.txt', 'qwerty');
+ $this->storage2->mkdir('source/subfolder');
+ $this->storage2->file_put_contents('source/subfolder/test.txt', 'bar');
+
+ $this->storage1->copyFromStorage($this->storage2, 'source', 'target');
+
+ $this->assertTrue($this->storage1->file_exists('target'));
+ $this->assertTrue($this->storage1->file_exists('target/test1.txt'));
+ $this->assertTrue($this->storage1->file_exists('target/test2.txt'));
+ $this->assertTrue($this->storage1->file_exists('target/subfolder'));
+ $this->assertTrue($this->storage1->file_exists('target/subfolder/test.txt'));
+
+ $this->assertTrue($this->storage2->file_exists('source'));
+ $this->assertTrue($this->storage2->file_exists('source/test1.txt'));
+ $this->assertTrue($this->storage2->file_exists('source/test2.txt'));
+ $this->assertTrue($this->storage2->file_exists('source/subfolder'));
+ $this->assertTrue($this->storage2->file_exists('source/subfolder/test.txt'));
+
+ $this->assertEquals('foo', $this->storage1->file_get_contents('target/test1.txt'));
+ $this->assertEquals('qwerty', $this->storage1->file_get_contents('target/test2.txt'));
+ $this->assertEquals('bar', $this->storage1->file_get_contents('target/subfolder/test.txt'));
+ }
+}