aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2022-12-01 15:42:07 -0100
committerRobin Appelman <robin@icewind.nl>2023-09-20 15:18:43 +0200
commita658135c679889b686affe021ef84d81b142db54 (patch)
tree0917d2c84705fa98286373c3ecf4a81ad6416c10
parentdbab6a648b79a51898ff22bae9ae9c3ff9d7b9bf (diff)
downloadnextcloud-server-fix/noid/refresh-filesize-on-conflict-24.tar.gz
nextcloud-server-fix/noid/refresh-filesize-on-conflict-24.zip
compare cached filesize on downloadfix/noid/refresh-filesize-on-conflict-24
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php14
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreStorage.php14
-rw-r--r--lib/private/Files/ObjectStore/S3ObjectTrait.php4
-rw-r--r--lib/private/Files/Stream/SeekableHttpStream.php18
4 files changed, 41 insertions, 9 deletions
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index 00c7c779eee..27fc17c008b 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -45,11 +45,11 @@ use OC\Files\Stream\HashWrapper;
use OC\Files\View;
use OC\Metadata\FileMetadata;
use OCA\DAV\AppInfo\Application;
+use OCA\DAV\Connector\Sabre\Exception\BadGateway;
use OCA\DAV\Connector\Sabre\Exception\EntityTooLarge;
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
use OCA\DAV\Connector\Sabre\Exception\Forbidden as DAVForbiddenException;
use OCA\DAV\Connector\Sabre\Exception\UnsupportedMediaType;
-use OCA\DAV\Connector\Sabre\Exception\BadGateway;
use OCP\Encryption\Exceptions\GenericEncryptionException;
use OCP\Files\EntityTooLargeException;
use OCP\Files\FileInfo;
@@ -492,9 +492,21 @@ class File extends Node implements IFile {
} catch (\Exception $e) {
$this->convertToSabreException($e);
}
+
if ($res === false) {
throw new ServiceUnavailable($this->l10n->t('Could not open file'));
}
+
+ // comparing current file size with the one in DB
+ // if different, fix DB and refresh cache.
+ if ($this->getSize() !== $this->fileView->filesize($this->getPath())) {
+ $logger = \OC::$server->get(ILogger::class);
+ $logger->warning('fixing cached size of file id=' . $this->getId());
+
+ $this->getFileInfo()->getStorage()->getUpdater()->update($this->getFileInfo()->getInternalPath());
+ $this->refreshInfo();
+ }
+
return $res;
} catch (GenericEncryptionException $e) {
// returning 503 will allow retry of the operation at a later point in time
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
index 898f64d97c2..c9210992a3e 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
@@ -303,13 +303,23 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
case 'rb':
$stat = $this->stat($path);
if (is_array($stat)) {
+ $filesize = $stat['size'] ?? 0;
// Reading 0 sized files is a waste of time
- if (isset($stat['size']) && $stat['size'] === 0) {
+ if ($filesize === 0) {
return fopen('php://memory', $mode);
}
try {
- return $this->objectStore->readObject($this->getURN($stat['fileid']));
+ $handle = $this->objectStore->readObject($this->getURN($stat['fileid']));
+ if ($handle === false) {
+ return false; // keep backward compatibility
+ }
+ $streamStat = fstat($handle);
+ $actualSize = $streamStat['size'] ?? -1;
+ if ($actualSize > -1 && $actualSize !== $filesize) {
+ $this->getCache()->update((int)$stat['fileid'], ['size' => $actualSize]);
+ }
+ return $handle;
} catch (NotFoundException $e) {
$this->logger->logException($e, [
'app' => 'objectstore',
diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php
index 9d692e01a23..65ef0725973 100644
--- a/lib/private/Files/ObjectStore/S3ObjectTrait.php
+++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php
@@ -29,9 +29,9 @@ namespace OC\Files\ObjectStore;
use Aws\S3\Exception\S3MultipartUploadException;
use Aws\S3\MultipartUploader;
use Aws\S3\S3Client;
+use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\Utils;
use OC\Files\Stream\SeekableHttpStream;
-use GuzzleHttp\Psr7;
use Psr\Http\Message\StreamInterface;
trait S3ObjectTrait {
@@ -47,6 +47,7 @@ trait S3ObjectTrait {
/**
* @param string $urn the unified resource name used to identify the object
+ *
* @return resource stream with the read data
* @throws \Exception when something goes wrong, message will be logged
* @since 7.0.0
@@ -88,6 +89,7 @@ trait S3ObjectTrait {
});
}
+
/**
* Single object put helper
*
diff --git a/lib/private/Files/Stream/SeekableHttpStream.php b/lib/private/Files/Stream/SeekableHttpStream.php
index 820a681bd07..cf504f46568 100644
--- a/lib/private/Files/Stream/SeekableHttpStream.php
+++ b/lib/private/Files/Stream/SeekableHttpStream.php
@@ -75,10 +75,13 @@ class SeekableHttpStream implements File {
/** @var resource */
private $current;
- /** @var int */
- private $offset = 0;
- /** @var int */
- private $length = 0;
+ /** @var int $offset offset of the current chunk */
+ private int $offset = 0;
+ /** @var int $length length of the current chunk */
+ private int $length = 0;
+ /** @var int $totalSize size of the full stream */
+ private int $totalSize = 0;
+ private bool $needReconnect = false;
private function reconnect(int $start) {
$range = $start . '-';
@@ -124,6 +127,9 @@ class SeekableHttpStream implements File {
$this->offset = $begin;
$this->length = $length;
+ if ($start === 0) {
+ $this->totalSize = $length;
+ }
return true;
}
@@ -173,7 +179,9 @@ class SeekableHttpStream implements File {
public function stream_stat() {
if (is_resource($this->current)) {
- return fstat($this->current);
+ $stat = fstat($this->current);
+ $stat['size'] = $this->totalSize;
+ return $stat;
} else {
return false;
}