Merge pull request #23912 from nextcloud/objectstore-copy
use in objectstore copy
This commit is contained in:
commit
2172432420
|
@ -130,4 +130,8 @@ class Azure implements IObjectStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copyObject($from, $to) {
|
||||||
|
$this->getBlobClient()->copyBlob($this->containerName, $to, $this->containerName, $from);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,15 @@ use Icewind\Streams\CallbackWrapper;
|
||||||
use Icewind\Streams\CountWrapper;
|
use Icewind\Streams\CountWrapper;
|
||||||
use Icewind\Streams\IteratorDirectory;
|
use Icewind\Streams\IteratorDirectory;
|
||||||
use OC\Files\Cache\CacheEntry;
|
use OC\Files\Cache\CacheEntry;
|
||||||
|
use OC\Files\Storage\PolyFill\CopyDirectory;
|
||||||
|
use OCP\Files\Cache\ICacheEntry;
|
||||||
|
use OCP\Files\FileInfo;
|
||||||
use OCP\Files\NotFoundException;
|
use OCP\Files\NotFoundException;
|
||||||
use OCP\Files\ObjectStore\IObjectStore;
|
use OCP\Files\ObjectStore\IObjectStore;
|
||||||
|
|
||||||
class ObjectStoreStorage extends \OC\Files\Storage\Common {
|
class ObjectStoreStorage extends \OC\Files\Storage\Common {
|
||||||
|
use CopyDirectory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \OCP\Files\ObjectStore\IObjectStore $objectStore
|
* @var \OCP\Files\ObjectStore\IObjectStore $objectStore
|
||||||
*/
|
*/
|
||||||
|
@ -474,7 +479,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
|
||||||
if ($size === null) {
|
if ($size === null) {
|
||||||
$countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) {
|
$countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) {
|
||||||
$this->getCache()->update($fileId, [
|
$this->getCache()->update($fileId, [
|
||||||
'size' => $writtenSize
|
'size' => $writtenSize,
|
||||||
]);
|
]);
|
||||||
$size = $writtenSize;
|
$size = $writtenSize;
|
||||||
});
|
});
|
||||||
|
@ -523,4 +528,59 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
|
||||||
public function getObjectStore(): IObjectStore {
|
public function getObjectStore(): IObjectStore {
|
||||||
return $this->objectStore;
|
return $this->objectStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copy($path1, $path2) {
|
||||||
|
$path1 = $this->normalizePath($path1);
|
||||||
|
$path2 = $this->normalizePath($path2);
|
||||||
|
|
||||||
|
$cache = $this->getCache();
|
||||||
|
$sourceEntry = $cache->get($path1);
|
||||||
|
if (!$sourceEntry) {
|
||||||
|
throw new NotFoundException('Source object not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->copyInner($sourceEntry, $path2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function copyInner(ICacheEntry $sourceEntry, string $to) {
|
||||||
|
$cache = $this->getCache();
|
||||||
|
|
||||||
|
if ($sourceEntry->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
|
||||||
|
if ($cache->inCache($to)) {
|
||||||
|
$cache->remove($to);
|
||||||
|
}
|
||||||
|
$this->mkdir($to);
|
||||||
|
|
||||||
|
foreach ($cache->getFolderContentsById($sourceEntry->getId()) as $child) {
|
||||||
|
$this->copyInner($child, $to . '/' . $child->getName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->copyFile($sourceEntry, $to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function copyFile(ICacheEntry $sourceEntry, string $to) {
|
||||||
|
$cache = $this->getCache();
|
||||||
|
|
||||||
|
$sourceUrn = $this->getURN($sourceEntry->getId());
|
||||||
|
|
||||||
|
$cache->copyFromCache($cache, $sourceEntry, $to);
|
||||||
|
$targetEntry = $cache->get($to);
|
||||||
|
|
||||||
|
if (!$targetEntry) {
|
||||||
|
throw new \Exception('Target not in cache after copy');
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetUrn = $this->getURN($targetEntry->getId());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->objectStore->copyObject($sourceUrn, $targetUrn);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$cache->remove($to);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,4 +124,8 @@ trait S3ObjectTrait {
|
||||||
public function objectExists($urn) {
|
public function objectExists($urn) {
|
||||||
return $this->getConnection()->doesObjectExist($this->bucket, $urn);
|
return $this->getConnection()->doesObjectExist($this->bucket, $urn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copyObject($from, $to) {
|
||||||
|
$this->getConnection()->copy($this->getBucket(), $from, $this->getBucket(), $to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,4 +93,8 @@ class StorageObjectStore implements IObjectStore {
|
||||||
public function objectExists($urn) {
|
public function objectExists($urn) {
|
||||||
return $this->storage->file_exists($urn);
|
return $this->storage->file_exists($urn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copyObject($from, $to) {
|
||||||
|
$this->storage->copy($from, $to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,13 +87,13 @@ class Swift implements IObjectStore {
|
||||||
if (filesize($tmpFile) < SWIFT_SEGMENT_SIZE) {
|
if (filesize($tmpFile) < SWIFT_SEGMENT_SIZE) {
|
||||||
$this->getContainer()->createObject([
|
$this->getContainer()->createObject([
|
||||||
'name' => $urn,
|
'name' => $urn,
|
||||||
'stream' => stream_for($handle)
|
'stream' => stream_for($handle),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$this->getContainer()->createLargeObject([
|
$this->getContainer()->createLargeObject([
|
||||||
'name' => $urn,
|
'name' => $urn,
|
||||||
'stream' => stream_for($handle),
|
'stream' => stream_for($handle),
|
||||||
'segmentSize' => SWIFT_SEGMENT_SIZE
|
'segmentSize' => SWIFT_SEGMENT_SIZE,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ class Swift implements IObjectStore {
|
||||||
'stream' => true,
|
'stream' => true,
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'X-Auth-Token' => $tokenId,
|
'X-Auth-Token' => $tokenId,
|
||||||
'Cache-Control' => 'no-cache'
|
'Cache-Control' => 'no-cache',
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -149,4 +149,10 @@ class Swift implements IObjectStore {
|
||||||
public function objectExists($urn) {
|
public function objectExists($urn) {
|
||||||
return $this->getContainer()->objectExists($urn);
|
return $this->getContainer()->objectExists($urn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copyObject($from, $to) {
|
||||||
|
$this->getContainer()->getObject($from)->copy([
|
||||||
|
'destination' => $this->getContainer()->name . '/' . $to
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,4 +73,12 @@ interface IObjectStore {
|
||||||
* @since 16.0.0
|
* @since 16.0.0
|
||||||
*/
|
*/
|
||||||
public function objectExists($urn);
|
public function objectExists($urn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $from the unified resource name used to identify the source object
|
||||||
|
* @param string $to the unified resource name used to identify the target object
|
||||||
|
* @return void
|
||||||
|
* @since 21.0.0
|
||||||
|
*/
|
||||||
|
public function copyObject($from, $to);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,4 +51,8 @@ class FailDeleteObjectStore implements IObjectStore {
|
||||||
public function objectExists($urn) {
|
public function objectExists($urn) {
|
||||||
return $this->objectStore->objectExists($urn);
|
return $this->objectStore->objectExists($urn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copyObject($from, $to) {
|
||||||
|
$this->objectStore->copyObject($from, $to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,4 +52,8 @@ class FailWriteObjectStore implements IObjectStore {
|
||||||
public function objectExists($urn) {
|
public function objectExists($urn) {
|
||||||
return $this->objectStore->objectExists($urn);
|
return $this->objectStore->objectExists($urn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function copyObject($from, $to) {
|
||||||
|
$this->objectStore->copyObject($from, $to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,4 +108,20 @@ abstract class ObjectStoreTest extends TestCase {
|
||||||
|
|
||||||
$this->assertFalse($instance->objectExists('2'));
|
$this->assertFalse($instance->objectExists('2'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCopy() {
|
||||||
|
$stream = $this->stringToStream('foobar');
|
||||||
|
|
||||||
|
$instance = $this->getInstance();
|
||||||
|
|
||||||
|
$instance->writeObject('source', $stream);
|
||||||
|
|
||||||
|
$this->assertFalse($instance->objectExists('target'));
|
||||||
|
|
||||||
|
$instance->copyObject('source', 'target');
|
||||||
|
|
||||||
|
$this->assertTrue($instance->objectExists('target'));
|
||||||
|
|
||||||
|
$this->assertEquals('foobar', stream_get_contents($instance->readObject('target')));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue