• php没有开启Memcache扩展类时


    模拟PHP Memcache 类。
    当服务器没有开启Memcache扩展的时候。可以采用本类
    使用方法
    class_exists('Memcache') or include './Memcache.class.php';
    $mem = new Memcache;
    $mem->add('key','value');
    $mem->get('key')


    目前已实现方法
    Memcache::connect ( string $host [, int $port ] )
    Memcache::get( string $key )
    Memcache::add( string $key , mixed $var [, int $expire] )
    Memcache::set( string $key , mixed $var [, int $expire] )
    Memcache::replace( string $key , mixed $var [, int $expire] )
    Memcache::getVersion( void )
    Memcache::flush ( void )
    Memcache::delete( string $key )
    Memcache::close( void )

    属性
    Memcache::info 服务器相关信息 返回数组

    注意 2014年3月28日
    本类需要sockets支持
    本类的 指定Memcache下标长度超出32字节。自动对key进行MD5

    @Version Memcache.class.php 1.1 2014-3-29 04:10:18 $
      bug 修复
      1. 修复必须需要sockets扩展才能使用的缺陷
      2. 代码优化
      3. 添加手动关闭 连接方法

    /**
     * Created by Iyoule .
     * 模拟PHP Memcache 类。
     *  当服务器没有开启Memcache扩展的时候。可以采用本类
     *  使用方法
     *            class_exists('Memcache') or include './Memcache.class.php';
     *            $mem = new Memcache;
     *            $mem->add('key','value');
     *            $mem->get('key')
     *  目前已实现方法
     *            Memcache::connect ( string $host [, int $port ] )
     *            Memcache::get( string $key )
     *            Memcache::add( string $key , mixed $var [, int $expire] )
     *            Memcache::set( string $key , mixed $var [, int $expire] )
     *            Memcache::replace( string $key , mixed $var [, int $expire] )
     *            Memcache::getVersion( void )
     *            Memcache::flush ( void )
     *            Memcache::delete( string $key )
     *            Memcache::close( void )           2014-3-29 02:13:19
     *
     * 属性
     *            Memcache::info 服务器相关信息 返回数组
     *
     *  注意
     *      本类需要sockets支持
     *      本类的 指定Memcache下标长度超出32字节。自动对key进行MD5
     *
     * @Version Memcache.class.php 1.1 2014-3-29 04:10:18  $
     *            bug 修复
     *            1. 修复必须需要sockets扩展才能使用的缺陷
     *            2. 代码优化
     *            3. 添加手动关闭 连接方法
     *
     * Version: Memcache.class.php 1.1 $
     * Time: 2014-3-28 上午12:04
     */
    class Memcache
    {
        /**
         * @var 服务器地址
         */
        public $host;
    
        /**
         * @var 服务器端口
         */
        public $port;
    
        /**
         * @var array memcache 服务信息
         */
        private $info = array();
    
        /**
         * @var null socket资源
         */
        private $socket = null;
    
        /**
         * @var memcache 命令
         */
        private $command;
    
        /**
         * @var int 连接超时时间
         */
        private $connect_timeout = 30;
        private $errno;
        private $errstr;
    
        /**
         * @var mamcache保存数据时长
         */
        private $expire;
    
        /**
         * @var memcache 保存数据的key 长于32位置将被MD5
         */
        private $key;
    
        /**
         * @var memcache 保存的值
         */
        private $var;
    
        /**
         * @var bool 主机是否关闭连接
         */
        private $is_close = false;
    
        /**
         * @var string 连接函数
         */
        private $connect_method;
    
        /**
         * 构造方法 判断 根据系统自动判断连接类型
         *  优先级
         *   优先 -> 低
         *  stream_socket_client -> fsockopen -> pfsockopen -> socket_create
         */
        public function __construct()
        {
            if (function_exists('stream_socket_client')) {
                $this->connect_method = 'stream_socket_client';
            } elseif (function_exists('fsockopen')) {
                $this->connect_method = 'fsockopen';
            } elseif (function_exists('pfsockopen')) {
                $this->connect_method = 'pfsockopen';
            } elseif (function_exists('socket_create')) {
                $this->connect_method = 'socket_create';
            }
        }
    
        /**
         * 从服务端检回一个元素
         * 如果服务端之前有以key作为key存储的元素, Memcache::get()方法此时返回之前存储的值。
         * 你可以给 Memcache::get()方法传递一个数组(多个key)来获取一个数组的元素值,返回的数组仅仅包含从 服务端查找到的key-value对。
         * @param $key 要获取值的key或key数组。
         * @return bool|string 返回key对应的存储元素的字符串值或者在失败或key未找到的时候返回FALSE。
         * @lastTime 2014-3-28 02:44:00
         */
        public function get($key)
        {
            $this->key = isset($key{32}) ? md5($key) : $key;
            $command = "get $key
    ";
            $this->socket_write($command);
            do {
                $out = $this->socket_read(128);
            } while (strlen($out) == 1);
            $list = preg_split("/s/", $out);
            if ($list[0] == 'END') return false;
            $string = array();
            $runing = 0;
            do {
                $string[$runing] = $this->socket_read(128);
                substr($string[$runing], 0, 3) == 'END' && strlen($string[$runing]) <= 5 ? $runing = false : $runing++;
            } while ($runing !== false);
            array_pop($string);
            $string = join('', $string);
            $indexOf = 0;
            if ($this->connect_method == 'socket_create') {
                $indexOf = 1;
            }
            $string = substr($string, $indexOf, -2);
            return $string;
        }
    
        /**
         * 建立连接
         * @param $host memcache 服务器地址
         * @param int $post 端口
         * @lastTime 2014-3-28 02:40:09
         */
        public function connect($host, $post = 11211)
        {
            $this->host = $host;
            $this->port = $post;
            $this->create_socket();
            $this->info();
        }
    
        /**
         * 魔法方法 构造 add set replace方法
         * @param $method
         * @param $args
         * @return mixed
         * @lastTime 2014-3-28 02:40:28
         */
        public function __call($method, $args)
        {
            if (in_array($method, array('add', 'set', 'replace', 'delete'))) {
                array_unshift($args, $method);
                return call_user_func_array(array($this, 'set__'), $args);
            }
        }
    
        /**
         * 魔法方法
         * @param $name
         * @return array
         * @lastTime 2014-3-29 04:17:17
         */
        public function __get($name)
        {
            if($name=='info')
                return $this->info;
        }
    
        /**
         * 针对 魔法方法 add set replace方法进行的处理
         * @param $func 方法名字
         * @param $key memcache的key下标
         * @param $var 设置的值
         * @param int $expire memcache对数据的保存时间 默认24小时
         * @return bool
         * @lastTime 时间
         */
        private function set__($func, $key, $var = null, $expire = 86400)
        {
            if ($this->is_close)
                return false;
            $this->command = trim($func);
            $this->key = isset($key{32}) ? md5($key) : $key;
            if ($func != 'delete') {
                $this->var = trim($var);
                $this->expire = trim($expire);
            }
            return $this->send_do();
        }
    
        /**
         * 清空memcache的值
         * @return bool
         * @lastTime 2014-3-28 02:43:23
         */
        public function flush()
        {
            $command = "flush_all
    ";
            $this->socket_write($command);
            if ($this->socket_read(3) == 'OK') {
                return true;
            }
            return false;
        }
    
        /**
         * Memcache::getVersion — 返回服务器版本信息
         * Memcache::getVersion()返回一个字符串表示的服务端版本号
         * 同样你也可以使用 Memcache::info['version']。
         * @return mixed
         * @lastTime 2014-3-28 02:44:56
         */
        public function getVersion()
        {
            return $this->info['version'];
        }
    
        /**
         * 对 add set   replace delete 方法进行的处理
         * @return bool
         * @lastTime 2014-3-28 02:45:55
         */
        private function send_do()
        {
            if ($this->command != 'delete') {
                $command = sprintf("%s %s 0 %d %d
    ", $this->command, $this->key, $this->expire, strlen($this->var));
                $var = sprintf("%s
    ", $this->var);
                $this->socket_write($command);
                $this->socket_write($var);
            } else {
                $command = sprintf("%s %s
    ", $this->command, $this->key);
                $this->socket_write($command);
            }
            do {
                $result = $this->socket_read(64);
            } while (strlen($result) == 1);
            $result = str_replace(array("
    ", "
    "), '', $result);
            if (substr($result, 0, 5) == 'STORE' || substr($result, 0, 6) == 'DELETE') {
                return true;
            }
            return false;
        }
    
        /**
         * 创建连接类型
         * @return bool
         * @lastTime 2014-3-29 04:06:15
         */
        private function create_socket()
        {
            $method = $this->connect_method;
            if ($method) {
                switch ($method) {
                    case 'socket_create':
                        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
                        socket_connect($this->socket, $this->host, $this->port);
                        break;
                    case 'fsockopen':
                    case 'pfsockopen':
                        $this->socket = $method($this->host, $this->port, $this->errno, $this->errstr, $this->connect_timeout);
                        break;
                    case 'stream_socket_client':
                        $address = sprintf("tcp://%s:%d", $this->host, $this->port);
                        $this->socket = $method($address, $this->errno, $this->errstr, $this->connect_timeout);
                        break;
                }
            }
            if (is_resource($this->socket))
                return true;
        }
    
        /**
         * 写入套字节
         * @param $string
         * @return int
         * @lastTime 2014-3-28 02:46:40
         */
        private function socket_write($string)
        {
            $return = false;
            if ($this->connect_method == 'socket_create')
                $return = socket_write($this->socket, $string, strlen($string));
            else if ($this->connect_method)
                $return = fwrite($this->socket, $string);
            return $return;
        }
    
        /**
         * 读取套字节
         * @param $len 取出的长度
         * @return string
         * @lastTime 2014-3-28 02:47:08
         */
        private function socket_read($len)
        {
            $return = null;
            if ($this->connect_method == 'socket_create')
                $return = socket_read($this->socket, $len, PHP_NORMAL_READ);
            else if ($this->connect_method)
                $return = fgets($this->socket, $len);
            return $return;
        }
    
        /**
         * 服务器的信息处理
         * @return array
         * @lastTime 2014-3-28 02:47:46
         */
        private function info()
        {
            if (!empty($this->info))
                return $this->info;
            $this->socket_write("stats
    ");
            $string = array();
            if ($this->connect_method) {
                $runing = 0;
                do {
                    $string[$runing] = $this->socket_read(68);
                    substr($string[$runing], 0, 3) == 'END' ? $runing = false : $runing++;
                } while ($runing !== false);
                $string = join("
    ", $string);
                $string = explode("
    ", $string);
                $string = array_filter($string, function ($value) {
                    return isset($value{4});
                });
                $string = array_map(function ($value) {
                    return explode(" ", $value);
                }, $string);
                foreach ($string as $val) {
                    $this->info[$val[1]] = $val[2];
                }
                return $this->info;
            }
        }
    
        /**
         * memcache 关闭连接
         * @return bool
         * @lastTime 2014-3-29 01:11:23
         */
        public function close()
        {
            $this->is_close = true;
            return !!$this->socket_write("quit
    ");
        }
    
        /**
         * 析构函数 关闭套字节
         */
        public function __destruct()
        {
            if (is_resource($this->socket) && $this->connect_method == 'socket_create')
                socket_close($this->socket);
            else if ($this->connect_method)
                fclose($this->socket);
        }
    
    }

     类二:
    memcached-client.php

    <?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$
    //
    
    /**
     * This is the PHP client for memcached - a distributed memory cache daemon.
     * More information is available at http://www.danga.com/memcached/
     *
     * Usage example:
     *
     * require_once 'memcached.php';
     * 
     * $mc = new memcached(array(
     *              'servers' => array('127.0.0.1:10000', 
     *                                 array('192.0.0.1:10010', 2),
     *                                 '127.0.0.1:10020'),
     *              'debug'   => false,
     *              'compress_threshold' => 10240,
     *              'persistant' => true));
     *
     * $mc->add('key', array('some', 'array'));
     * $mc->replace('key', 'some random string');
     * $val = $mc->get('key');
     *
     * @author  Ryan T. Dean <rtdean@cytherianage.net>
     * @package memcached-client
     * @version 0.1.2
     */
    
    // {{{ requirements
    // }}}
    
    // {{{ constants
    // {{{ flags
    
    /**
     * Flag: indicates data is serialized
     */
    define("MEMCACHE_SERIALIZED", 1<<0);
    
    /**
     * Flag: indicates data is compressed
     */
    define("MEMCACHE_COMPRESSED", 1<<1);
    
    // }}}
    
    /**
     * Minimum savings to store data compressed
     */
    define("COMPRESSION_SAVINGS", 0.20);
    
    // }}}
    
    // {{{ class memcached
    /**
     * memcached client class implemented using (p)fsockopen()
     *
     * @author  Ryan T. Dean <rtdean@cytherianage.net>
     * @package memcached-client
     */
    class memcached
    {
       // {{{ properties
       // {{{ public
    
       /**
        * Command statistics
        *
        * @var     array
        * @access  public
        */
       var $stats;
       
       // }}}
       // {{{ private
    
       /**
        * Cached Sockets that are connected
        *
        * @var     array
        * @access  private
        */
       var $_cache_sock;
       
       /**
        * Current debug status; 0 - none to 9 - profiling
        *
        * @var     boolean
        * @access  private
        */
       var $_debug;
       
       /**
        * Dead hosts, assoc array, 'host'=>'unixtime when ok to check again'
        *
        * @var     array
        * @access  private
        */
       var $_host_dead;
       
       /**
        * Is compression available?
        *
        * @var     boolean
        * @access  private
        */
       var $_have_zlib;
       
       /**
        * Do we want to use compression?
        *
        * @var     boolean
        * @access  private
        */
       var $_compress_enable;
       
       /**
        * At how many bytes should we compress?
        *
        * @var     interger
        * @access  private
        */
       var $_compress_threshold;
       
       /**
        * Are we using persistant links?
        *
        * @var     boolean
        * @access  private
        */
       var $_persistant;
       
       /**
        * If only using one server; contains ip:port to connect to
        *
        * @var     string
        * @access  private
        */
       var $_single_sock;
       
       /**
        * Array containing ip:port or array(ip:port, weight)
        *
        * @var     array
        * @access  private
        */
       var $_servers;
       
       /**
        * Our bit buckets
        *
        * @var     array
        * @access  private
        */
       var $_buckets;
       
       /**
        * Total # of bit buckets we have
        *
        * @var     interger
        * @access  private
        */
       var $_bucketcount;
       
       /**
        * # of total servers we have
        *
        * @var     interger
        * @access  private
        */
       var $_active;
    
       // }}}
       // }}}
       // {{{ methods
       // {{{ public functions
       // {{{ memcached()
    
       /**
        * Memcache initializer
        *
        * @param   array    $args    Associative array of settings
        *
        * @return  mixed
        * @access  public
        */
       function memcached ($args)
       {
          $this->set_servers($args['servers']);
          $this->_debug = $args['debug'];
          $this->stats = array();
          $this->_compress_threshold = $args['compress_threshold'];
          $this->_persistant = isset($args['persistant']) ? $args['persistant'] : false;
          $this->_compress_enable = true;
          $this->_have_zlib = function_exists("gzcompress");
          
          $this->_cache_sock = array();
          $this->_host_dead = array();
       }
    
       // }}}
       // {{{ add()
    
       /**
        * 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   interger $exp     (optional) Time to expire data at
        *
        * @return  boolean
        * @access  public
        */
       function add ($key, $val, $exp = 0)
       {
          return $this->_set('add', $key, $val, $exp);
       }
    
       // }}}
       // {{{ decr()
    
       /**
        * Decriment a value stored on the memcache server
        *
        * @param   string   $key     Key to decriment
        * @param   interger $amt     (optional) Amount to decriment
        *
        * @return  mixed    FALSE on failure, value on success
        * @access  public
        */
       function decr ($key, $amt=1)
       {
          return $this->_incrdecr('decr', $key, $amt);
       }
    
       // }}}
       // {{{ delete()
    
       /**
        * Deletes a key from the server, optionally after $time
        *
        * @param   string   $key     Key to delete
        * @param   interger $time    (optional) How long to wait before deleting
        *
        * @return  boolean  TRUE on success, FALSE on failure
        * @access  public
        */
       function delete ($key, $time = 0)
       {
          if (!$this->_active)
             return false;
             
          $sock = $this->get_sock($key);
          if (!is_resource($sock))
             return false;
          
          $key = is_array($key) ? $key[1] : $key;
          
          $this->stats['delete']++;
          $cmd = "delete $key $time
    ";
          if(!fwrite($sock, $cmd, strlen($cmd)))
          {
             $this->_dead_sock($sock);
             return false;
          }
          $res = trim(fgets($sock));
          
          if ($this->_debug)
             printf("MemCache: delete %s (%s)
    ", $key, $res);
          
          if ($res == "DELETED")
             return true;
          return false;
       }
    
       // }}}
       // {{{ disconnect_all()
    
       /**
        * Disconnects all connected sockets
        *
        * @access  public
        */
       function disconnect_all ()
       {
          foreach ($this->_cache_sock as $sock)
             fclose($sock);
    
          $this->_cache_sock = array();
       }
    
       // }}}
       // {{{ enable_compress()
    
       /**
        * Enable / Disable compression
        *
        * @param   boolean  $enable  TRUE to enable, FALSE to disable
        *
        * @access  public
        */
       function enable_compress ($enable)
       {
          $this->_compress_enable = $enable;
       }
    
       // }}}
       // {{{ forget_dead_hosts()
    
       /**
        * Forget about all of the dead hosts
        *
        * @access  public
        */
       function forget_dead_hosts ()
       {
          $this->_host_dead = array();
       }
    
       // }}}
       // {{{ get()
    
       /**
        * Retrieves the value associated with the key from the memcache server
        *
        * @param  string   $key     Key to retrieve
        *
        * @return  mixed
        * @access  public
        */
       function get ($key)
       {
          if (!$this->_active)
             return false;
             
          $sock = $this->get_sock($key);
          
          if (!is_resource($sock))
             return false;
             
          $this->stats['get']++;
          
          $cmd = "get $key
    ";
          if (!fwrite($sock, $cmd, strlen($cmd)))
          {
             $this->_dead_sock($sock);
             return false;
          }
          
          $val = array();
          $this->_load_items($sock, $val);
          
          if ($this->_debug)
             foreach ($val as $k => $v)
                printf("MemCache: sock %s got %s => %s
    ", $sock, $k, $v);
          
          return $val[$key];
       }
    
       // }}}
       // {{{ get_multi()
    
       /**
        * Get multiple keys from the server(s)
        *
        * @param   array    $keys    Keys to retrieve
        *
        * @return  array
        * @access  public
        *  get('key1')   keys=array('key1','key2');
        */
       function get_multi ($keys)
       {
          if (!$this->_active)
             return false;
             
          $this->stats['get_multi']++;
          
          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;
             }
             $sock_keys[$sock][] = $key;
          }
          
          // Send out the requests
          foreach ($socks as $sock)
          {
             $cmd = "get";
             foreach ($sock_keys[$sock] as $key)
             {
                $cmd .= " ". $key;
             }
             $cmd .= "
    ";
             
             if (fwrite($sock, $cmd, strlen($cmd)))
             {
                $gather[] = $sock;
             } else
             {
                $this->_dead_sock($sock);
             }
          }
          
          // Parse responses
          $val = array();
          foreach ($gather as $sock)
          {
             $this->_load_items($sock, $val);
          }
          
          if ($this->_debug)
             foreach ($val as $k => $v)
                printf("MemCache: got %s => %s
    ", $k, $v);
                
          return $val;
       }
    
       // }}}
       // {{{ incr()
    
       /**
        * Increments $key (optionally) by $amt
        *
        * @param   string   $key     Key to increment
        * @param   interger $amt     (optional) amount to increment
        *
        * @return  interger New key value?
        * @access  public
        */
       function incr ($key, $amt=1)
       {
          return $this->_incrdecr('incr', $key, $amt);
       }
    
       // }}}
       // {{{ replace()
    
       /**
        * 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   interger $exp     (optional) Experiation time
        *
        * @return  boolean
        * @access  public
        */
       function replace ($key, $value, $exp=0)
       {
          return $this->_set('replace', $key, $value, $exp);
       }
    
       // }}}
       // {{{ run_command()
    
       /**
        * Passes through $cmd to the memcache server connected by $sock; returns 
        * output as an array (null array if no output)
        *
        * NOTE: due to a possible bug in how PHP reads while using fgets(), each
        *       line may not be terminated by a 
    .  More specifically, my testing
        *       has shown that, on FreeBSD at least, each line is terminated only
        *       with a 
    .  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
        *
        * @return  array    Output array
        * @access  public
        */
       function run_command ($sock, $cmd)
       {
          if (!is_resource($sock))
             return array();
          
          if (!fwrite($sock, $cmd, strlen($cmd)))
             return array();
             
          while (true)
          {
             $res = fgets($sock);
             $ret[] = $res;
             if (preg_match('/^END/', $res))
                break;
             if (strlen($res) == 0)
                break;
          }
          return $ret;
       }
    
       // }}}
       // {{{ set()
    
       /**
        * 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   interger $exp     (optional) Experiation time
        *
        * @return  boolean  TRUE on success
        * @access  public
        */
       function set ($key, $value, $exp=0)
       {
          return $this->_set('set', $key, $value, $exp);
       }
    
       // }}}
       // {{{ set_compress_threshold()
    
       /**
        * Sets the compression threshold
        *
        * @param   interger $thresh  Threshold to compress if larger than
        *
        * @access  public
        */
       function set_compress_threshold ($thresh)
       {
          $this->_compress_threshold = $thresh;
       }
    
       // }}}
       // {{{ set_debug()
    
       /**
        * Sets the debug flag
        *
        * @param   boolean  $dbg     TRUE for debugging, FALSE otherwise
        *
        * @access  public
        *
        * @see     memcahced::memcached
        */
       function set_debug ($dbg)
       {
          $this->_debug = $dbg;
       }
    
       // }}}
       // {{{ set_servers()
    
       /**
        * Sets the server list to distribute key gets and puts between
        *
        * @param   array    $list    Array of servers to connect to
        *
        * @access  public
        *
        * @see     memcached::memcached()
        */
       function set_servers ($list)
       {
          $this->_servers = $list;
          $this->_active = count($list);
          $this->_buckets = null;
          $this->_bucketcount = 0;
          
          $this->_single_sock = null;
          if ($this->_active == 1)
             $this->_single_sock = $this->_servers[0];
       }
    
       // }}}
       // }}}
       // {{{ private methods
       // {{{ _close_sock()
    
       /**
        * Close the specified socket
        *
        * @param   string   $sock    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]);
       }
    
       // }}}
       // {{{ _connect_sock()
    
       /**
        * Connects $sock to $host, timing out after $timeout
        *
        * @param   interger $sock    Socket to connect
        * @param   string   $host    Host:IP to connect to
        * @param   float    $timeout (optional) Timeout value, defaults to 0.25s
        *
        * @return  boolean
        * @access  private
        */
       function _connect_sock (&$sock, $host, $timeout = 0.25)
       {
          list ($ip, $port) = explode(":", $host);
          if ($this->_persistant == 1)
          {
             $sock = @pfsockopen($ip, $port, $errno, $errstr, $timeout);
          } else
          {
             $sock = @fsockopen($ip, $port, $errno, $errstr, $timeout);
          }
          
          if (!$sock)
             return false;
          return true;
       }
    
       // }}}
       // {{{ _dead_sock()
    
       /**
        * Marks a host as dead until 30-40 seconds in the future
        *
        * @param   string   $sock    Socket to mark as dead
        *
        * @access  private
        */
       function _dead_sock ($sock)
       {
          $host = array_search($sock, $this->_cache_sock);
          list ($ip, $port) = explode(":", $host);
          $this->_host_dead[$ip] = time() + 30 + intval(rand(0, 10));
          $this->_host_dead[$host] = $this->_host_dead[$ip];
          unset($this->_cache_sock[$host]);
       }
    
       // }}}
       // {{{ get_sock()
    
       /**
        * get_sock
        *
        * @param   string   $key     Key to retrieve value for;
        *
        * @return  mixed    resource on success, false on failure
        * @access  private
        */
       function get_sock ($key)
       {
          if (!$this->_active)
             return false;
    
          if ($this->_single_sock !== null)
             return $this->sock_to_host($this->_single_sock);
          
          $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++)
                      $bu[] = $v[0];
                } else
                {
                   $bu[] = $v;
                }
             }
             $this->_buckets = $bu;
             $this->_bucketcount = count($bu);
          }
          
          $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))
                return $sock;
             $hv += $this->_hashfunc($tries . $realkey);
          }
          
          return false;
       }
    
       // }}}
       // {{{ _hashfunc()
    
       /**
        * Creates a hash interger based on the $key
        *
        * @param   string   $key     Key to hash
        *
        * @return  interger Hash value
        * @access  private
        */
       function _hashfunc ($key)
       {
          $hash = 0;
          for ($i=0; $i<strlen($key); $i++)
          {
             $hash = $hash*33 + ord($key[$i]);
          }
          
          return $hash;
       }
    
       // }}}
       // {{{ _incrdecr()
    
       /**
        * Perform increment/decriment on $key
        *
        * @param   string   $cmd     Command to perform
        * @param   string   $key     Key to perform it on
        * @param   interger $amt     Amount to adjust
        *
        * @return  interger    New value of $key
        * @access  private
        */
       function _incrdecr ($cmd, $key, $amt=1)
       {
          if (!$this->_active)
             return null;
             
          $sock = $this->get_sock($key);
          if (!is_resource($sock))
             return null;
             
          $key = is_array($key) ? $key[1] : $key;
          $this->stats[$cmd]++;
          if (!fwrite($sock, "$cmd $key $amt
    "))
             return $this->_dead_sock($sock);
             
          stream_set_timeout($sock, 1, 0);
          $line = fgets($sock);
          if (!preg_match('/^(d+)/', $line, $match))
             return null;
          return $match[1];
       }
    
       // }}}
       // {{{ _load_items()
    
       /**
        * Load items into $ret from $sock
        *
        * @param   resource $sock    Socket to read from
        * @param   array    $ret     Returned values
        *
        * @access  private
        */
       function _load_items ($sock, &$ret)
       {
          while (1)
          {
             $decl = fgets($sock);
             if ($decl == "END
    ")
             {
                return true;
             } elseif (preg_match('/^VALUE (S+) (d+) (d+)
    $/', $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)
                      break;
                   $offset += $n;
                   $bneed -= $n;
                   $ret[$rkey] .= $data;
                }
                
                if ($offset != $len+2)
                {
                   // Something is borked!
                   if ($this->_debug)
                      printf("Something is borked!  key %s expecting %d got %d length
    ", $rkey, $len+2, $offset);
    
                   unset($ret[$rkey]);
                   $this->_close_sock($sock);
                   return false;
                }
                
                $ret[$rkey] = rtrim($ret[$rkey]);
    
                if ($this->_have_zlib && $flags & MEMCACHE_COMPRESSED)
                   $ret[$rkey] = gzuncompress($ret[$rkey]);
    
                if ($flags & MEMCACHE_SERIALIZED)
                   $ret[$rkey] = unserialize($ret[$rkey]);
    
             } else 
             {
                if ($this->_debug)
                   print("Error parsing memcached response
    ");
                return 0;
             }
          }
       }
    
       // }}}
       // {{{ _set()
    
       /**
        * 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   interger $exp     When it should expire
        *
        * @return  boolean
        * @access  private
        */
       function _set ($cmd, $key, $val, $exp)
       {
          if (!$this->_active)
             return false;
             //get_sock就是去获取到memcached服务器连接
          $sock = $this->get_sock($key);
          if (!is_resource($sock))
             return false;
             
          $this->stats[$cmd]++;
          
          $flags = 0;
          
          if (!is_scalar($val))
          {
             $val = serialize($val);
             $flags |= MEMCACHE_SERIALIZED;
             if ($this->_debug)
                printf("client: serializing data as it is not scalar
    ");
          }
          
          $len = strlen($val);
          
          if ($this->_have_zlib && $this->_compress_enable && 
              $this->_compress_threshold && $len >= $this->_compress_threshold)
          {
             $c_val = gzcompress($val, 9);
             $c_len = strlen($c_val);
             
             if ($c_len < $len*(1 - COMPRESS_SAVINGS))
             {
                if ($this->_debug)
                   printf("client: compressing data; was %d bytes is now %d bytes
    ", $len, $c_len);
                $val = $c_val;
                $len = $c_len;
                $flags |= MEMCACHE_COMPRESSED;
             }
          }
          if (!fwrite($sock, "$cmd $key $flags $exp $len
    $val
    "))
             return $this->_dead_sock($sock);
             
          $line = trim(fgets($sock));
          
          if ($this->_debug)
          {
             if ($flags & MEMCACHE_COMPRESSED)
                $val = 'compressed data';
             printf("MemCache: %s %s => %s (%s)
    ", $cmd, $key, $val, $line);
          }
          if ($line == "STORED")
             return true;
          return false;
       }
    
       // }}}
       // {{{ sock_to_host()
    
    
       /**
        * Returns the socket for the host
        *
        * @param   string   $host    Host:IP to get socket for
        *
        * @return  mixed    IO Stream or false
        * @access  private
        */
       function sock_to_host ($host)
    
       {
         
          if (isset($this->_cache_sock[$host]))
             return $this->_cache_sock[$host];
          
          $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)
             return null;
             
          if (!$this->_connect_sock($sock, $host))
             return $this->_dead_sock($host);
             
          // Do not buffer writes
          stream_set_write_buffer($sock, 0);
          
          $this->_cache_sock[$host] = $sock;
          
          return $this->_cache_sock[$host];
       }
    
       // }}}
       // }}}
       // }}}
    }
    
    // }}}
    ?> 
  • 相关阅读:
    《代码整洁之道》阅读笔记(三)
    pyqt5知识
    软件开发的生命周期
    软件过程与管理CMMI
    pyQt5练习(三)
    pyQt5练习(二)
    《代码整洁之道》阅读笔记(二)
    pyQt5练习(一)
    Android Studio错误:Connect to 127.0.0.1:1080 [/127.0.0.1] failed: Connection refused: connect
    AndroidStudio:Minimum supported Gradle version is XXX Current version is XXX
  • 原文地址:https://www.cnblogs.com/ahwu/p/3975077.html
Copyright © 2020-2023  润新知