Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorringmaster <epithet@gmail.com>2014-05-21 01:44:57 +0400
committerThomas Müller <thomas.mueller@tmit.eu>2014-06-04 09:55:44 +0400
commit5365ae416ec1a2c1dd868707cbb01f50bbe9027d (patch)
tree09b8a89846594eedbb14adb4f5ae31204205c912
parent3a1994d00149bea6d554c96a3bdee3126cfb17b8 (diff)
flock changes. Work in progress.
-rw-r--r--apps/files_external/lib/streamwrapper.php1
-rw-r--r--lib/private/files/storage/local.php14
-rw-r--r--lib/private/files/storage/wrapper/lockingwrapper.php139
-rwxr-xr-xlib/private/util.php10
-rw-r--r--lib/public/files/lock.php48
-rw-r--r--lib/public/files/locknotacquiredexception.php47
-rw-r--r--lib/public/files/storage.php1
7 files changed, 259 insertions, 1 deletions
diff --git a/apps/files_external/lib/streamwrapper.php b/apps/files_external/lib/streamwrapper.php
index 44bd9a0161a..d749f62afe7 100644
--- a/apps/files_external/lib/streamwrapper.php
+++ b/apps/files_external/lib/streamwrapper.php
@@ -103,5 +103,4 @@ abstract class StreamWrapper extends Common {
public function stat($path) {
return stat($this->constructUrl($path));
}
-
}
diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php
index e33747bbd52..565f9202d5c 100644
--- a/lib/private/files/storage/local.php
+++ b/lib/private/files/storage/local.php
@@ -279,5 +279,19 @@ if (\OC_Util::runningOnWindows()) {
public function isLocal() {
return true;
}
+
+ /**
+ * Acquire a lock on a file
+ */
+ public function getLock($path, $lockType) {
+ return true;
+ }
+
+ /**
+ * Release an existing lock
+ */
+ public function releaseLock($path) {
+ return true;
+ }
}
}
diff --git a/lib/private/files/storage/wrapper/lockingwrapper.php b/lib/private/files/storage/wrapper/lockingwrapper.php
new file mode 100644
index 00000000000..04a325940bf
--- /dev/null
+++ b/lib/private/files/storage/wrapper/lockingwrapper.php
@@ -0,0 +1,139 @@
+<?php
+
+/**
+ * Copyright (c) 2013 ownCloud, Inc.
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Storage\Wrapper;
+
+use OC\Files\Filesystem;
+use OCP\Files\LockNotAcquiredException;
+use OCP\Files\Lock;
+
+/**
+ * Class LockingWrapper
+ * A Storage Wrapper used to lock files at the system level
+ * @package OC\Files\Storage\Wrapper
+ *
+ * Notes: Does the $locks array need to be global to all LockingWrapper instances, such as in the case of two paths
+ * that point to the same physical file? Otherwise accessing the file from a different path the second time would show
+ * the file as locked, even though this process is the one locking it.
+ */
+class LockingWrapper extends Wrapper {
+
+ /** @var array $locks Holds an array of lock instances indexed by path for this storage */
+ protected $locks = array();
+
+ /**
+ * Acquire a lock on a file
+ * @param string $path Path to file, relative to this storage
+ * @param integer $lockType A Lock class constant, Lock::READ/Lock::WRITE
+ * @return bool|\OCP\Files\Lock Lock instance on success, false on failure
+ */
+ protected function getLock($path, $lockType){
+ $path = Filesystem::normalizePath($path);
+ if(!isset($this->locks[$path])) {
+ $this->locks[$path] = new Lock($path);
+ }
+ $this->locks[$path]->addLock($lockType);
+ return $this->locks[$path];
+ }
+
+ /**
+ * Release an existing lock
+ * @param string $path Path to file, relative to this storage
+ * @return bool true on success, false on failure
+ */
+ protected function releaseLock($path, $lockType, $releaseAll = false){
+ $path = Filesystem::normalizePath($path);
+ if(isset($this->locks[$path])) {
+ if($releaseAll) {
+ return $this->locks[$path]->releaseAll();
+ }
+ else {
+ return $this->locks[$path]->release($lockType);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * see http://php.net/manual/en/function.file_get_contents.php
+ * @param string $path
+ * @return string
+ * @throws \Exception
+ */
+ public function file_get_contents($path) {
+ try {
+ if (!$this->getLock($path, Lock::READ)) {
+ throw new LockNotAcquiredException($path, Lock::READ);
+ }
+ $result = $this->storage->file_get_contents($path);
+ }
+ catch(\Exception $originalException) {
+ // Need to release the lock before more operations happen in upstream exception handlers
+ $this->releaseLock($path, Lock::READ);
+ throw $originalException;
+ }
+ return $result;
+ }
+
+ public function file_put_contents($path, $data) {
+ try {
+ if (!$this->getLock($path, Lock::WRITE)) {
+ throw new LockNotAcquiredException($path, Lock::WRITE);
+ }
+ $result = $this->storage->file_put_contents($path, $data);
+ }
+ catch(\Exception $originalException) {
+ // Release lock, throw original exception
+ $this->releaseLock($path, Lock::WRITE);
+ throw $originalException;
+ }
+ return $result;
+ }
+
+
+ public function copy($path1, $path2) {
+ try {
+ if (!$this->getLock($path1, Lock::READ)) {
+ throw new LockNotAcquiredException($path1, Lock::READ);
+ }
+ if (!$this->getLock($path2, Lock::WRITE)) {
+ throw new LockNotAcquiredException($path2, Lock::WRITE);
+ }
+ $result = $this->storage->copy($path1, $path2);
+ }
+ catch(\Exception $originalException) {
+ // Release locks, throw original exception
+ $this->releaseLock($path1, Lock::READ);
+ $this->releaseLock($path2, Lock::WRITE);
+ throw $originalException;
+ }
+ return $result;
+ }
+
+ public function rename($path1, $path2) {
+ try {
+ if (!$this->getLock($path1, Lock::READ)) {
+ throw new LockNotAcquiredException($path1, Lock::READ);
+ }
+ if (!$this->getLock($path2, Lock::WRITE)) {
+ throw new LockNotAcquiredException($path2, Lock::WRITE);
+ }
+ $result = $this->storage->rename($path1, $path2);
+ }
+ catch(\Exception $originalException) {
+ // Release locks, throw original exception
+ $this->releaseLock($path1, Lock::READ);
+ $this->releaseLock($path2, Lock::WRITE);
+ throw $originalException;
+ }
+ return $result;
+ }
+
+
+} \ No newline at end of file
diff --git a/lib/private/util.php b/lib/private/util.php
index 306e37b9478..8cc48c03462 100755
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -71,6 +71,16 @@ class OC_Util {
return $storage;
});
+ // Set up flock
+ \OC\Files\Filesystem::addStorageWrapper(function($mountPoint, /** @var \OC\Files\Storage\Storage|null $storage */ $storage){
+ // lock files on all local storage
+ if ($storage instanceof \OC\Files\Storage\Storage && $storage->isLocal()) {
+ return new \OC\Files\Storage\Wrapper\LockingWrapper(array('storage' => $storage));
+ } else {
+ return $storage;
+ }
+ });
+
$userDir = '/'.$user.'/files';
$userRoot = OC_User::getHome($user);
$userDirectory = $userRoot . '/files';
diff --git a/lib/public/files/lock.php b/lib/public/files/lock.php
new file mode 100644
index 00000000000..fb1e4b9f1c5
--- /dev/null
+++ b/lib/public/files/lock.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files;
+
+/**
+ * Class Lock
+ * @package OC\Files
+ */
+class Lock {
+ const READ = 1;
+ const WRITE = 2;
+
+ /** @var string $path Filename of the file as represented in storage */
+ protected $path;
+
+ public function __construct($path) {
+ $this->path = $path;
+ }
+
+ public function addLock($lockType) {
+ // This class is a stub/base for classes that implement locks
+ // We don't actually care what kind of lock we're queuing here
+ }
+
+ /**
+ * Release locks on handles and files
+ */
+ public function release($lockType) {
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/lib/public/files/locknotacquiredexception.php b/lib/public/files/locknotacquiredexception.php
new file mode 100644
index 00000000000..9fb70e7cbe2
--- /dev/null
+++ b/lib/public/files/locknotacquiredexception.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/LockNotAcquiredException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for a file that is locked
+ */
+class LockNotAcquiredException extends \Exception {
+ /** @var string $path The path that could not be locked */
+ public $path;
+
+ /** @var integer $lockType The type of the lock that was attempted */
+ public $lockType;
+
+ public function __construct($path, $lockType, $code = 0, \Exception $previous = null) {
+ $message = \OC_L10N::get('core')->t('Could not obtain lock type %d on "%s".', array($lockType, $path));
+ parent::__construct($message, $code, $previous);
+ }
+
+ // custom string representation of object
+ public function __toString() {
+ return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
+ }
+} \ No newline at end of file
diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php
index 323d20db564..758cbb27377 100644
--- a/lib/public/files/storage.php
+++ b/lib/public/files/storage.php
@@ -35,6 +35,7 @@ namespace OCP\Files;
* All paths passed to the storage are relative to the storage and should NOT have a leading slash.
*/
interface Storage {
+
/**
* $parameters is a free form array with the configuration options needed to construct the storage
*