Merge "Read full memcached response before manipulating data"
[lhc/web/wiklou.git] / includes / clientpool / RedisConnectionPool.php
index 95a0afa..e81bc5d 100644 (file)
@@ -28,7 +28,7 @@
  * This can be used to get handle wrappers that free the handle when the wrapper
  * leaves scope. The maximum number of free handles (connections) is configurable.
  * This provides an easy way to cache connection handles that may also have state,
- * such as handle does between multi() and exec(), and without hoarding connections.
+ * such as handle does between multi() and exec(), and without hoarding connections.
  * The wrappers use PHP magic methods so that calling functions on them calls the
  * function of the actual Redis object handle.
  *
@@ -72,18 +72,10 @@ class RedisConnectionPool {
                        throw new MWException( __CLASS__. ' requires the phpredis extension: ' .
                                'https://github.com/nicolasff/phpredis' );
                }
-               $this->connectTimeout = isset( $options['connectTimeout'] )
-                       ? $options['connectTimeout']
-                       : 1;
-               $this->persistent = isset( $options['persistent'] )
-                       ? $options['persistent']
-                       : false;
-               $this->password = isset( $options['password'] )
-                       ? $options['password']
-                       : '';
-               $this->poolSize = isset( $options['poolSize'] )
-                       ? $options['poolSize']
-                       : 5;
+               $this->connectTimeout = $options['connectTimeout'];
+               $this->persistent = $options['persistent'];
+               $this->password = $options['password'];
+               $this->poolSize = $options['poolSize'];
                if ( !isset( $options['serializer'] ) || $options['serializer'] === 'php' ) {
                        $this->serializer = Redis::SERIALIZER_PHP;
                } elseif ( $options['serializer'] === 'igbinary' ) {
@@ -93,16 +85,46 @@ class RedisConnectionPool {
                }
        }
 
+       /**
+        * @param $options Array
+        * @return Array
+        */
+       protected static function applyDefaultConfig( array $options ) {
+               if ( !isset( $options['connectTimeout'] ) ) {
+                       $options['connectTimeout'] = 1;
+               }
+               if ( !isset( $options['persistent'] ) ) {
+                       $options['persistent'] = false;
+               }
+               if ( !isset( $options['password'] ) ) {
+                       $options['password'] = '';
+               }
+               if ( !isset( $options['poolSize'] ) ) {
+                       $options['poolSize'] = 1;
+               }
+               return $options;
+       }
+
        /**
         * @param $options Array
         * @return RedisConnectionPool
         */
        public static function singleton( array $options ) {
-               $id = sha1( serialize( $options ) );
+               $options = self::applyDefaultConfig( $options );
+               // Map the options to a unique hash...
+               $poolOptions = $options;
+               unset( $poolOptions['poolSize'] ); // avoid pool fragmentation
+               ksort( $poolOptions ); // normalize to avoid pool fragmentation
+               $id = sha1( serialize( $poolOptions ) );
+               // Initialize the object at the hash as needed...
                if ( !isset( self::$instances[$id] ) ) {
                        self::$instances[$id] = new self( $options );
                        wfDebug( "Creating a new " . __CLASS__ . " instance with id $id." );
                }
+               // Simply grow the pool size if the existing one is too small
+               $psize = $options['poolSize']; // size requested
+               self::$instances[$id]->poolSize = max( $psize, self::$instances[$id]->poolSize );
+
                return self::$instances[$id];
        }