* changed variable list as per comment on r79954 left only wgDBtype
[lhc/web/wiklou.git] / includes / memcached-client.php
index d63a4b8..53f0324 100644 (file)
@@ -1,40 +1,41 @@
 <?php
-//
-// +---------------------------------------------------------------------------+
-// | memcached client, PHP                                                     |
-// +---------------------------------------------------------------------------+
-// | Copyright (c) 2003 Ryan T. Dean <rtdean@cytherianage.net>                 |
-// | All rights reserved.                                                      |
-// |                                                                           |
-// | Redistribution and use in source and binary forms, with or without        |
-// | modification, are permitted provided that the following conditions        |
-// | are met:                                                                  |
-// |                                                                           |
-// | 1. Redistributions of source code must retain the above copyright         |
-// |    notice, this list of conditions and the following disclaimer.          |
-// | 2. Redistributions in binary form must reproduce the above copyright      |
-// |    notice, this list of conditions and the following disclaimer in the    |
-// |    documentation and/or other materials provided with the distribution.   |
-// |                                                                           |
-// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
-// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
-// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
-// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
-// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
-// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
-// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
-// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
-// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
-// +---------------------------------------------------------------------------+
-// | Author: Ryan T. Dean <rtdean@cytherianage.net>                            |
-// | Heavily influenced by the Perl memcached client by Brad Fitzpatrick.      |
-// |   Permission granted by Brad Fitzpatrick for relicense of ported Perl     |
-// |   client logic under 2-clause BSD license.                                |
-// +---------------------------------------------------------------------------+
-//
-// $TCAnet$
-//
+/**
+ * +---------------------------------------------------------------------------+
+ * | memcached client, PHP                                                     |
+ * +---------------------------------------------------------------------------+
+ * | Copyright (c) 2003 Ryan T. Dean <rtdean@cytherianage.net>                 |
+ * | All rights reserved.                                                      |
+ * |                                                                           |
+ * | Redistribution and use in source and binary forms, with or without        |
+ * | modification, are permitted provided that the following conditions        |
+ * | are met:                                                                  |
+ * |                                                                           |
+ * | 1. Redistributions of source code must retain the above copyright         |
+ * |    notice, this list of conditions and the following disclaimer.          |
+ * | 2. Redistributions in binary form must reproduce the above copyright      |
+ * |    notice, this list of conditions and the following disclaimer in the    |
+ * |    documentation and/or other materials provided with the distribution.   |
+ * |                                                                           |
+ * | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
+ * | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
+ * | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
+ * | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
+ * | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
+ * | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
+ * | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
+ * | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
+ * | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
+ * +---------------------------------------------------------------------------+
+ * | Author: Ryan T. Dean <rtdean@cytherianage.net>                            |
+ * | Heavily influenced by the Perl memcached client by Brad Fitzpatrick.      |
+ * |   Permission granted by Brad Fitzpatrick for relicense of ported Perl     |
+ * |   client logic under 2-clause BSD license.                                |
+ * +---------------------------------------------------------------------------+
+ *
+ * @file
+ * $TCAnet$
+ */
 
 /**
  * This is the PHP client for memcached - a distributed memory cache daemon.
  * @author  Ryan T. Dean <rtdean@cytherianage.net>
  * @ingroup Cache
  */
