aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2018-12-12 15:24:40 +0100
committerRobin Appelman <robin@icewind.nl>2018-12-12 15:24:40 +0100
commitd6bf5d43841f8d80ed54137db75c8ca6d2396cf4 (patch)
treeebd0520e813236fa005ec9fe49e1b04c3544a03d /lib
parent6c9f2644cf8bac151b9af743802eb72a51278e8b (diff)
downloadnextcloud-server-d6bf5d43841f8d80ed54137db75c8ca6d2396cf4.tar.gz
nextcloud-server-d6bf5d43841f8d80ed54137db75c8ca6d2396cf4.zip
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 <robin@icewind.nl>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreStorage.php22
1 files changed, 17 insertions, 5 deletions
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;
}
}