mirror of
https://github.com/nextcloud/server.git
synced 2026-06-13 10:40:40 -04:00
refactor: tidy up non-native CAD/NCAD implementations
Signed-off-by: Josh <josh.t.richards@gmail.com>
This commit is contained in:
parent
8fc8c6cef6
commit
0a05cc26e5
1 changed files with 64 additions and 26 deletions
|
|
@ -7,6 +7,9 @@
|
|||
*/
|
||||
namespace OC\Memcache;
|
||||
|
||||
/**
|
||||
* CAD/NCAD implementations for cache backends that lack their own.
|
||||
*/
|
||||
trait CADTrait {
|
||||
abstract public function get($key);
|
||||
|
||||
|
|
@ -15,42 +18,77 @@ trait CADTrait {
|
|||
abstract public function add($key, $value, $ttl = 0);
|
||||
|
||||
/**
|
||||
* Compare and delete
|
||||
* Compare-and-delete.
|
||||
*
|
||||
* If $key's current value is equal to $expectedValue, delete $key.
|
||||
* Note may return false for reasons other than not meeting condition.
|
||||
*
|
||||
* Implements CAD using simple locking (only requiring backend add/remove support).
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $old
|
||||
* @return bool
|
||||
* @param mixed $expectedValue
|
||||
* @return bool True if key was deleted; False if no deletion occurred
|
||||
*/
|
||||
public function cad($key, $old) {
|
||||
//no native cas, emulate with locking
|
||||
if ($this->add($key . '_lock', true)) {
|
||||
if ($this->get($key) === $old) {
|
||||
$this->remove($key);
|
||||
$this->remove($key . '_lock');
|
||||
return true;
|
||||
} else {
|
||||
$this->remove($key . '_lock');
|
||||
return false;
|
||||
}
|
||||
public function cad($key, $expectedValue) {
|
||||
if (!$this->acquireLock($key)) {
|
||||
return false;
|
||||
}
|
||||
$currentValue = $this->get($key);
|
||||
// Check condition
|
||||
if ($currentValue === $expectedValue) {
|
||||
// Matches condition
|
||||
$this->remove($key);
|
||||
$this->releaseLock($key);
|
||||
return true;
|
||||
} else {
|
||||
// Fails condition
|
||||
$this->releaseLock($key);
|
||||
// TODO: consider throwing if release fails
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function ncad(string $key, mixed $old): bool {
|
||||
//no native cad, emulate with locking
|
||||
if ($this->add($key . '_lock', true)) {
|
||||
$value = $this->get($key);
|
||||
if ($value !== null && $value !== $old) {
|
||||
$this->remove($key);
|
||||
$this->remove($key . '_lock');
|
||||
return true;
|
||||
} else {
|
||||
$this->remove($key . '_lock');
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Nonequal-compare-and-delete.
|
||||
*
|
||||
* If $key's current value is not equal to $expectedValue, delete $key.
|
||||
* Note may return false for reasons other than not meeting condition.
|
||||
*
|
||||
* Implements NCAD using simple locking (only requiring backend add/remove support).
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $expectedValue
|
||||
* @return bool True if key was deleted; False if no deletion occurred
|
||||
*/
|
||||
public function ncad(string $key, mixed $expectedValue): bool {
|
||||
if (!$this->acquireLock($key)) {
|
||||
return false;
|
||||
}
|
||||
$currentValue = $this->get($key);
|
||||
// Check condition
|
||||
if ($currentValue !== null && $currentValue !== $expectedValue) {
|
||||
// Matches condition
|
||||
$this->remove($key);
|
||||
$this->releaseLock($key);
|
||||
return true;
|
||||
} else {
|
||||
// Fails condition
|
||||
$this->releaseLock($key);
|
||||
// TODO: consider throwing if release fails
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
||||
private function acquireLock(string $key): bool {
|
||||
// TODO: an actual TTL would be clearer
|
||||
return $this->add($key . '_lock', true);
|
||||
}
|
||||
|
||||
private function releaseLock(string $key): bool {
|
||||
return $this->remove($key . '_lock');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue