Added merge() function to BagOStuff for CAS-like functionality.
[lhc/web/wiklou.git] / includes / objectcache / RedisBagOStuff.php
index 4715859..bd5b354 100644 (file)
@@ -90,7 +90,7 @@ class RedisBagOStuff extends BagOStuff {
                }
        }
 
-       public function get( $key ) {
+       public function get( $key, &$casToken = null ) {
                wfProfileIn( __METHOD__ );
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
@@ -103,6 +103,7 @@ class RedisBagOStuff extends BagOStuff {
                        $result = false;
                        $this->handleException( $server, $e );
                }
+               $casToken = $result;
                $this->logRequest( 'get', $key, $server, $result );
                wfProfileOut( __METHOD__ );
                return $result;
@@ -133,6 +134,49 @@ class RedisBagOStuff extends BagOStuff {
                return $result;
        }
 
+       /**
+        * @param $casToken mixed
+        * @param $key string
+        * @param $value mixed
+        * @param $exptime int
+        * @return bool
+        */
+       public function cas( $casToken, $key, $value, $expiry = 0 ) {
+               wfProfileIn( __METHOD__ );
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       wfProfileOut( __METHOD__ );
+                       return false;
+               }
+               $expiry = $this->convertToRelative( $expiry );
+               try {
+                       $conn->watch( $key );
+
+                       if ( $this->get( $key ) !== $casToken ) {
+                               wfProfileOut( __METHOD__ );
+                               return false;
+                       }
+
+                       $conn->multi();
+
+                       if ( !$expiry ) {
+                               // No expiry, that is very different from zero expiry in Redis
+                               $conn->set( $key, $value );
+                       } else {
+                               $conn->setex( $key, $expiry, $value );
+                       }
+
+                       $result = $conn->exec();
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $server, $e );
+               }
+
+               $this->logRequest( 'cas', $key, $server, $result );
+               wfProfileOut( __METHOD__ );
+               return $result;
+       }
+
        public function delete( $key, $time = 0 ) {
                wfProfileIn( __METHOD__ );
                list( $server, $conn ) = $this->getConnection( $key );