add method to atomically change between shared and exclusive lock
This commit is contained in:
parent
43772e2a9a
commit
a1372b2fb5
|
@ -98,6 +98,26 @@ class MemcacheLockingProvider implements ILockingProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the type of an existing lock
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
|
||||||
|
* @throws \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function changeLock($path, $targetType) {
|
||||||
|
if ($targetType === self::LOCK_SHARED) {
|
||||||
|
if (!$this->memcache->cas($path, 'exclusive', 1)) {
|
||||||
|
throw new LockedException($path);
|
||||||
|
}
|
||||||
|
} else if ($targetType === self::LOCK_EXCLUSIVE) {
|
||||||
|
// we can only change a shared lock to an exclusive if there's only a single owner of the shared lock
|
||||||
|
if (!$this->memcache->cas($path, 1, 'exclusive')) {
|
||||||
|
throw new LockedException($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* release all lock acquired by this instance
|
* release all lock acquired by this instance
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,15 @@ interface ILockingProvider {
|
||||||
*/
|
*/
|
||||||
public function releaseLock($path, $type);
|
public function releaseLock($path, $type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the type of an existing lock
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
|
||||||
|
* @throws \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function changeLock($path, $targetType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* release all lock acquired by this instance
|
* release all lock acquired by this instance
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -158,4 +158,57 @@ abstract class LockingProvider extends TestCase {
|
||||||
$this->assertEquals('foo', $e->getPath());
|
$this->assertEquals('foo', $e->getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testChangeLockToExclusive() {
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
$this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
|
||||||
|
$this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeLockToShared() {
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
|
||||||
|
$this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function testChangeLockToExclusiveDoubleShared() {
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function testChangeLockToExclusiveNoShared() {
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function testChangeLockToExclusiveFromExclusive() {
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function testChangeLockToSharedNoExclusive() {
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Lock\LockedException
|
||||||
|
*/
|
||||||
|
public function testChangeLockToSharedFromShared() {
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue