]> source.dussan.org Git - nextcloud-server.git/commitdiff
compare cached filesize on download 34232/head
authorMaxence Lange <maxence@artificial-owl.com>
Thu, 1 Dec 2022 16:42:07 +0000 (15:42 -0100)
committerMaxence Lange <maxence@artificial-owl.com>
Thu, 1 Dec 2022 16:42:15 +0000 (15:42 -0100)
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
apps/dav/lib/Connector/Sabre/File.php
lib/private/Files/ObjectStore/ObjectStoreStorage.php
lib/private/Files/ObjectStore/S3ObjectTrait.php
lib/private/Files/Stream/SeekableHttpStream.php

index 94632b265dbf582871d9f284874fd392aedce691..3a871b06259d17d9d74fafbbf81e69285234311f 100644 (file)
@@ -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;
@@ -491,9 +491,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(LoggerInterface::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
index 04dd846abe40f3dc5122f65f2cb559e9cbf0fbd9..02b65bf37f74db709915266bd58c13efd286c841 100644 (file)
@@ -309,13 +309,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',
index a88ebbeda8234e993efb015747dd679b8b0a915d..e6a2cf21cd05dffc1068e98be74fe91abef915b1 100644 (file)
@@ -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
         *
index df37fd29f42b86edd3ad3d8c80ffdf1650615753..51ccaeba998cb5558d5694f177037e4c0f3ff233 100644 (file)
@@ -75,8 +75,12 @@ class SeekableHttpStream implements File {
 
        /** @var ?resource|closed-resource */
        private $current;
+       /** @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): bool {
@@ -128,6 +132,9 @@ class SeekableHttpStream implements File {
 
                $this->offset = $begin;
                $this->length = $length;
+               if ($start === 0) {
+                       $this->totalSize = $length;
+               }
 
                return true;
        }
@@ -211,7 +218,9 @@ class SeekableHttpStream implements File {
 
        public function stream_stat() {
                if ($this->getCurrent()) {
-                       return fstat($this->getCurrent());
+                       $stat = fstat($this->getCurrent());
+                       $stat['size'] = $this->totalSize;
+                       return $stat;
                } else {
                        return false;
                }