[Pkg-owncloud-commits] [owncloud] 206/457: high level locking wip
David Prévot
taffit at moszumanska.debian.org
Sun Jun 28 20:06:07 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch stable8
in repository owncloud.
commit 7e418c7d699718b6d934de6184f6c96fdf9437d6
Author: Robin Appelman <icewind at owncloud.com>
Date: Tue May 5 13:48:49 2015 +0200
high level locking wip
---
lib/private/files/view.php | 64 ++++++++++++++++++++++++++++++++++++++++++----
tests/lib/files/view.php | 27 +++++++++++++++++++
2 files changed, 86 insertions(+), 5 deletions(-)
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index c82f8e1..eb6fd0b 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -41,6 +41,7 @@
namespace OC\Files;
+use Icewind\Streams\CallbackWrapper;
use OC\Files\Cache\Updater;
use OC\Files\Mount\MoveableMount;
use OCP\Files\FileNameTooLongException;
@@ -636,6 +637,9 @@ class View {
$internalPath1 = $mount1->getInternalPath($absolutePath1);
$internalPath2 = $mount2->getInternalPath($absolutePath2);
+ $this->lockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
+ $this->lockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
+
if ($internalPath1 === '' and $mount1 instanceof MoveableMount) {
if ($this->isTargetAllowed($absolutePath2)) {
/**
@@ -656,6 +660,10 @@ class View {
} else {
$result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
}
+
+ $this->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
+ $this->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
+
if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
// if it was a rename from a part file to a regular file it was a write and not a rename operation
$this->updater->update($path2);
@@ -734,6 +742,9 @@ class View {
$internalPath1 = $mount1->getInternalPath($absolutePath1);
$storage2 = $mount2->getStorage();
$internalPath2 = $mount2->getInternalPath($absolutePath2);
+
+ $this->lockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
+
if ($mount1->getMountPoint() == $mount2->getMountPoint()) {
if ($storage1) {
$result = $storage1->copy($internalPath1, $internalPath2);
@@ -744,6 +755,9 @@ class View {
$result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2);
}
$this->updater->update($path2);
+
+ $this->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
+
if ($this->shouldEmitHooks() && $result !== false) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
@@ -939,10 +953,24 @@ class View {
$run = $this->runHooks($hooks, $path);
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
if ($run and $storage) {
- if (!is_null($extraParam)) {
- $result = $storage->$operation($internalPath, $extraParam);
+ if (in_array('write', $hooks) || in_array('delete', $hooks)) {
+ $this->lockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
} else {
- $result = $storage->$operation($internalPath);
+ $this->lockFile($path, ILockingProvider::LOCK_SHARED);
+ }
+ try {
+ if (!is_null($extraParam)) {
+ $result = $storage->$operation($internalPath, $extraParam);
+ } else {
+ $result = $storage->$operation($internalPath);
+ }
+ } catch (\Exception $e) {
+ if (in_array('write', $hooks) || in_array('delete', $hooks)) {
+ $this->lockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
+ } else {
+ $this->lockFile($path, ILockingProvider::LOCK_SHARED);
+ }
+ throw $e;
}
if (in_array('delete', $hooks) and $result) {
@@ -955,6 +983,23 @@ class View {
$this->updater->update($path, $extraParam);
}
+ if ($operation === 'fopen') {
+ $result = CallbackWrapper::wrap($result, null, null, function () use ($hooks, $path) {
+ if (in_array('write', $hooks)) {
+ $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
+ } else {
+ $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
+ }
+ });
+ } else {
+ if (in_array('write', $hooks) || in_array('delete', $hooks)) {
+ $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
+ } else {
+ $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
+ }
+ }
+
+
if ($this->shouldEmitHooks($path) && $result !== false) {
if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open
$this->runHooks($hooks, $path, true);
@@ -1568,6 +1613,9 @@ class View {
* @return string[]
*/
private function getParents($path) {
+ if (!$path) {
+ return [];
+ }
$parts = explode('/', $path);
// remove the singe file
@@ -1585,12 +1633,16 @@ class View {
private function lockPath($path, $type) {
$mount = $this->getMount($path);
- $mount->getStorage()->acquireLock($mount->getInternalPath($path), $type, $this->lockingProvider);
+ if ($mount) {
+ $mount->getStorage()->acquireLock($mount->getInternalPath($this->getAbsolutePath($path)), $type, $this->lockingProvider);
+ }
}
private function unlockPath($path, $type) {
$mount = $this->getMount($path);
- $mount->getStorage()->releaseLock($mount->getInternalPath($path), $type, $this->lockingProvider);
+ if ($mount) {
+ $mount->getStorage()->releaseLock($mount->getInternalPath($this->getAbsolutePath($path)), $type, $this->lockingProvider);
+ }
}
/**
@@ -1600,6 +1652,7 @@ class View {
* @param int $type
*/
public function lockFile($path, $type) {
+ $path = rtrim($path, '/');
$this->lockPath($path, $type);
$parents = $this->getParents($path);
@@ -1615,6 +1668,7 @@ class View {
* @param int $type
*/
public function unlockFile($path, $type) {
+ $path = rtrim($path, '/');
$this->unlockPath($path, $type);
$parents = $this->getParents($path);
diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php
index 6bc6355..9931074 100644
--- a/tests/lib/files/view.php
+++ b/tests/lib/files/view.php
@@ -11,6 +11,7 @@ use OC\Files\Cache\Watcher;
use OC\Files\Storage\Common;
use OC\Files\Mount\MountPoint;
use OC\Files\Storage\Temporary;
+use OCP\Lock\ILockingProvider;
class TemporaryNoTouch extends \OC\Files\Storage\Temporary {
public function touch($path, $mtime = null) {
@@ -1080,4 +1081,30 @@ class View extends \Test\TestCase {
public function testNullAsRoot() {
new \OC\Files\View(null);
}
+
+ /**
+ * e.g. reading from a folder that's being renamed
+ *
+ * @expectedException \OCP\Lock\LockedException
+ */
+ public function testReadFromWriteLockedPath() {
+ $view = new \OC\Files\View();
+ $storage = new Temporary(array());
+ Filesystem::mount($storage, [], '/');
+ $view->lockFile('/foo/bar', ILockingProvider::LOCK_EXCLUSIVE);
+ $view->lockFile('/foo/bar/asd', ILockingProvider::LOCK_SHARED);
+ }
+
+ /**
+ * e.g. writing a file that's being downloaded
+ *
+ * @expectedException \OCP\Lock\LockedException
+ */
+ public function testWriteToReadLockedFile() {
+ $view = new \OC\Files\View();
+ $storage = new Temporary(array());
+ Filesystem::mount($storage, [], '/');
+ $view->lockFile('/foo/bar', ILockingProvider::LOCK_SHARED);
+ $view->lockFile('/foo/bar', ILockingProvider::LOCK_EXCLUSIVE);
+ }
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git
More information about the Pkg-owncloud-commits
mailing list