X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fobjectcache%2FRedisBagOStuff.php;h=ae8cc5b70b88361c0e614a3dd52f85b67e716bfa;hb=9079f55f69724f45374cfbf41fc2261808ff95bd;hp=d6d49ae5824872cdc1bad357b067e76e44ec65e0;hpb=0e675650aed26a742a9c2173d9469647a9f42bcc;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/objectcache/RedisBagOStuff.php b/includes/objectcache/RedisBagOStuff.php index d6d49ae582..ae8cc5b70b 100644 --- a/includes/objectcache/RedisBagOStuff.php +++ b/includes/objectcache/RedisBagOStuff.php @@ -211,6 +211,59 @@ class RedisBagOStuff extends BagOStuff { return $result; } + /** + * @param array $data + * @param int $expiry + * @return bool + */ + public function setMulti( array $data, $expiry = 0 ) { + $section = new ProfileSection( __METHOD__ ); + + $batches = array(); + $conns = array(); + foreach ( $data as $key => $value ) { + list( $server, $conn ) = $this->getConnection( $key ); + if ( !$conn ) { + continue; + } + $conns[$server] = $conn; + $batches[$server][] = $key; + } + + $expiry = $this->convertToRelative( $expiry ); + $result = true; + foreach ( $batches as $server => $batchKeys ) { + $conn = $conns[$server]; + try { + $conn->multi( Redis::PIPELINE ); + foreach ( $batchKeys as $key ) { + if ( $expiry ) { + $conn->setex( $key, $expiry, $this->serialize( $data[$key] ) ); + } else { + $conn->set( $key, $this->serialize( $data[$key] ) ); + } + } + $batchResult = $conn->exec(); + if ( $batchResult === false ) { + $this->debug( "setMulti request to $server failed" ); + continue; + } + foreach ( $batchResult as $value ) { + if ( $value === false ) { + $result = false; + } + } + } catch ( RedisException $e ) { + $this->handleException( $server, $conn, $e ); + $result = false; + } + } + + return $result; + } + + + public function add( $key, $value, $expiry = 0 ) { $section = new ProfileSection( __METHOD__ ); @@ -245,9 +298,9 @@ class RedisBagOStuff extends BagOStuff { * command. But we are constrained by the memcached-like interface to * return null in that case. Once the key exists, further increments are * atomic. - * @param string $key - * @param int $value - * @param bool|mixed + * @param string $key Key to increase + * @param int $value Value to add to $key (Default 1) + * @return int|bool New value or false on failure */ public function incr( $key, $value = 1 ) { $section = new ProfileSection( __METHOD__ ); @@ -260,7 +313,7 @@ class RedisBagOStuff extends BagOStuff { return null; } try { - $result = $this->unserialize( $conn->incrBy( $key, $value ) ); + $result = $conn->incrBy( $key, $value ); } catch ( RedisException $e ) { $result = false; $this->handleException( $conn, $e ); @@ -269,14 +322,14 @@ class RedisBagOStuff extends BagOStuff { $this->logRequest( 'incr', $key, $server, $result ); return $result; } - /** * @param mixed $data * @return string */ protected function serialize( $data ) { - // Ignore digit strings and ints so INCR/DECR work - return ( is_int( $data ) || ctype_digit( $data ) ) ? $data : serialize( $data ); + // Serialize anything but integers so INCR/DECR work + // Do not store integer-like strings as integers to avoid type confusion (bug 60563) + return is_int( $data ) ? $data : serialize( $data ); } /** @@ -284,12 +337,12 @@ class RedisBagOStuff extends BagOStuff { * @return mixed */ protected function unserialize( $data ) { - // Ignore digit strings and ints so INCR/DECR work - return ( is_int( $data ) || ctype_digit( $data ) ) ? $data : unserialize( $data ); + return ctype_digit( $data ) ? intval( $data ) : unserialize( $data ); } /** * Get a Redis object with a connection suitable for fetching the specified key + * @param string $key * @return array (server, RedisConnRef) or (false, false) */ protected function getConnection( $key ) {