From 1bc56a99e9e368091753ff79facf930336478a35 Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Mon, 8 Jun 2015 15:22:20 +0200
Subject: [PATCH] compare-and-set and compare-and-delete using lua scripts for
 redis

---
 lib/private/memcache/redis.php | 52 ++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/lib/private/memcache/redis.php b/lib/private/memcache/redis.php
index cfc35dcc377..1ef9417eaf9 100644
--- a/lib/private/memcache/redis.php
+++ b/lib/private/memcache/redis.php
@@ -26,13 +26,15 @@ namespace OC\Memcache;
 use OCP\IMemcache;
 
 class Redis extends Cache implements IMemcache {
-	use CASTrait;
-
 	/**
 	 * @var \Redis $cache
 	 */
 	private static $cache = null;
 
+	private static $casScript;
+
+	private static $cadScript;
+
 	public function __construct($prefix = '') {
 		parent::__construct($prefix);
 		if (is_null(self::$cache)) {
@@ -57,6 +59,29 @@ class Redis extends Cache implements IMemcache {
 
 			self::$cache->connect($host, $port, $timeout);
 
+			self::$casScript = self::$cache->script('load', '
+local key = ARGV[1]
+local old = ARGV[2]
+local new = ARGV[3]
+
+if redis.call(\'get\', key) == old then
+  redis.call(\'set\', key, new)
+  return true
+end
+
+return false');
+
+			self::$cadScript = self::$cache->script('load', '
+local key = ARGV[1]
+local old = ARGV[2]
+
+if redis.call(\'get\', key) == old then
+  redis.call(\'del\', key)
+  return true
+end
+
+return false');
+
 			if (isset($config['dbindex'])) {
 				self::$cache->select($config['dbindex']);
 			}
@@ -150,6 +175,29 @@ class Redis extends Cache implements IMemcache {
 		return self::$cache->decrBy($this->getNamespace() . $key, $step);
 	}
 
+	/**
+	 * Compare and set
+	 *
+	 * @param string $key
+	 * @param mixed $old
+	 * @param mixed $new
+	 * @return bool
+	 */
+	public function cas($key, $old, $new) {
+		return (bool) self::$cache->evalSha(self::$casScript, [$this->getNamespace() . $key, json_encode($old), json_encode($new)]);
+	}
+
+	/**
+	 * Compare and delete
+	 *
+	 * @param string $key
+	 * @param mixed $old
+	 * @return bool
+	 */
+	public function cad($key, $old) {
+		return (bool)self::$cache->evalSha(self::$cadScript, [$this->getNamespace() . $key, json_encode($old)]);
+	}
+
 	static public function isAvailable() {
 		return extension_loaded('redis')
 			&& version_compare(phpversion('redis'), '2.2.5', '>=');
-- 
GitLab