-class MWMemcached
-{
-   // {{{ properties
-   // {{{ public
+class MWMemcached {
+       // {{{ properties
+       // {{{ public
 
        // {{{ constants
        // {{{ flags
@@ -240,26 +240,25 @@ class MWMemcached
        /**
         * Memcache initializer
         *
-        * @param   array    $args    Associative array of settings
+        * @param $args Array Associative array of settings
         *
         * @return  mixed
-        * @access  public
         */
-       function __construct ($args)
-       {
-               $this->set_servers(@$args['servers']);
-               $this->_debug = @$args['debug'];
+       public function __construct( $args ) {
+               global $wgMemCachedTimeout;
+               $this->set_servers( isset( $args['servers'] ) ? $args['servers'] : array() );
+               $this->_debug = isset( $args['debug'] ) ? $args['debug'] : false;
                $this->stats = array();
-               $this->_compress_threshold = @$args['compress_threshold'];
-               $this->_persistant = array_key_exists('persistant', $args) ? (@$args['persistant']) : false;
+               $this->_compress_threshold = isset( $args['compress_threshold'] ) ? $args['compress_threshold'] : 0;
+               $this->_persistant = isset( $args['persistant'] ) ? $args['persistant'] : false;
                $this->_compress_enable = true;
-               $this->_have_zlib = function_exists("gzcompress");
+               $this->_have_zlib = function_exists( 'gzcompress' );
 
                $this->_cache_sock = array();
                $this->_host_dead = array();
 
                $this->_timeout_seconds = 0;
-               $this->_timeout_microseconds = 50000;
+               $this->_timeout_microseconds = $wgMemCachedTimeout;
 
                $this->_connect_timeout = 0.01;
                $this->_connect_attempts = 2;
@@ -272,33 +271,33 @@ class MWMemcached
         * Adds a key/value to the memcache server if one isn't already set with
         * that key
         *
-        * @param   string  $key     Key to set with data
-        * @param   mixed   $val     Value to store
-        * @param   integer $exp     (optional) Time to expire data at
+        * @param $key String: key to set with data
+        * @param $val Mixed: value to store
+        * @param $exp Integer: (optional) Expiration time. This can be a number of seconds
+        * to cache for (up to 30 days inclusive).  Any timespans of 30 days + 1 second or
+        * longer must be the timestamp of the time at which the mapping should expire. It
+        * is safe to use timestamps in all cases, regardless of exipration
+        * eg: strtotime("+3 hour")
         *
-        * @return  boolean
-        * @access  public
+        * @return Boolean
         */
-       function add ($key, $val, $exp = 0)
-       {
-               return $this->_set('add', $key, $val, $exp);
+       public function add( $key, $val, $exp = 0 ) {
+               return $this->_set( 'add', $key, $val, $exp );
        }
 
        // }}}
        // {{{ decr()
 
        /**
-        * Decriment a value stored on the memcache server
+        * Decrease a value stored on the memcache server
         *
-        * @param   string   $key     Key to decriment
-        * @param   integer  $amt     (optional) Amount to decriment
+        * @param $key String: key to decrease
+        * @param $amt Integer: (optional) amount to decrease
         *
-        * @return  mixed    FALSE on failure, value on success
-        * @access  public
+        * @return Mixed: FALSE on failure, value on success
         */
-       function decr ($key, $amt=1)
-       {
-               return $this->_incrdecr('decr', $key, $amt);
+       public function decr( $key, $amt = 1 ) {
+               return $this->_incrdecr( 'decr', $key, $amt );
        }
 
        // }}}
@@ -307,37 +306,42 @@ class MWMemcached
        /**
         * Deletes a key from the server, optionally after $time
         *
-        * @param   string   $key     Key to delete
-        * @param   integer  $time    (optional) How long to wait before deleting
+        * @param $key String: key to delete
+        * @param $time Integer: (optional) how long to wait before deleting
         *
-        * @return  boolean  TRUE on success, FALSE on failure
-        * @access  public
+        * @return Boolean: TRUE on success, FALSE on failure
         */
-       function delete ($key, $time = 0)
-       {
-               if (!$this->_active)
+       public function delete( $key, $time = 0 ) {
+               if ( !$this->_active ) {
                        return false;
+               }
 
-               $sock = $this->get_sock($key);
-               if (!is_resource($sock))
+               $sock = $this->get_sock( $key );
+               if ( !is_resource( $sock ) ) {
                        return false;
+               }
 
-               $key = is_array($key) ? $key[1] : $key;
+               $key = is_array( $key ) ? $key[1] : $key;
 
-               @$this->stats['delete']++;
+               if ( isset( $this->stats['delete'] ) ) {
+                       $this->stats['delete']++;
+               } else {
+                       $this->stats['delete'] = 1;
+               }
                $cmd = "delete $key $time\r\n";
-               if(!$this->_safe_fwrite($sock, $cmd, strlen($cmd)))
-               {
-                       $this->_dead_sock($sock);
+               if( !$this->_safe_fwrite( $sock, $cmd, strlen( $cmd ) ) ) {
+                       $this->_dead_sock( $sock );
                        return false;
                }
-               $res = trim(fgets($sock));
+               $res = trim( fgets( $sock ) );
 
-               if ($this->_debug)
-                       $this->_debugprint(sprintf("MemCache: delete %s (%s)\n", $key, $res));
+               if ( $this->_debug ) {
+                       $this->_debugprint( sprintf( "MemCache: delete %s (%s)\n", $key, $res ) );
+               }
 
-               if ($res == "DELETED")
+               if ( $res == "DELETED" ) {
                        return true;
+               }
                return false;
        }
 
@@ -346,13 +350,11 @@ class MWMemcached
 
        /**
         * Disconnects all connected sockets
-        *
-        * @access  public
         */
-       function disconnect_all ()
-       {
-               foreach ($this->_cache_sock as $sock)
-                       fclose($sock);
+       public function disconnect_all() {
+               foreach ( $this->_cache_sock as $sock ) {
+                       fclose( $sock );
+               }
 
                $this->_cache_sock = array();
        }
@@ -363,12 +365,9 @@ class MWMemcached
        /**
         * Enable / Disable compression
         *
-        * @param   boolean  $enable  TRUE to enable, FALSE to disable
-        *
-        * @access  public
+        * @param $enable Boolean: TRUE to enable, FALSE to disable
         */
-       function enable_compress ($enable)
-       {
+       public function enable_compress( $enable ) {
                $this->_compress_enable = $enable;
        }
 
@@ -377,11 +376,8 @@ class MWMemcached
 
        /**
         * Forget about all of the dead hosts
-        *
-        * @access  public
         */
-       function forget_dead_hosts ()
-       {
+       public function forget_dead_hosts() {
                $this->_host_dead = array();
        }
 
@@ -391,47 +387,50 @@ class MWMemcached
        /**
         * Retrieves the value associated with the key from the memcache server
         *
-        * @param  string   $key     Key to retrieve
+        * @param $key Mixed: key to retrieve
         *
-        * @return  mixed
-        * @access  public
+        * @return Mixed
         */
-       function get ($key)
-       {
+       public function get( $key ) {
                wfProfileIn( __METHOD__ );
 
                if ( $this->_debug ) {
                        $this->_debugprint( "get($key)\n" );
                }
 
-               if (!$this->_active) {
+               if ( !$this->_active ) {
                        wfProfileOut( __METHOD__ );
                        return false;
                }
 
-               $sock = $this->get_sock($key);
+               $sock = $this->get_sock( $key );
 
-               if (!is_resource($sock)) {
+               if ( !is_resource( $sock ) ) {
                        wfProfileOut( __METHOD__ );
                        return false;
                }
 
-               @$this->stats['get']++;
+               if ( isset( $this->stats['get'] ) ) {
+                       $this->stats['get']++;
+               } else {
+                       $this->stats['get'] = 1;
+               }
 
                $cmd = "get $key\r\n";
-               if (!$this->_safe_fwrite($sock, $cmd, strlen($cmd)))
-               {
-                       $this->_dead_sock($sock);
+               if ( !$this->_safe_fwrite( $sock, $cmd, strlen( $cmd ) ) ) {
+                       $this->_dead_sock( $sock );
                        wfProfileOut( __METHOD__ );
                        return false;
                }
 
                $val = array();
-               $this->_load_items($sock, $val);
+               $this->_load_items( $sock, $val );
 
-               if ($this->_debug)
-                       foreach ($val as $k => $v)
-                               $this->_debugprint(sprintf("MemCache: sock %s got %s\n", serialize($sock), $k));
+               if ( $this->_debug ) {
+                       foreach ( $val as $k => $v ) {
+                               $this->_debugprint( sprintf( "MemCache: sock %s got %s\n", serialize( $sock ), $k ) );
+                       }
+               }
 
                wfProfileOut( __METHOD__ );
                return @$val[$key];
@@ -443,26 +442,29 @@ class MWMemcached
        /**
         * Get multiple keys from the server(s)
         *
-        * @param   array    $keys    Keys to retrieve
+        * @param $keys Array: keys to retrieve
         *
-        * @return  array
-        * @access  public
+        * @return Array
         */
-       function get_multi ($keys)
-       {
-               if (!$this->_active)
+       public function get_multi( $keys ) {
+               if ( !$this->_active ) {
                        return false;
+               }
 
-               @$this->stats['get_multi']++;
+               if ( isset( $this->stats['get_multi'] ) ) {
+                       $this->stats['get_multi']++;
+               } else {
+                       $this->stats['get_multi'] = 1;
+               }
                $sock_keys = array();
 
-               foreach ($keys as $key)
-               {
-                       $sock = $this->get_sock($key);
-                       if (!is_resource($sock)) continue;
-                       $key = is_array($key) ? $key[1] : $key;
-                       if (!isset($sock_keys[$sock]))
-                       {
+               foreach ( $keys as $key ) {
+                       $sock = $this->get_sock( $key );
+                       if ( !is_resource( $sock ) ) {
+                               continue;
+                       }
+                       $key = is_array( $key ) ? $key[1] : $key;
+                       if ( !isset( $sock_keys[$sock] ) ) {
                                $sock_keys[$sock] = array();
                                $socks[] = $sock;
                        }
@@ -470,34 +472,31 @@ class MWMemcached
                }
 
                // Send out the requests
-               foreach ($socks as $sock)
-               {
-                       $cmd = "get";
-                       foreach ($sock_keys[$sock] as $key)
-                       {
-                               $cmd .= " ". $key;
+               foreach ( $socks as $sock ) {
+                       $cmd = 'get';
+                       foreach ( $sock_keys[$sock] as $key ) {
+                               $cmd .= ' ' . $key;
                        }
                        $cmd .= "\r\n";
 
-                       if ($this->_safe_fwrite($sock, $cmd, strlen($cmd)))
-                       {
+                       if ( $this->_safe_fwrite( $sock, $cmd, strlen( $cmd ) ) ) {
                                $gather[] = $sock;
-                       } else
-                       {
-                               $this->_dead_sock($sock);
+                       } else {
+                               $this->_dead_sock( $sock );
                        }
                }
 
                // Parse responses
                $val = array();
-               foreach ($gather as $sock)
-               {
-                       $this->_load_items($sock, $val);
+               foreach ( $gather as $sock ) {
+                       $this->_load_items( $sock, $val );
                }
 
-               if ($this->_debug)
-                       foreach ($val as $k => $v)
-                               $this->_debugprint(sprintf("MemCache: got %s\n", $k));
+               if ( $this->_debug ) {
+                       foreach ( $val as $k => $v ) {
+                               $this->_debugprint( sprintf( "MemCache: got %s\n", $k ) );
+                       }
+               }
 
                return $val;
        }
@@ -508,15 +507,15 @@ class MWMemcached
        /**
         * Increments $key (optionally) by $amt
         *
-        * @param   string   $key     Key to increment
-        * @param   integer  $amt     (optional) amount to increment
+        * @param $key String: key to increment
+        * @param $amt Integer: (optional) amount to increment
         *
-        * @return  integer  New key value?
-        * @access  public
+        * @return Integer: null if the key does not exist yet (this does NOT
+        * create new mappings if the key does not exist). If the key does
+        * exist, this returns the new value for that key.
         */
-       function incr ($key, $amt=1)
-       {
-               return $this->_incrdecr('incr', $key, $amt);
+       public function incr( $key, $amt = 1 ) {
+               return $this->_incrdecr( 'incr', $key, $amt );
        }
 
        // }}}
@@ -525,16 +524,18 @@ class MWMemcached
        /**
         * Overwrites an existing value for key; only works if key is already set
         *
-        * @param   string   $key     Key to set value as
-        * @param   mixed    $value   Value to store
-        * @param   integer  $exp     (optional) Experiation time
+        * @param $key String: key to set value as
+        * @param $value Mixed: value to store
+        * @param $exp Integer: (optional) Expiration time. This can be a number of seconds
+        * to cache for (up to 30 days inclusive).  Any timespans of 30 days + 1 second or
+        * longer must be the timestamp of the time at which the mapping should expire. It
+        * is safe to use timestamps in all cases, regardless of exipration
+        * eg: strtotime("+3 hour")
         *
-        * @return  boolean
-        * @access  public
+        * @return Boolean
         */
-       function replace ($key, $value, $exp=0)
-       {
-               return $this->_set('replace', $key, $value, $exp);
+       public function replace( $key, $value, $exp = 0 ) {
+               return $this->_set( 'replace', $key, $value, $exp );
        }
 
        // }}}
@@ -550,28 +551,29 @@ class MWMemcached
         *       with a \n.  This is with the PHP flag auto_detect_line_endings set
         *       to falase (the default).
         *
-        * @param   resource $sock    Socket to send command on
-        * @param   string   $cmd     Command to run
+        * @param $sock Ressource: socket to send command on
+        * @param $cmd String: command to run
         *
-        * @return  array    Output array
-        * @access  public
+        * @return Array: output array
         */
-       function run_command ($sock, $cmd)
-       {
-               if (!is_resource($sock))
+       public function run_command( $sock, $cmd ) {
+               if ( !is_resource( $sock ) ) {
                        return array();
+               }
 
-               if (!$this->_safe_fwrite($sock, $cmd, strlen($cmd)))
+               if ( !$this->_safe_fwrite( $sock, $cmd, strlen( $cmd ) ) ) {
                        return array();
+               }
 
-               while (true)
-               {
-                       $res = fgets($sock);
+               while ( true ) {
+                       $res = fgets( $sock );
                        $ret[] = $res;
-                       if (preg_match('/^END/', $res))
+                       if ( preg_match( '/^END/', $res ) ) {
                                break;
-                       if (strlen($res) == 0)
+                       }
+                       if ( strlen( $res ) == 0 ) {
                                break;
+                       }
                }
                return $ret;
        }
@@ -583,16 +585,18 @@ class MWMemcached
         * Unconditionally sets a key to a given value in the memcache.  Returns true
         * if set successfully.
         *
-        * @param   string   $key     Key to set value as
-        * @param   mixed    $value   Value to set
-        * @param   integer  $exp     (optional) Experiation time
+        * @param $key String: key to set value as
+        * @param $value Mixed: value to set
+        * @param $exp Integer: (optional) Expiration time. This can be a number of seconds
+        * to cache for (up to 30 days inclusive).  Any timespans of 30 days + 1 second or
+        * longer must be the timestamp of the time at which the mapping should expire. It
+        * is safe to use timestamps in all cases, regardless of exipration
+        * eg: strtotime("+3 hour")
         *
-        * @return  boolean  TRUE on success
-        * @access  public
+        * @return Boolean: TRUE on success
         */
-       function set ($key, $value, $exp=0)
-       {
-               return $this->_set('set', $key, $value, $exp);
+       public function set( $key, $value, $exp = 0 ) {
+               return $this->_set( 'set', $key, $value, $exp );
        }
 
        // }}}
@@ -601,12 +605,9 @@ class MWMemcached
        /**
         * Sets the compression threshold
         *
-        * @param   integer  $thresh  Threshold to compress if larger than
-        *
-        * @access  public
+        * @param $thresh Integer: threshold to compress if larger than
         */
-       function set_compress_threshold ($thresh)
-       {
+       public function set_compress_threshold( $thresh ) {
                $this->_compress_threshold = $thresh;
        }
 
@@ -616,14 +617,11 @@ class MWMemcached
        /**
         * Sets the debug flag
         *
-        * @param   boolean  $dbg     TRUE for debugging, FALSE otherwise
-        *
-        * @access  public
+        * @param $dbg Boolean: TRUE for debugging, FALSE otherwise
         *
         * @see     MWMemcached::__construct
         */
-       function set_debug ($dbg)
-       {
+       public function set_debug( $dbg ) {
                $this->_debug = $dbg;
        }
 
@@ -633,34 +631,29 @@ class MWMemcached
        /**
         * Sets the server list to distribute key gets and puts between
         *
-        * @param   array    $list    Array of servers to connect to
-        *
-        * @access  public
+        * @param $list Array of servers to connect to
         *
         * @see     MWMemcached::__construct()
         */
-       function set_servers ($list)
-       {
+       public function set_servers( $list ) {
                $this->_servers = $list;
-               $this->_active = count($list);
+               $this->_active = count( $list );
                $this->_buckets = null;
                $this->_bucketcount = 0;
 
                $this->_single_sock = null;
-               if ($this->_active == 1)
+               if ( $this->_active == 1 ) {
                        $this->_single_sock = $this->_servers[0];
+               }
        }
 
        /**
         * Sets the timeout for new connections
         *
-        * @param   integer  $seconds Number of seconds
-        * @param   integer  $microseconds  Number of microseconds
-        *
-        * @access  public
+        * @param $seconds Integer: number of seconds
+        * @param $microseconds Integer: number of microseconds
         */
-       function set_timeout ($seconds, $microseconds)
-       {
+       public function set_timeout( $seconds, $microseconds ) {
                $this->_timeout_seconds = $seconds;
                $this->_timeout_microseconds = $microseconds;
        }
@@ -673,15 +666,14 @@ class MWMemcached
        /**
         * Close the specified socket
         *
-        * @param   string   $sock    Socket to close
+        * @param $sock String: socket to close
         *
         * @access  private
         */
-       function _close_sock ($sock)
-       {
-               $host = array_search($sock, $this->_cache_sock);
-               fclose($this->_cache_sock[$host]);
-               unset($this->_cache_sock[$host]);
+       function _close_sock( $sock ) {
+               $host = array_search( $sock, $this->_cache_sock );
+               fclose( $this->_cache_sock[$host] );
+               unset( $this->_cache_sock[$host] );
        }
 
        // }}}
@@ -690,35 +682,35 @@ class MWMemcached
        /**
         * Connects $sock to $host, timing out after $timeout
         *
-        * @param   integer  $sock    Socket to connect
-        * @param   string   $host    Host:IP to connect to
+        * @param $sock Integer: socket to connect
+        * @param $host String: Host:IP to connect to
         *
         * @return  boolean
         * @access  private
         */
-       function _connect_sock (&$sock, $host)
-       {
-               list ($ip, $port) = explode(":", $host);
+       function _connect_sock( &$sock, $host ) {
+               list( $ip, $port ) = explode( ':', $host );
                $sock = false;
                $timeout = $this->_connect_timeout;
                $errno = $errstr = null;
-               for ($i = 0; !$sock && $i < $this->_connect_attempts; $i++) {
-                       if ($this->_persistant == 1)
-                       {
-                               $sock = @pfsockopen($ip, $port, $errno, $errstr, $timeout);
-                       } else
-                       {
-                               $sock = @fsockopen($ip, $port, $errno, $errstr, $timeout);
+               for( $i = 0; !$sock && $i < $this->_connect_attempts; $i++ ) {
+                       wfSuppressWarnings();
+                       if ( $this->_persistant == 1 ) {
+                               $sock = pfsockopen( $ip, $port, $errno, $errstr, $timeout );
+                       } else {
+                               $sock = fsockopen( $ip, $port, $errno, $errstr, $timeout );
                        }
+                       wfRestoreWarnings();
                }
-               if (!$sock) {
-                       if ($this->_debug)
+               if ( !$sock ) {
+                       if ( $this->_debug ) {
                                $this->_debugprint( "Error connecting to $host: $errstr\n" );
+                       }
                        return false;
                }
 
                // Initialise timeout
-               stream_set_timeout($sock, $this->_timeout_seconds, $this->_timeout_microseconds);
+               stream_set_timeout( $sock, $this->_timeout_seconds, $this->_timeout_microseconds );
 
                return true;
        }
@@ -729,22 +721,21 @@ class MWMemcached
        /**
         * Marks a host as dead until 30-40 seconds in the future
         *
-        * @param   string   $sock    Socket to mark as dead
+        * @param $sock String: socket to mark as dead
         *
         * @access  private
         */
-       function _dead_sock ($sock)
-       {
-               $host = array_search($sock, $this->_cache_sock);
-               $this->_dead_host($host);
+       function _dead_sock( $sock ) {
+               $host = array_search( $sock, $this->_cache_sock );
+               $this->_dead_host( $host );
        }
 
-       function _dead_host ($host)
-       {
-               @list ($ip, /* $port */) = explode(":", $host);
-               $this->_host_dead[$ip] = time() + 30 + intval(rand(0, 10));
+       function _dead_host( $host ) {
+               $parts = explode( ':', $host );
+               $ip = $parts[0];
+               $this->_host_dead[$ip] = time() + 30 + intval( rand( 0, 10 ) );
                $this->_host_dead[$host] = $this->_host_dead[$ip];
-               unset($this->_cache_sock[$host]);
+               unset( $this->_cache_sock[$host] );
        }
 
        // }}}
@@ -753,49 +744,45 @@ class MWMemcached
        /**
         * get_sock
         *
-        * @param   string   $key     Key to retrieve value for;
+        * @param $key String: key to retrieve value for;
         *
-        * @return  mixed    resource on success, false on failure
-        * @access  private
+        * @return Mixed: resource on success, false on failure
+        * @access private
         */
-       function get_sock ($key)
-       {
-               if (!$this->_active)
+       function get_sock( $key ) {
+               if ( !$this->_active ) {
                        return false;
+               }
 
-               if ($this->_single_sock !== null) {
-                       $this->_flush_read_buffer($this->_single_sock);
-                       return $this->sock_to_host($this->_single_sock);
+               if ( $this->_single_sock !== null ) {
+                       $this->_flush_read_buffer( $this->_single_sock );
+                       return $this->sock_to_host( $this->_single_sock );
                }
 
-               $hv = is_array($key) ? intval($key[0]) : $this->_hashfunc($key);
+               $hv = is_array( $key ) ? intval( $key[0] ) : $this->_hashfunc( $key );
 
-               if ($this->_buckets === null)
-               {
-                       foreach ($this->_servers as $v)
-                       {
-                               if (is_array($v))
-                               {
-                                       for ($i=0; $i<$v[1]; $i++)
+               if ( $this->_buckets === null ) {
+                       foreach ( $this->_servers as $v ) {
+                               if ( is_array( $v ) ) {
+                                       for( $i = 0; $i < $v[1]; $i++ ) {
                                                $bu[] = $v[0];
-                               } else
-                               {
+                                       }
+                               } else {
                                        $bu[] = $v;
                                }
                        }
                        $this->_buckets = $bu;
-                       $this->_bucketcount = count($bu);
+                       $this->_bucketcount = count( $bu );
                }
 
-               $realkey = is_array($key) ? $key[1] : $key;
-               for ($tries = 0; $tries<20; $tries++)
-               {
+               $realkey = is_array( $key ) ? $key[1] : $key;
+               for( $tries = 0; $tries < 20; $tries++ ) {
                        $host = $this->_buckets[$hv % $this->_bucketcount];
-                       $sock = $this->sock_to_host($host);
-                       if (is_resource($sock)) {
-                               $this->_flush_read_buffer($sock);
+                       $sock = $this->sock_to_host( $host );
+                       if ( is_resource( $sock ) ) {
+                               $this->_flush_read_buffer( $sock );
                                return $sock;
-                }
+                       }
                        $hv = $this->_hashfunc( $hv . $realkey );
                }
 
@@ -806,19 +793,18 @@ class MWMemcached
        // {{{ _hashfunc()
 
        /**
-        * Creates a hash integer       based on the $key
+        * Creates a hash integer based on the $key
         *
-        * @param   string   $key     Key to hash
+        * @param $key String: key to hash
         *
-        * @return  integer  Hash value
-        * @access  private
+        * @return Integer: hash value
+        * @access private
         */
-       function _hashfunc ($key)
-       {
+       function _hashfunc( $key ) {
                # Hash function must on [0,0x7ffffff]
                # We take the first 31 bits of the MD5 hash, which unlike the hash
                # function used in a previous version of this client, works
-               return hexdec(substr(md5($key),0,8)) & 0x7fffffff;
+               return hexdec( substr( md5( $key ), 0, 8 ) ) & 0x7fffffff;
        }
 
        // }}}
@@ -827,31 +813,38 @@ class MWMemcached
        /**
         * Perform increment/decriment on $key
         *
-        * @param   string   $cmd     Command to perform
-        * @param   string   $key     Key to perform it on
-        * @param   integer  $amt     Amount to adjust
+        * @param $cmd String: command to perform
+        * @param $key String: key to perform it on
+        * @param $amt Integer: amount to adjust
         *
-        * @return  integer     New value of $key
-        * @access  private
+        * @return Integer: new value of $key
+        * @access private
         */
-       function _incrdecr ($cmd, $key, $amt=1)
-       {
-               if (!$this->_active)
+       function _incrdecr( $cmd, $key, $amt = 1 ) {
+               if ( !$this->_active ) {
                        return null;
+               }
 
-               $sock = $this->get_sock($key);
-               if (!is_resource($sock))
+               $sock = $this->get_sock( $key );
+               if ( !is_resource( $sock ) ) {
                        return null;
+               }
 
-               $key = is_array($key) ? $key[1] : $key;
-               @$this->stats[$cmd]++;
-               if (!$this->_safe_fwrite($sock, "$cmd $key $amt\r\n"))
-                       return $this->_dead_sock($sock);
+               $key = is_array( $key ) ? $key[1] : $key;
+               if ( isset( $this->stats[$cmd] ) ) {
+                       $this->stats[$cmd]++;
+               } else {
+                       $this->stats[$cmd] = 1;
+               }
+               if ( !$this->_safe_fwrite( $sock, "$cmd $key $amt\r\n" ) ) {
+                       return $this->_dead_sock( $sock );
+               }
 
-               $line = fgets($sock);
+               $line = fgets( $sock );
                $match = array();
-               if (!preg_match('/^(\d+)/', $line, $match))
+               if ( !preg_match( '/^(\d+)/', $line, $match ) ) {
                        return null;
+               }
                return $match[1];
        }
 
@@ -861,58 +854,59 @@ class MWMemcached
        /**
         * Load items into $ret from $sock
         *
-        * @param   resource $sock    Socket to read from
-        * @param   array    $ret     Returned values
+        * @param $sock Ressource: socket to read from
+        * @param $ret Array: returned values
         *
-        * @access  private
+        * @access private
         */
-       function _load_items ($sock, &$ret)
-       {
-               while (1)
-               {
-                       $decl = fgets($sock);
-                       if ($decl == "END\r\n")
-                       {
+       function _load_items( $sock, &$ret ) {
+               while ( 1 ) {
+                       $decl = fgets( $sock );
+                       if ( $decl == "END\r\n" ) {
                                return true;
-                       } elseif (preg_match('/^VALUE (\S+) (\d+) (\d+)\r\n$/', $decl, $match))
-                       {
-                               list($rkey, $flags, $len) = array($match[1], $match[2], $match[3]);
-                               $bneed = $len+2;
+                       } elseif ( preg_match( '/^VALUE (\S+) (\d+) (\d+)\r\n$/', $decl, $match ) ) {
+                               list( $rkey, $flags, $len ) = array( $match[1], $match[2], $match[3] );
+                               $bneed = $len + 2;
                                $offset = 0;
 
-                               while ($bneed > 0)
-                               {
-                                       $data = fread($sock, $bneed);
-                                       $n = strlen($data);
-                                       if ($n == 0)
+                               while ( $bneed > 0 ) {
+                                       $data = fread( $sock, $bneed );
+                                       $n = strlen( $data );
+                                       if ( $n == 0 ) {
                                                break;
+                                       }
                                        $offset += $n;
                                        $bneed -= $n;
-                                       @$ret[$rkey] .= $data;
+                                       if ( isset( $ret[$rkey] ) ) {
+                                               $ret[$rkey] .= $data;
+                                       } else {
+                                               $ret[$rkey] = $data;
+                                       }
                                }
 
-                               if ($offset != $len+2)
-                               {
+                               if ( $offset != $len + 2 ) {
                                        // Something is borked!
-                                       if ($this->_debug)
-                                               $this->_debugprint(sprintf("Something is borked!  key %s expecting %d got %d length\n", $rkey, $len+2, $offset));
+                                       if ( $this->_debug ) {
+                                               $this->_debugprint( sprintf( "Something is borked!  key %s expecting %d got %d length\n", $rkey, $len + 2, $offset ) );
+                                       }
 
-                                       unset($ret[$rkey]);
-                                       $this->_close_sock($sock);
+                                       unset( $ret[$rkey] );
+                                       $this->_close_sock( $sock );
                                        return false;
                                }
 
-                               if ($this->_have_zlib && $flags & self::COMPRESSED)
-                                       $ret[$rkey] = gzuncompress($ret[$rkey]);
+                               if ( $this->_have_zlib && $flags & self::COMPRESSED ) {
+                                       $ret[$rkey] = gzuncompress( $ret[$rkey] );
+                               }
 
-                               $ret[$rkey] = rtrim($ret[$rkey]);
+                               $ret[$rkey] = rtrim( $ret[$rkey] );
 
-                               if ($flags & self::SERIALIZED)
-                                       $ret[$rkey] = unserialize($ret[$rkey]);
+                               if ( $flags & self::SERIALIZED ) {
+                                       $ret[$rkey] = unserialize( $ret[$rkey] );
+                               }
 
-                       } else
-                       {
-                               $this->_debugprint("Error parsing memcached response\n");
+                       } else {
+                               $this->_debugprint( "Error parsing memcached response\n" );
                                return 0;
                        }
                }
@@ -924,63 +918,73 @@ class MWMemcached
        /**
         * Performs the requested storage operation to the memcache server
         *
-        * @param   string   $cmd     Command to perform
-        * @param   string   $key     Key to act on
-        * @param   mixed    $val     What we need to store
-        * @param   integer  $exp     When it should expire
-        *
-        * @return  boolean
-        * @access  private
+        * @param $cmd String: command to perform
+        * @param $key String: key to act on
+        * @param $val Mixed: what we need to store
+        * @param $exp Integer: (optional) Expiration time. This can be a number of seconds
+        * to cache for (up to 30 days inclusive).  Any timespans of 30 days + 1 second or
+        * longer must be the timestamp of the time at which the mapping should expire. It
+        * is safe to use timestamps in all cases, regardless of exipration
+        * eg: strtotime("+3 hour")
+        *
+        * @return Boolean
+        * @access private
         */
-       function _set ($cmd, $key, $val, $exp)
-       {
-               if (!$this->_active)
+       function _set( $cmd, $key, $val, $exp ) {
+               if ( !$this->_active ) {
                        return false;
+               }
 
-               $sock = $this->get_sock($key);
-               if (!is_resource($sock))
+               $sock = $this->get_sock( $key );
+               if ( !is_resource( $sock ) ) {
                        return false;
+               }
 
-               @$this->stats[$cmd]++;
+               if ( isset( $this->stats[$cmd] ) ) {
+                       $this->stats[$cmd]++;
+               } else {
+                       $this->stats[$cmd] = 1;
+               }
 
                $flags = 0;
 
-               if (!is_scalar($val))
-               {
-                       $val = serialize($val);
+               if ( !is_scalar( $val ) ) {
+                       $val = serialize( $val );
                        $flags |= self::SERIALIZED;
-                       if ($this->_debug)
-                               $this->_debugprint(sprintf("client: serializing data as it is not scalar\n"));
+                       if ( $this->_debug ) {
+                               $this->_debugprint( sprintf( "client: serializing data as it is not scalar\n" ) );
+                       }
                }
 
-               $len = strlen($val);
+               $len = strlen( $val );
 
-               if ($this->_have_zlib && $this->_compress_enable &&
-                        $this->_compress_threshold && $len >= $this->_compress_threshold)
+               if ( $this->_have_zlib && $this->_compress_enable &&
+                        $this->_compress_threshold && $len >= $this->_compress_threshold )
                {
-                       $c_val = gzcompress($val, 9);
-                       $c_len = strlen($c_val);
+                       $c_val = gzcompress( $val, 9 );
+                       $c_len = strlen( $c_val );
 
-                       if ($c_len < $len*(1 - self::COMPRESSION_SAVINGS))
-                       {
-                               if ($this->_debug)
-                                       $this->_debugprint(sprintf("client: compressing data; was %d bytes is now %d bytes\n", $len, $c_len));
+                       if ( $c_len < $len * ( 1 - self::COMPRESSION_SAVINGS ) ) {
+                               if ( $this->_debug ) {
+                                       $this->_debugprint( sprintf( "client: compressing data; was %d bytes is now %d bytes\n", $len, $c_len ) );
+                               }
                                $val = $c_val;
                                $len = $c_len;
                                $flags |= self::COMPRESSED;
                        }
                }
-               if (!$this->_safe_fwrite($sock, "$cmd $key $flags $exp $len\r\n$val\r\n"))
-                       return $this->_dead_sock($sock);
+               if ( !$this->_safe_fwrite( $sock, "$cmd $key $flags $exp $len\r\n$val\r\n" ) ) {
+                       return $this->_dead_sock( $sock );
+               }
 
-               $line = trim(fgets($sock));
+               $line = trim( fgets( $sock ) );
 
-               if ($this->_debug)
-               {
-                       $this->_debugprint(sprintf("%s %s (%s)\n", $cmd, $key, $line));
+               if ( $this->_debug ) {
+                       $this->_debugprint( sprintf( "%s %s (%s)\n", $cmd, $key, $line ) );
                }
-               if ($line == "STORED")
+               if ( $line == "STORED" ) {
                        return true;
+               }
                return false;
        }
 
@@ -990,59 +994,62 @@ class MWMemcached
        /**
         * Returns the socket for the host
         *
-        * @param   string   $host    Host:IP to get socket for
+        * @param $host String: Host:IP to get socket for
         *
-        * @return  mixed    IO Stream or false
-        * @access  private
+        * @return Mixed: IO Stream or false
+        * @access private
         */
-       function sock_to_host ($host)
-       {
-               if (isset($this->_cache_sock[$host]))
+       function sock_to_host( $host ) {
+               if ( isset( $this->_cache_sock[$host] ) ) {
                        return $this->_cache_sock[$host];
+               }
 
                $sock = null;
                $now = time();
-               list ($ip, /* $port */) = explode (":", $host);
-               if (isset($this->_host_dead[$host]) && $this->_host_dead[$host] > $now ||
-                       isset($this->_host_dead[$ip]) && $this->_host_dead[$ip] > $now)
+               list( $ip, /* $port */) = explode( ':', $host );
+               if ( isset( $this->_host_dead[$host] ) && $this->_host_dead[$host] > $now ||
+                       isset( $this->_host_dead[$ip] ) && $this->_host_dead[$ip] > $now
+               ) {
                        return null;
+               }
 
-               if (!$this->_connect_sock($sock, $host))
-                       return $this->_dead_host($host);
+               if ( !$this->_connect_sock( $sock, $host ) ) {
+                       return $this->_dead_host( $host );
+               }
 
                // Do not buffer writes
-               stream_set_write_buffer($sock, 0);
+               stream_set_write_buffer( $sock, 0 );
 
                $this->_cache_sock[$host] = $sock;
 
                return $this->_cache_sock[$host];
        }
 
-       function _debugprint($str){
-               print($str);
+       function _debugprint( $str ) {
+               print( $str );
        }
 
        /**
         * Write to a stream, timing out after the correct amount of time
         *
-        * @return bool false on failure, true on success
+        * @return Boolean: false on failure, true on success
         */
        /*
-       function _safe_fwrite($f, $buf, $len = false) {
-               stream_set_blocking($f, 0);
+       function _safe_fwrite( $f, $buf, $len = false ) {
+               stream_set_blocking( $f, 0 );
 
-               if ($len === false) {
-                       wfDebug("Writing " . strlen( $buf ) . " bytes\n");
-                       $bytesWritten = fwrite($f, $buf);
+               if ( $len === false ) {
+                       wfDebug( "Writing " . strlen( $buf ) . " bytes\n" );
+                       $bytesWritten = fwrite( $f, $buf );
                } else {
-                       wfDebug("Writing $len bytes\n");
-                       $bytesWritten = fwrite($f, $buf, $len);
+                       wfDebug( "Writing $len bytes\n" );
+                       $bytesWritten = fwrite( $f, $buf, $len );
                }
-               $n = stream_select($r=NULL, $w = array($f), $e = NULL, 10, 0);
-               #   $this->_timeout_seconds, $this->_timeout_microseconds);
+               $n = stream_select( $r = null, $w = array( $f ), $e = null, 10, 0 );
+               #   $this->_timeout_seconds, $this->_timeout_microseconds );
 
-               wfDebug("stream_select returned $n\n");
-               stream_set_blocking($f, 1);
+               wfDebug( "stream_select returned $n\n" );
+               stream_set_blocking( $f, 1 );
                return $n == 1;
                return $bytesWritten;
        }*/
@@ -1050,11 +1057,11 @@ class MWMemcached
        /**
         * Original behaviour
         */
-       function _safe_fwrite($f, $buf, $len = false) {
-               if ($len === false) {
-                       $bytesWritten = fwrite($f, $buf);
+       function _safe_fwrite( $f, $buf, $len = false ) {
+               if ( $len === false ) {
+                       $bytesWritten = fwrite( $f, $buf );
                } else {
-                       $bytesWritten = fwrite($f, $buf, $len);
+                       $bytesWritten = fwrite( $f, $buf, $len );
                }
                return $bytesWritten;
        }
@@ -1062,14 +1069,14 @@ class MWMemcached
        /**
         * Flush the read buffer of a stream
         */
-       function _flush_read_buffer($f) {
-               if (!is_resource($f)) {
+       function _flush_read_buffer( $f ) {
+               if ( !is_resource( $f ) ) {
                        return;
                }
-               $n = stream_select($r=array($f), $w = null, $e = null, 0, 0);
-               while ($n == 1 && !feof($f)) {
-                       fread($f, 1024);
-                       $n = stream_select($r=array($f), $w = null, $e = null, 0, 0);
+               $n = stream_select( $r = array( $f ), $w = null, $e = null, 0, 0 );
+               while ( $n == 1 && !feof( $f ) ) {
+                       fread( $f, 1024 );
+                       $n = stream_select( $r = array( $f ), $w = null, $e = null, 0, 0 );
                }
        }