From d6bf5d43841f8d80ed54137db75c8ca6d2396cf4 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 12 Dec 2018 15:24:40 +0100 Subject: upload new files in objectstore to a .part path first This prevent the object store and cache from getting out of sync when an objectstore silently fails or the php process get's killed during the upload without giving us the chance to cleanup Signed-off-by: Robin Appelman --- .../Files/ObjectStore/ObjectStoreStorage.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php index 26db551a384..7ee1c8e2055 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php @@ -436,7 +436,10 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { $stat['mimetype'] = $mimetype; $stat['etag'] = $this->getETag($path); - $fileId = $this->getCache()->put($path, $stat); + $exists = $this->getCache()->inCache($path); + $uploadPath = $exists ? $path : $path . '.part'; + $fileId = $this->getCache()->put($uploadPath, $stat); + $urn = $this->getURN($fileId); try { //upload to object storage if ($size === null) { @@ -446,22 +449,31 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { ]); $size = $writtenSize; }); - $this->objectStore->writeObject($this->getURN($fileId), $countStream); + $this->objectStore->writeObject($urn, $countStream); if (is_resource($countStream)) { fclose($countStream); } } else { - $this->objectStore->writeObject($this->getURN($fileId), $stream); + $this->objectStore->writeObject($urn, $stream); } } catch (\Exception $ex) { - $this->getCache()->remove($path); + $this->getCache()->remove($uploadPath); $this->logger->logException($ex, [ 'app' => 'objectstore', - 'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path, + 'message' => 'Could not create object ' . $urn . ' for ' . $path, ]); throw $ex; // make this bubble up } + if (!$exists) { + if ($this->objectStore->objectExists($urn)) { + $this->getCache()->move($uploadPath, $path); + } else { + $this->getCache()->remove($uploadPath); + throw new \Exception("Object not found after writing (urn: $urn, path: $path)", 404); + } + } + return $size; } } -- cgit v1.2.3