summaryrefslogtreecommitdiffstats
path: root/lib/private/files
diff options
context:
space:
mode:
authorringmaster <epithet@gmail.com>2014-05-20 17:44:57 -0400
committerThomas Müller <thomas.mueller@tmit.eu>2014-06-04 07:55:44 +0200
commit5365ae416ec1a2c1dd868707cbb01f50bbe9027d (patch)
tree09b8a89846594eedbb14adb4f5ae31204205c912 /lib/private/files
parent3a1994d00149bea6d554c96a3bdee3126cfb17b8 (diff)
downloadnextcloud-server-5365ae416ec1a2c1dd868707cbb01f50bbe9027d.tar.gz
nextcloud-server-5365ae416ec1a2c1dd868707cbb01f50bbe9027d.zip
flock changes. Work in progress.
Diffstat (limited to 'lib/private/files')
-rw-r--r--lib/private/files/storage/local.php14
-rw-r--r--lib/private/files/storage/wrapper/lockingwrapper.php139
2 files changed, 153 insertions, 0 deletions
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