<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[BIWEB开源PHP WMS系统创始人ArthurXF肖飞的blog]]></title> 
<link>http://www.bizeway.net/index.php</link> 
<description><![CDATA[网务通 - 网务公司发展之路]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[BIWEB开源PHP WMS系统创始人ArthurXF肖飞的blog]]></copyright>
<item>
<link>http://www.bizeway.net/read.php?</link>
<title><![CDATA[MemCached的PHP客户端操作类一]]></title> 
<author>ArthurXF &lt;arthurxf@gmail.com&gt;</author>
<category><![CDATA[PHP]]></category>
<pubDate>Thu, 25 Jan 2007 08:38:43 +0000</pubDate> 
<guid>http://www.bizeway.net/read.php?</guid> 
<description>
<![CDATA[ 
	<div class="code">&lt;?php <br/>// <br/>// +---------------------------------------------------------------------------+ <br/>// &#124; memcached client, PHP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// +---------------------------------------------------------------------------+ <br/>// &#124; Copyright (c) 2003 Ryan T. Dean &lt;rtdean@cytherianage.net&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// &#124; All rights reserved. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// &#124; Redistribution and use in source and binary forms, with or without &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; modification, are permitted provided that the following conditions &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; are met: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// &#124; 1. Redistributions of source code must retain the above copyright &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// &#124; &nbsp; &nbsp;notice, this list of conditions and the following disclaimer. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; 2. Redistributions in binary form must reproduce the above copyright &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; &nbsp; &nbsp;notice, this list of conditions and the following disclaimer in the &nbsp; &nbsp;&#124; <br/>// &#124; &nbsp; &nbsp;documentation and/or other materials provided with the distribution. &nbsp; &#124; <br/>// &#124; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// &#124; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS&#039;&#039; AND ANY EXPRESS OR &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES &#124; <br/>// &#124; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. &nbsp; &#124; <br/>// &#124; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT &nbsp;&#124; <br/>// &#124; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, &#124; <br/>// &#124; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY &nbsp; &nbsp; &#124; <br/>// &#124; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT &nbsp; &nbsp; &nbsp; &#124; <br/>// &#124; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF &nbsp;&#124; <br/>// &#124; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. &nbsp; &nbsp; &nbsp; &nbsp; &#124; <br/>// +---------------------------------------------------------------------------+ <br/>// &#124; Author: Ryan T. Dean &lt;rtdean@cytherianage.net&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; Heavily influenced by the Perl memcached client by Brad Fitzpatrick. &nbsp; &nbsp; &nbsp;&#124; <br/>// &#124; &nbsp; Permission granted by Brad Fitzpatrick for relicense of ported Perl &nbsp; &nbsp; &#124; <br/>// &#124; &nbsp; client logic under 2-clause BSD license. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#124; <br/>// +---------------------------------------------------------------------------+ <br/>// <br/>// $TCAnet$ <br/>// <br/><br/>/** <br/> * This is the PHP client for memcached - a distributed memory cache daemon. <br/> * More information is available at http://www.danga.com/memcached/ <br/> * <br/> * Usage example: <br/> * <br/> * require_once &#039;memcached.php&#039;; <br/> * &nbsp;<br/> * $mc = new memcached(array( <br/> * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#039;servers&#039; =&gt; array(&#039;127.0.0.1:10000&#039;, &nbsp;<br/> * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; array(&#039;192.0.0.1:10010&#039;, 2), <br/> * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#039;127.0.0.1:10020&#039;), <br/> * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#039;debug&#039; &nbsp; =&gt; false, <br/> * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#039;compress_threshold&#039; =&gt; 10240, <br/> * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#039;persistant&#039; =&gt; true)); <br/> * <br/> * $mc-&gt;add(&#039;key&#039;, array(&#039;some&#039;, &#039;array&#039;)); <br/> * $mc-&gt;replace(&#039;key&#039;, &#039;some random string&#039;); <br/> * $val = $mc-&gt;get(&#039;key&#039;); <br/> * <br/> * @author &nbsp;Ryan T. Dean &lt;rtdean@cytherianage.net&gt; <br/> * @package memcached-client <br/> * @version 0.1.2 <br/> */ <br/><br/>// {{{ requirements <br/>// }}} <br/><br/>// {{{ constants <br/>// {{{ flags <br/><br/>/** <br/> * Flag: indicates data is serialized <br/> */ <br/>define(&quot;MEMCACHE_SERIALIZED&quot;, 1&lt;&lt;0); <br/><br/>/** <br/> * Flag: indicates data is compressed <br/> */ <br/>define(&quot;MEMCACHE_COMPRESSED&quot;, 1&lt;&lt;1); <br/><br/>// }}} <br/><br/>/** <br/> * Minimum savings to store data compressed <br/> */ <br/>define(&quot;COMPRESSION_SAVINGS&quot;, 0.20); <br/><br/>// }}} <br/><br/>// {{{ class memcached <br/>/** <br/> * memcached client class implemented using (p)fsockopen() <br/> * <br/> * @author &nbsp;Ryan T. Dean &lt;rtdean@cytherianage.net&gt; <br/> * @package memcached-client <br/> */ <br/>class memcached <br/>{ <br/> &nbsp; // {{{ properties <br/> &nbsp; // {{{ public <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Command statistics <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; array <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $stats; <br/> &nbsp; &nbsp;<br/> &nbsp; // }}} <br/> &nbsp; // {{{ private <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Cached Sockets that are connected <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; array <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_cache_sock; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Current debug status; 0 - none to 9 - profiling <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; boolean <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_debug; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Dead hosts, assoc array, &#039;host&#039;=&gt;&#039;unixtime when ok to check again&#039; <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; array <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_host_dead; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Is compression available? <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; boolean <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_have_zlib; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Do we want to use compression? <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; boolean <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_compress_enable; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* At how many bytes should we compress? <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; interger <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_compress_threshold; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Are we using persistant links? <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; boolean <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_persistant; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* If only using one server; contains ip:port to connect to <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; string <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_single_sock; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Array containing ip:port or array(ip:port, weight) <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; array <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_servers; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Our bit buckets <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; array <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_buckets; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* Total # of bit buckets we have <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; interger <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_bucketcount; <br/> &nbsp; &nbsp;<br/> &nbsp; /** <br/> &nbsp; &nbsp;* # of total servers we have <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @var &nbsp; &nbsp; interger <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; var $_active; <br/><br/> &nbsp; // }}} <br/> &nbsp; // }}} <br/> &nbsp; // {{{ methods <br/> &nbsp; // {{{ public functions <br/> &nbsp; // {{{ memcached() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Memcache initializer <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; array &nbsp; &nbsp;$args &nbsp; &nbsp;Associative array of settings <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;mixed <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function memcached ($args) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$this-&gt;set_servers($args&#91;&#039;servers&#039;&#93;); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_debug = $args&#91;&#039;debug&#039;&#93;; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;stats = array(); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_compress_threshold = $args&#91;&#039;compress_threshold&#039;&#93;; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_persistant = isset($args&#91;&#039;persistant&#039;&#93;) ? $args&#91;&#039;persistant&#039;&#93; : false; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_compress_enable = true; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_have_zlib = function_exists(&quot;gzcompress&quot;); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_cache_sock = array(); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_host_dead = array(); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ add() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Adds a key/value to the memcache server if one isn&#039;t already set with &nbsp;<br/> &nbsp; &nbsp;* that key <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to set with data <br/> &nbsp; &nbsp;* @param &nbsp; mixed &nbsp; &nbsp;$val &nbsp; &nbsp; Value to store <br/> &nbsp; &nbsp;* @param &nbsp; interger $exp &nbsp; &nbsp; (optional) Time to expire data at <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;boolean <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function add ($key, $val, $exp = 0) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;return $this-&gt;_set(&#039;add&#039;, $key, $val, $exp); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ decr() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Decriment a value stored on the memcache server <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to decriment <br/> &nbsp; &nbsp;* @param &nbsp; interger $amt &nbsp; &nbsp; (optional) Amount to decriment <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;mixed &nbsp; &nbsp;FALSE on failure, value on success <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function decr ($key, $amt=1) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;return $this-&gt;_incrdecr(&#039;decr&#039;, $key, $amt); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ delete() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Deletes a key from the server, optionally after $time <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to delete <br/> &nbsp; &nbsp;* @param &nbsp; interger $time &nbsp; &nbsp;(optional) How long to wait before deleting <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;boolean &nbsp;TRUE on success, FALSE on failure <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function delete ($key, $time = 0) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_active) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$sock = $this-&gt;get_sock($key); <br/> &nbsp; &nbsp; &nbsp;if (!is_resource($sock)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$key = is_array($key) ? $key&#91;1&#93; : $key; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;stats&#91;&#039;delete&#039;&#93;++; <br/> &nbsp; &nbsp; &nbsp;$cmd = &quot;delete $key $time&#92;r&#92;n&quot;; <br/> &nbsp; &nbsp; &nbsp;if(!fwrite($sock, $cmd, strlen($cmd))) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_dead_sock($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp;$res = trim(fgets($sock)); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;MemCache: delete %s (%s)&#92;n&quot;, $key, $res); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($res == &quot;DELETED&quot;) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return true; <br/> &nbsp; &nbsp; &nbsp;return false; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ disconnect_all() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Disconnects all connected sockets <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function disconnect_all () <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;foreach ($this-&gt;_cache_sock as $sock) <br/> &nbsp; &nbsp; &nbsp; &nbsp; fclose($sock); <br/><br/> &nbsp; &nbsp; &nbsp;$this-&gt;_cache_sock = array(); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ enable_compress() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Enable / Disable compression <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; boolean &nbsp;$enable &nbsp;TRUE to enable, FALSE to disable <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function enable_compress ($enable) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_compress_enable = $enable; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ forget_dead_hosts() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Forget about all of the dead hosts <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function forget_dead_hosts () <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_host_dead = array(); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ get() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Retrieves the value associated with the key from the memcache server <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp;string &nbsp; $key &nbsp; &nbsp; Key to retrieve <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;mixed <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function get ($key) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_active) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$sock = $this-&gt;get_sock($key); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if (!is_resource($sock)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$this-&gt;stats&#91;&#039;get&#039;&#93;++; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$cmd = &quot;get $key&#92;r&#92;n&quot;; <br/> &nbsp; &nbsp; &nbsp;if (!fwrite($sock, $cmd, strlen($cmd))) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_dead_sock($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$val = array(); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_load_items($sock, $val); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; foreach ($val as $k =&gt; $v) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf(&quot;MemCache: sock %s got %s =&gt; %s&#92;r&#92;n&quot;, $sock, $k, $v); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;return $val&#91;$key&#93;; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ get_multi() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Get multiple keys from the server(s) <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; array &nbsp; &nbsp;$keys &nbsp; &nbsp;Keys to retrieve <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;array <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function get_multi ($keys) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_active) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$this-&gt;stats&#91;&#039;get_multi&#039;&#93;++; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;foreach ($keys as $key) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $sock = $this-&gt;get_sock($key); <br/> &nbsp; &nbsp; &nbsp; &nbsp; if (!is_resource($sock)) continue; <br/> &nbsp; &nbsp; &nbsp; &nbsp; $key = is_array($key) ? $key&#91;1&#93; : $key; <br/> &nbsp; &nbsp; &nbsp; &nbsp; if (!isset($sock_keys&#91;$sock&#93;)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$sock_keys&#91;$sock&#93; = array(); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$socks&#91;&#93; = $sock; <br/> &nbsp; &nbsp; &nbsp; &nbsp; } <br/> &nbsp; &nbsp; &nbsp; &nbsp; $sock_keys&#91;$sock&#93;&#91;&#93; = $key; <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;// Send out the requests <br/> &nbsp; &nbsp; &nbsp;foreach ($socks as $sock) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $cmd = &quot;get&quot;; <br/> &nbsp; &nbsp; &nbsp; &nbsp; foreach ($sock_keys&#91;$sock&#93; as $key) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$cmd .= &quot; &quot;. $key; <br/> &nbsp; &nbsp; &nbsp; &nbsp; } <br/> &nbsp; &nbsp; &nbsp; &nbsp; $cmd .= &quot;&#92;r&#92;n&quot;; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp; &nbsp; if (fwrite($sock, $cmd, strlen($cmd))) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$gather&#91;&#93; = $sock; <br/> &nbsp; &nbsp; &nbsp; &nbsp; } else <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$this-&gt;_dead_sock($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; } <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;// Parse responses <br/> &nbsp; &nbsp; &nbsp;$val = array(); <br/> &nbsp; &nbsp; &nbsp;foreach ($gather as $sock) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_load_items($sock, $val); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; foreach ($val as $k =&gt; $v) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf(&quot;MemCache: got %s =&gt; %s&#92;r&#92;n&quot;, $k, $v); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;return $val; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ incr() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Increments $key (optionally) by $amt <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to increment <br/> &nbsp; &nbsp;* @param &nbsp; interger $amt &nbsp; &nbsp; (optional) amount to increment <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;interger New key value? <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function incr ($key, $amt=1) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;return $this-&gt;_incrdecr(&#039;incr&#039;, $key, $amt); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ replace() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Overwrites an existing value for key; only works if key is already set <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to set value as <br/> &nbsp; &nbsp;* @param &nbsp; mixed &nbsp; &nbsp;$value &nbsp; Value to store <br/> &nbsp; &nbsp;* @param &nbsp; interger $exp &nbsp; &nbsp; (optional) Experiation time <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;boolean <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function replace ($key, $value, $exp=0) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;return $this-&gt;_set(&#039;replace&#039;, $key, $value, $exp); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ run_command() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Passes through $cmd to the memcache server connected by $sock; returns &nbsp;<br/> &nbsp; &nbsp;* output as an array (null array if no output) <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* NOTE: due to a possible bug in how PHP reads while using fgets(), each <br/> &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; line may not be terminated by a &#92;r&#92;n. &nbsp;More specifically, my testing <br/> &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; has shown that, on FreeBSD at least, each line is terminated only <br/> &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; with a &#92;n. &nbsp;This is with the PHP flag auto_detect_line_endings set <br/> &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; to falase (the default). <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; resource $sock &nbsp; &nbsp;Socket to send command on <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $cmd &nbsp; &nbsp; Command to run <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;array &nbsp; &nbsp;Output array <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function run_command ($sock, $cmd) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!is_resource($sock)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return array(); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if (!fwrite($sock, $cmd, strlen($cmd))) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return array(); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;while (true) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $res = fgets($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; $ret&#91;&#93; = $res; <br/> &nbsp; &nbsp; &nbsp; &nbsp; if (preg_match(&#039;/^END/&#039;, $res)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break; <br/> &nbsp; &nbsp; &nbsp; &nbsp; if (strlen($res) == 0) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break; <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp;return $ret; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ set() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Unconditionally sets a key to a given value in the memcache. &nbsp;Returns true <br/> &nbsp; &nbsp;* if set successfully. <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to set value as <br/> &nbsp; &nbsp;* @param &nbsp; mixed &nbsp; &nbsp;$value &nbsp; Value to set <br/> &nbsp; &nbsp;* @param &nbsp; interger $exp &nbsp; &nbsp; (optional) Experiation time <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;boolean &nbsp;TRUE on success <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function set ($key, $value, $exp=0) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;return $this-&gt;_set(&#039;set&#039;, $key, $value, $exp); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ set_compress_threshold() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Sets the compression threshold <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; interger $thresh &nbsp;Threshold to compress if larger than <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function set_compress_threshold ($thresh) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_compress_threshold = $thresh; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ set_debug() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Sets the debug flag <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; boolean &nbsp;$dbg &nbsp; &nbsp; TRUE for debugging, FALSE otherwise <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @see &nbsp; &nbsp; memcahced::memcached <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function set_debug ($dbg) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_debug = $dbg; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ set_servers() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Sets the server list to distribute key gets and puts between <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; array &nbsp; &nbsp;$list &nbsp; &nbsp;Array of servers to connect to <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;public <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @see &nbsp; &nbsp; memcached::memcached() <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function set_servers ($list) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_servers = $list; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_active = count($list); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_buckets = null; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_bucketcount = 0; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_single_sock = null; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_active == 1) <br/> &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_single_sock = $this-&gt;_servers&#91;0&#93;; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // }}} <br/> &nbsp; // {{{ private methods <br/> &nbsp; // {{{ _close_sock() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Close the specified socket <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $sock &nbsp; &nbsp;Socket to close <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _close_sock ($sock) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$host = array_search($sock, $this-&gt;_cache_sock); <br/> &nbsp; &nbsp; &nbsp;fclose($this-&gt;_cache_sock&#91;$host&#93;); <br/> &nbsp; &nbsp; &nbsp;unset($this-&gt;_cache_sock&#91;$host&#93;); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ _connect_sock() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Connects $sock to $host, timing out after $timeout <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; interger $sock &nbsp; &nbsp;Socket to connect <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $host &nbsp; &nbsp;Host:IP to connect to <br/> &nbsp; &nbsp;* @param &nbsp; float &nbsp; &nbsp;$timeout (optional) Timeout value, defaults to 0.25s <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;boolean <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _connect_sock (&amp;$sock, $host, $timeout = 0.25) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;list ($ip, $port) = explode(&quot;:&quot;, $host); <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_persistant == 1) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $sock = @pfsockopen($ip, $port, $errno, $errstr, $timeout); <br/> &nbsp; &nbsp; &nbsp;} else <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $sock = @fsockopen($ip, $port, $errno, $errstr, $timeout); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if (!$sock) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp;return true; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ _dead_sock() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Marks a host as dead until 30-40 seconds in the future <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $sock &nbsp; &nbsp;Socket to mark as dead <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _dead_sock ($sock) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$host = array_search($sock, $this-&gt;_cache_sock); <br/> &nbsp; &nbsp; &nbsp;list ($ip, $port) = explode(&quot;:&quot;, $host); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_host_dead&#91;$ip&#93; = time() + 30 + intval(rand(0, 10)); <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_host_dead&#91;$host&#93; = $this-&gt;_host_dead&#91;$ip&#93;; <br/> &nbsp; &nbsp; &nbsp;unset($this-&gt;_cache_sock&#91;$host&#93;); <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ get_sock() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* get_sock <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to retrieve value for; <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;mixed &nbsp; &nbsp;resource on success, false on failure <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function get_sock ($key) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_active) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/><br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_single_sock !== null) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return $this-&gt;sock_to_host($this-&gt;_single_sock); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$hv = is_array($key) ? intval($key&#91;0&#93;) : $this-&gt;_hashfunc($key); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_buckets === null) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; foreach ($this-&gt;_servers as $v) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (is_array($v)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for ($i=0; $i&lt;$v&#91;1&#93;; $i++) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$bu&#91;&#93; = $v&#91;0&#93;; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} else <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $bu&#91;&#93; = $v; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; &nbsp; } <br/> &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_buckets = $bu; <br/> &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_bucketcount = count($bu); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$realkey = is_array($key) ? $key&#91;1&#93; : $key; <br/> &nbsp; &nbsp; &nbsp;for ($tries = 0; $tries&lt;20; $tries++) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $host = $this-&gt;_buckets&#91;$hv % $this-&gt;_bucketcount&#93;; <br/> &nbsp; &nbsp; &nbsp; &nbsp; $sock = $this-&gt;sock_to_host($host); <br/> &nbsp; &nbsp; &nbsp; &nbsp; if (is_resource($sock)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return $sock; <br/> &nbsp; &nbsp; &nbsp; &nbsp; $hv += $this-&gt;_hashfunc($tries . $realkey); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;return false; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ _hashfunc() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Creates a hash interger based on the $key <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to hash <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;interger Hash value <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _hashfunc ($key) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;$hash = 0; <br/> &nbsp; &nbsp; &nbsp;for ($i=0; $i&lt;strlen($key); $i++) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $hash = $hash*33 + ord($key&#91;$i&#93;); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;return $hash; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ _incrdecr() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Perform increment/decriment on $key <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $cmd &nbsp; &nbsp; Command to perform <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to perform it on <br/> &nbsp; &nbsp;* @param &nbsp; interger $amt &nbsp; &nbsp; Amount to adjust <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;interger &nbsp; &nbsp;New value of $key <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _incrdecr ($cmd, $key, $amt=1) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_active) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return null; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$sock = $this-&gt;get_sock($key); <br/> &nbsp; &nbsp; &nbsp;if (!is_resource($sock)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return null; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$key = is_array($key) ? $key&#91;1&#93; : $key; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;stats&#91;$cmd&#93;++; <br/> &nbsp; &nbsp; &nbsp;if (!fwrite($sock, &quot;$cmd $key $amt&#92;r&#92;n&quot;)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return $this-&gt;_dead_sock($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;stream_set_timeout($sock, 1, 0); <br/> &nbsp; &nbsp; &nbsp;$line = fgets($sock); <br/> &nbsp; &nbsp; &nbsp;if (!preg_match(&#039;/^(&#92;d+)/&#039;, $line, $match)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return null; <br/> &nbsp; &nbsp; &nbsp;return $match&#91;1&#93;; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ _load_items() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Load items into $ret from $sock <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; resource $sock &nbsp; &nbsp;Socket to read from <br/> &nbsp; &nbsp;* @param &nbsp; array &nbsp; &nbsp;$ret &nbsp; &nbsp; Returned values <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _load_items ($sock, &amp;$ret) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;while (1) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $decl = fgets($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; if ($decl == &quot;END&#92;r&#92;n&quot;) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true; <br/> &nbsp; &nbsp; &nbsp; &nbsp; } elseif (preg_match(&#039;/^VALUE (&#92;S+) (&#92;d+) (&#92;d+)&#92;r&#92;n$/&#039;, $decl, $match)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list($rkey, $flags, $len) = array($match&#91;1&#93;, $match&#91;2&#93;, $match&#91;3&#93;); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$bneed = $len+2; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$offset = 0; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;while ($bneed &gt; 0) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $data = fread($sock, $bneed); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $n = strlen($data); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ($n == 0) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $offset += $n; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $bneed -= $n; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ret&#91;$rkey&#93; .= $data; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ($offset != $len+2) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Something is borked! <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf(&quot;Something is borked! &nbsp;key %s expecting %d got %d length&#92;n&quot;, $rkey, $len+2, $offset); <br/><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unset($ret&#91;$rkey&#93;); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;_close_sock($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$ret&#91;$rkey&#93; = rtrim($ret&#91;$rkey&#93;); <br/><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ($this-&gt;_have_zlib &amp;&amp; $flags &amp; MEMCACHE_COMPRESSED) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ret&#91;$rkey&#93; = gzuncompress($ret&#91;$rkey&#93;); <br/><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ($flags &amp; MEMCACHE_SERIALIZED) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ret&#91;$rkey&#93; = unserialize($ret&#91;$rkey&#93;); <br/><br/> &nbsp; &nbsp; &nbsp; &nbsp; } else &nbsp;<br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(&quot;Error parsing memcached response&#92;n&quot;); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return 0; <br/> &nbsp; &nbsp; &nbsp; &nbsp; } <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ _set() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Performs the requested storage operation to the memcache server <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $cmd &nbsp; &nbsp; Command to perform <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $key &nbsp; &nbsp; Key to act on <br/> &nbsp; &nbsp;* @param &nbsp; mixed &nbsp; &nbsp;$val &nbsp; &nbsp; What we need to store <br/> &nbsp; &nbsp;* @param &nbsp; interger $exp &nbsp; &nbsp; When it should expire <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;boolean <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function _set ($cmd, $key, $val, $exp) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_active) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$sock = $this-&gt;get_sock($key); <br/> &nbsp; &nbsp; &nbsp;if (!is_resource($sock)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return false; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$this-&gt;stats&#91;$cmd&#93;++; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$flags = 0; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if (!is_scalar($val)) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $val = serialize($val); <br/> &nbsp; &nbsp; &nbsp; &nbsp; $flags &#124;= MEMCACHE_SERIALIZED; <br/> &nbsp; &nbsp; &nbsp; &nbsp; if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf(&quot;client: serializing data as it is not scalar&#92;n&quot;); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$len = strlen($val); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_have_zlib &amp;&amp; $this-&gt;_compress_enable &amp;&amp; &nbsp;<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$this-&gt;_compress_threshold &amp;&amp; $len &gt;= $this-&gt;_compress_threshold) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; $c_val = gzcompress($val, 9); <br/> &nbsp; &nbsp; &nbsp; &nbsp; $c_len = strlen($c_val); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp; &nbsp; if ($c_len &lt; $len*(1 - COMPRESS_SAVINGS)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; { <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;client: compressing data; was %d bytes is now %d bytes&#92;n&quot;, $len, $c_len); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$val = $c_val; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$len = $c_len; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$flags &#124;= MEMCACHE_COMPRESSED; <br/> &nbsp; &nbsp; &nbsp; &nbsp; } <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp;if (!fwrite($sock, &quot;$cmd $key $flags $exp $len&#92;r&#92;n$val&#92;r&#92;n&quot;)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return $this-&gt;_dead_sock($sock); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;$line = trim(fgets($sock)); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;if ($this-&gt;_debug) <br/> &nbsp; &nbsp; &nbsp;{ <br/> &nbsp; &nbsp; &nbsp; &nbsp; if ($flags &amp; MEMCACHE_COMPRESSED) <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$val = &#039;compressed data&#039;; <br/> &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;MemCache: %s %s =&gt; %s (%s)&#92;n&quot;, $cmd, $key, $val, $line); <br/> &nbsp; &nbsp; &nbsp;} <br/> &nbsp; &nbsp; &nbsp;if ($line == &quot;STORED&quot;) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return true; <br/> &nbsp; &nbsp; &nbsp;return false; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // {{{ sock_to_host() <br/><br/> &nbsp; /** <br/> &nbsp; &nbsp;* Returns the socket for the host <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @param &nbsp; string &nbsp; $host &nbsp; &nbsp;Host:IP to get socket for <br/> &nbsp; &nbsp;* <br/> &nbsp; &nbsp;* @return &nbsp;mixed &nbsp; &nbsp;IO Stream or false <br/> &nbsp; &nbsp;* @access &nbsp;private <br/> &nbsp; &nbsp;*/ <br/> &nbsp; function sock_to_host ($host) <br/> &nbsp; { <br/> &nbsp; &nbsp; &nbsp;if (isset($this-&gt;_cache_sock&#91;$host&#93;)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return $this-&gt;_cache_sock&#91;$host&#93;; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$now = time(); <br/> &nbsp; &nbsp; &nbsp;list ($ip, $port) = explode (&quot;:&quot;, $host); <br/> &nbsp; &nbsp; &nbsp;if (isset($this-&gt;_host_dead&#91;$host&#93;) &amp;&amp; $this-&gt;_host_dead&#91;$host&#93; &gt; $now &#124;&#124; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;isset($this-&gt;_host_dead&#91;$ip&#93;) &amp;&amp; $this-&gt;_host_dead&#91;$ip&#93; &gt; $now) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return null; <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;if (!$this-&gt;_connect_sock($sock, $host)) <br/> &nbsp; &nbsp; &nbsp; &nbsp; return $this-&gt;_dead_sock($host); <br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br/> &nbsp; &nbsp; &nbsp;// Do not buffer writes <br/> &nbsp; &nbsp; &nbsp;stream_set_write_buffer($sock, 0); <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;$this-&gt;_cache_sock&#91;$host&#93; = $sock; <br/> &nbsp; &nbsp; &nbsp; <br/> &nbsp; &nbsp; &nbsp;return $this-&gt;_cache_sock&#91;$host&#93;; <br/> &nbsp; } <br/><br/> &nbsp; // }}} <br/> &nbsp; // }}} <br/> &nbsp; // }}} <br/>} <br/><br/>// }}} <br/>?&gt; </div><br/>Tags - <a href="tag.php?tag=php" rel="tag">php</a> , <a href="tag.php?tag=memcached" rel="tag">memcached</a>
]]>
</description>
</item><item>
<link>http://www.bizeway.net/read.php?&amp;guid=0#topreply</link>
<title><![CDATA[[评论] MemCached的PHP客户端操作类一]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.bizeway.net/read.php?&amp;guid=0#topreply</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>