Merge pull request #21710 from nextcloud/backport/21074/stable19
[stable19] Fix releasing a shared lock multiple times
This commit is contained in:
commit
42d899c4d5
|
@ -41,6 +41,13 @@ class LockPlugin extends ServerPlugin {
|
||||||
*/
|
*/
|
||||||
private $server;
|
private $server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of the lock
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isLocked;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -48,6 +55,7 @@ class LockPlugin extends ServerPlugin {
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->server->on('beforeMethod:*', [$this, 'getLock'], 50);
|
$this->server->on('beforeMethod:*', [$this, 'getLock'], 50);
|
||||||
$this->server->on('afterMethod:*', [$this, 'releaseLock'], 50);
|
$this->server->on('afterMethod:*', [$this, 'releaseLock'], 50);
|
||||||
|
$this->isLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLock(RequestInterface $request) {
|
public function getLock(RequestInterface $request) {
|
||||||
|
@ -67,10 +75,15 @@ class LockPlugin extends ServerPlugin {
|
||||||
} catch (LockedException $e) {
|
} catch (LockedException $e) {
|
||||||
throw new FileLocked($e->getMessage(), $e->getCode(), $e);
|
throw new FileLocked($e->getMessage(), $e->getCode(), $e);
|
||||||
}
|
}
|
||||||
|
$this->isLocked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function releaseLock(RequestInterface $request) {
|
public function releaseLock(RequestInterface $request) {
|
||||||
|
// don't try to release the lock if we never locked one
|
||||||
|
if ($this->isLocked === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
|
if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -81,6 +94,7 @@ class LockPlugin extends ServerPlugin {
|
||||||
}
|
}
|
||||||
if ($node instanceof Node) {
|
if ($node instanceof Node) {
|
||||||
$node->releaseLock(ILockingProvider::LOCK_SHARED);
|
$node->releaseLock(ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->isLocked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,8 +94,12 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
|
||||||
*/
|
*/
|
||||||
public function releaseLock(string $path, int $type) {
|
public function releaseLock(string $path, int $type) {
|
||||||
if ($type === self::LOCK_SHARED) {
|
if ($type === self::LOCK_SHARED) {
|
||||||
|
$ownSharedLockCount = $this->getOwnSharedLockCount($path);
|
||||||
$newValue = 0;
|
$newValue = 0;
|
||||||
if ($this->getOwnSharedLockCount($path) === 1) {
|
if ($ownSharedLockCount === 0) { // if we are not holding the lock, don't try to release it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($ownSharedLockCount === 1) {
|
||||||
$removed = $this->memcache->cad($path, 1); // if we're the only one having a shared lock we can remove it in one go
|
$removed = $this->memcache->cad($path, 1); // if we're the only one having a shared lock we can remove it in one go
|
||||||
if (!$removed) { //someone else also has a shared lock, decrease only
|
if (!$removed) { //someone else also has a shared lock, decrease only
|
||||||
$newValue = $this->memcache->dec($path);
|
$newValue = $this->memcache->dec($path);
|
||||||
|
|
Loading…
Reference in New Issue