]> source.dussan.org Git - nextcloud-server.git/commitdiff
Added part files for when writing chunks
authorVincent Petry <pvince81@owncloud.com>
Wed, 11 Feb 2015 15:26:03 +0000 (16:26 +0100)
committerThomas Müller <thomas.mueller@tmit.eu>
Mon, 16 Mar 2015 09:13:13 +0000 (10:13 +0100)
Whenever a chunk is being written, it is now written to a part file
first. This is to avoid a concurrent chunk upload to believe that the
former chunk already exists, even though it's not fully written.

This makes sure that the final file assembly is only done when all
chunks were successfully written.

Also added an extra unique id to chunk parts in case the same chunk is
uploaded twice concurrently.

lib/private/cache/file.php

index 6fa7686ea96e9ad238eb5b460cb027648844e4bf..8ec048ccba077af9635e7c3c1534c44a09e12b0b 100644 (file)
@@ -11,6 +11,7 @@ namespace OC\Cache;
 
 use OC\Files\Filesystem;
 use OC\Files\View;
+use OCP\Security\ISecureRandom;
 
 class File {
        protected $storage;
@@ -79,12 +80,22 @@ class File {
                $storage = $this->getStorage();
                $result = false;
                $proxyStatus = \OC_FileProxy::$enabled;
+               // unique id to avoid chunk collision, just in case
+               $uniqueId = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(
+                       16,
+                       ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER
+               );
+
+               // use part file to prevent hasKey() to find the key
+               // while it is being written
+               $keyPart = $key . '.' . $uniqueId . '.part';
                \OC_FileProxy::$enabled = false;
-               if ($storage and $storage->file_put_contents($key, $value)) {
+               if ($storage and $storage->file_put_contents($keyPart, $value)) {
                        if ($ttl === 0) {
                                $ttl = 86400; // 60*60*24
                        }
-                       $result = $storage->touch($key, time() + $ttl);
+                       $result = $storage->touch($keyPart, time() + $ttl);
+                       $result &= $storage->rename($keyPart, $key);
                }
                \OC_FileProxy::$enabled = $proxyStatus;
                return $result;