欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

Tokyo Tyrant的PHP类

程序员文章站 2022-05-24 22:56:22
...
Tyrant文件夹里的文件

Common.php

* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package    Tyrant* @author     Bertrand Mansion * @license    http://www.opensource.org/licenses/mit-license.php MIT License* @link       http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/../Tyrant.php';require_once dirname(__FILE__).'/Exception.php';/*** Abstract base class for all types of database connections** This base class is mostly here to avoid duplication of code since * databases share common functions. It** @package    Tyrant* @author     Bertrand Mansion */abstract class Tyrant_Common implements ArrayAccess, Countable, Iterator{    protected $socket;    abstract function put($key, $value);    abstract function get($key);    public function __construct(&$socket)    {        $this->socket =& $socket;    }    /**    * Close the connection to TokyoTyrant    */    public function disconnect()    {        if (is_resource($this->socket)) {            socket_close($this->socket);            $this->socket = null;        }    }    /**    * Returns the connection socket    * @return resource  Connection socket    */    public function &socket()    {        return $this->socket;    }    /**    * Removes a record    *     * @param    string  Specifies the primary key    * @return   bool    True when successful, false otherwise    */    public function out($key)    {        $cmd = pack('CCN', 0xC8, 0x20, strlen($key)) . $key;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }                return true;    }    /**    * Gets the size of the value of a record    *    * @param    string  Specifies the key    * @return   int|false   Number with size or false otherwise    */    public function vsiz($key)    {        $cmd = pack("CCN", 0xC8, 0x38, strlen($key)) . $key;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return $this->_recvInt32();    }    /**    * Initializes the iterator    *    * The iterator is used in order to access the key of every record     * stored in a database.    *    * @return   bool    True when successful, false otherwise    */    public function iterinit()    {        $cmd = pack("CC", 0xC8, 0x50);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return true;    }    /**    * Gets the next key of the iterator    *    * It is possible to access every record by iteration of     * calling this method. It is allowed to update or remove     * records whose keys are fetched while the iteration.    * However, it is not assured if updating the database is     * occurred while the iteration. Besides, the order of this     * traversal access method is arbitrary, so it is not assured     * that the order of storing matches the one of the traversal     * access.    *    * @return   mixed   Either the next key when successful, false if no more records are available    */    public function iternext()    {        $cmd = pack("CC", 0xC8, 0x51);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        $ksiz = $this->_recvInt32();        if ($ksiz === false) {            return false;        }        $kref = $this->_recv($ksiz);        return $kref;    }    /**    * Gets forward matching keys    *    * The return value is an array of the keys of the     * corresponding records. This method does never fail and return     * an empty array even if no record corresponds. Note that this     * method may be very slow because every key in the database is     * scanned.    *    * @param    string  Prefix of the corresponding keys    * @param    int     Maximum number of keys to be fetched. If it    *                   is not defined or negative, no limit is specified.    * @return   array   An array of found primary keys    */    public function fwmkeys($prefix, $max = null)    {        $keys = array();        if (empty($max) || $max _send($cmd);        if ($code !== 0) {            return $keys;        }        $knum = $this->_recvInt32();        if ($knum === false) {            return $keys;        }        for ($i = 0; $i _recvInt32();            if ($ksiz === false) {                return $keys;            }            $kref = $this->_recv($ksiz);            $keys[] = $kref;        }        return $keys;    }    /**    * Synchronizes updated contents with the file and the device    * @return   bool    True when successful, false otherwise    */    public function sync()    {        $cmd = pack('CC', 0xC8, 0x70);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return true;    }    /**    * Optimize the database file    * @return   bool    True when successful, false otherwise    */    public function optimize($params = "")    {        $cmd = pack('CCN', 0xC8, 0x71, strlen($params)) . $params;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return true;    }    /**    * Remove all records    * @return   bool    True when successful, false otherwise    */    public function vanish()    {        $cmd = pack('CC', 0xC8, 0x72);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return true;    }    /**    * Copy the database file    *    * The database file is assured to be kept synchronized and not modified     * while the copying or executing operation is in progress.    * So, this method is useful to create a backup file of the database file.    *    * @param    string  Specifies the path of the destination file.    *                   If it begins with `@', the trailing substring     *                   is executed as a command line.    * @return   True if successful, false otherwise.    */    public function copy($path)    {        $cmd = pack('CCN', 0xC8, 0x73, strlen($path)) . $path;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return true;    }    /**    * Restore the database with update log    *    * @param    Specifies the path of the update log directory    * @param    Specifies the beginning time stamp in microseconds    * @param    Specifies options by bitwise-or:    *           - Tyrant::ROCHKCON for consistency checking    * @return   True if successful, false otherwise.    */    public function restore($path, $msec, $opts = 0)    {        $cmd = pack('CCN', 0xC8, 0x74, strlen($path)) .                 $this->_pack64($msec) . $opts . $path;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return true;    }    /**    * Get the number of records    * @return int|false Number of records or false if something goes wrong    */    public function rnum()    {        $cmd = pack('CC', 0xC8, 0x80);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return $this->_recvInt64();    }    /**    * Get the size of the database    * @return mixed  Database size or false if something goes wrong    */    public function size()    {        $cmd = pack('CC', 0xC8, 0x81);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        return $this->_recvInt64();    }    /**    * Get some statistics about the database    * @return   array   Array of statistics about the database    */    public function stat()    {        $cmd = pack('CC', 0xC8, 0x88);        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        $value = $this->_recv();        $value = explode("\n", trim($value));        $stats = array();        foreach ($value as $v) {            $v = explode("\t", $v);            $stats[$v[0]] = $v[1];        }        return $stats;    }    /**    * Call a versatile function for miscellaneous operations    *    * All databases support "putlist", "outlist", and "getlist".    * - putlist is to store records. It receives keys and values one     *   after the other, and returns an empty list.    * - outlist is to remove records. It receives keys, and returns     *   an empty list.    * - getlist is to retrieve records. It receives keys, and returns     *   values.    *    * Table database supports "setindex", "search", "genuid".    *    * @param    string  Specifies the name of the function    * @param    array   Specifies an array containing arguments    * @param    int     Specifies options by bitwise-or    *                   bitflag that can be Tyrant::MONOULOG to prevent     *                   writing to the update log    * @return   array|false     Values or false if something goes wrong    */    public function misc($name, Array $args = array(), $opts = 0)    {        $cmd = pack('CCNNN', 0xC8, 0x90, strlen($name), $opts,                 count($args)) . $name;        foreach ($args as $arg) {            $cmd .= pack('N', strlen($arg)) . $arg;        }        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        $rnum = $this->_recvInt32();        $res = array();        for ($i = 0; $i _recvInt32();            if ($esiz === false) {                return false;            }            $eref = $this->_recv($esiz);            if ($eref === false) {                return false;            }            $res[] = $eref;        }        return $res;    }    /**    * Call a function of the script language extension    *    * @param    string  Specifies the function name    * @param    string  Specifies the key. Defaults to an empty string.    * @param    string  Specifies the value. Defaults to an empty string.    * @param    int     Specifies options by bitwise-or:     *                   - Tyrant::XOLCKREC for record locking    *                   - Tyrant::XOLCKGLB for global locking    *                   Defaults to no option.    * @return   mixed   Value of the response or false on failure    */    public function ext($name, $key = '', $value = '', $opts = 0)    {        $cmd = pack('CCNNNN', 0xC8, 0x68, strlen($name), $opts,                 strlen($key), strlen($value)) .                 $name . $key . $value;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        $vsiz = $this->_recvInt32();        if ($vsiz _recv($vsiz);        return $vbuf;    }    protected function _socketWrite($cmd)    {        $len = strlen($cmd);        $offset = 0;        while ($offset socket, substr($cmd, $offset), $len-$offset);            if ($sent === false) {                return false;            }            $offset += $sent;        }        return ($offset _socketWrite($cmd);        if ($status === false) {            return false;        }        $code = $this->_recvCode();        if ($code === false) {            return false;        }        return $code;    }    protected function _recv($len = null)    {        if (is_null($len)) {            $len = $this->_recvInt32();            if ($len === false) {                return false;            }        }        if ($len socket, $str, $len, 0))  0) {            $tstr = "";            if (($rec = socket_recv($this->socket, $tstr, $len, 0)) _recv(1)) !== false) {            $c = unpack("C", $rbuf);            if (!isset($c[1])) {                return false;            }            return $c[1];        }        return false;    }    protected function _recvInt32()    {        if (($rbuf = $this->_recv(4)) !== false) {            $num = unpack("N", $rbuf);            if (!isset($num[1])) {                return false;            }            $size = unpack("l", pack("l", $num[1]));            return $size[1];        }        return false;    }    protected function _recvInt64()    {        if (($rbuf = $this->_recv(8)) !== false) {            return $this->_unpack64($rbuf);        }        return false;    }    /**    * Portability function to pack a x64 value with PHP limitations    * @return   mixed   Packed number    */    protected function _pack64($v)    {        // x64        if (PHP_INT_SIZE >= 8) {            $v = (int)$v;            return pack ("NN", $v>>32, $v&0xFFFFFFFF);        }        // x32, int        if (is_int($v)) {            return pack("NN", $v = 8) {            if ($hi  0) {                return $lo;            }            return sprintf("%u", $lo);        } elseif ($hi == -1) {            // x32, int            if ($lo iterinit();        $this->_current = $this->iternext();    }    /**    * Return the current element.     * Similar to the current() function for arrays in PHP     * @return mixed current element from the collection     */    public function current()    {        return $this->get($this->_current);    }    /**     * Return the identifying key of the current element.     * Similar to the key() function for arrays in PHP     * @return mixed either an integer or a string     */     public function key()    {        return $this->_current;    }    /**     * Move forward to next element.     * Similar to the next() function for arrays in PHP     * @return void     */     public function next()    {        $this->_current = $this->iternext();    }        /**     * Check if there is a current element after calls to rewind() or next().     * Used to check if we've iterated to the end of the collection     * @return boolean FALSE if there's nothing more to iterate over     */     public function valid()    {        return $this->_current !== false;    }        /**    * Returns whether the key exists    * @return boolean    */    public function offsetExists($offset)    {        return $this->vsiz($offset) !== false;    }    /**    * Returns the value associated with the key     * @return mixed    */    public function offsetGet($offset)    {        return $this->get($offset);    }    /**    * Sets a value for the key    * @return boolean   True if value was set successfully    */    public function offsetSet($offset, $value)    {        return $this->put($offset, $value);    }    /**    * Removes the value for the key    * @return void    */    public function offsetUnset($offset)    {        $this->out($offset);    }    /**    * Returns the number of records in the database    * @return int   Number of records    */    public function count()    {        return $this->rnum();    }}

Exception.php

* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package    Tyrant* @author     Bertrand Mansion * @license    http://www.opensource.org/licenses/mit-license.php MIT License* @link       http://mamasam.indefero.net/p/tyrant/*//*** Base class for Exceptions in Tyrant package** @package    Tyrant*/class Tyrant_Exception extends Exception { }

Query.php

** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.** @package    Tyrant* @author     Bertrand Mansion * @license    http://www.opensource.org/licenses/mit-license.php MIT License* @link       http://mamasam.indefero.net/p/tyrant/*//*** Query class for the RDBTable database queries** @package    Tyrant* @author     Bertrand Mansion */class Tyrant_Query{    /**    * Query arguments    * @var  array    */    protected $args = array();    /**    * Query condition: string is equal to    */    const QCSTREQ = 0;    /**    * Query condition: string is included in    */    const QCSTRINC = 1;    /**    * Query condition: string begins with    */    const QCSTRBW = 2;    /**    * Query condition: string ends with    */    const QCSTREW = 3;    /**    * Query condition: string includes all tokens in    */    const QCSTRAND = 4;    /**    * Query condition: string includes at least one token in    */    const QCSTROR = 5;    /**    * Query condition: string is equal to at least one token in    */    const QCSTROREQ = 6;    /**    * Query condition: string matches regular expressions of    */    const QCSTRRX = 7;    /**    * Query condition: number is equal to    */    const QCNUMEQ = 8;    /**    * Query condition: number is greater than    */    const QCNUMGT = 9;    /**    * Query condition: number is greater than or equal to    */    const QCNUMGE = 10;    /**    * Query condition: number is less than    */    const QCNUMLT = 11;    /**    * Query condition: number is less than or equal to    */    const QCNUMLE = 12;    /**    * Query condition: number is between two tokens of    */    const QCNUMBT = 13;    /**    * Query condition: number is equal to at least one token in    */    const QCNUMOREQ = 14;    /**    * Query condition: full-text search with the phrase of the expression    */    const QCFTSPH = 15;    /**    * Query condition: full-text search with all tokens in the expression    */    const QCFTSAND = 16;    /**    * Query condition: full-text search with at least one token in the expression    */    const QCFTSOR = 17;    /**    * Query condition: full-text search with the compound expression    */    const QCFTSEX = 18;    /**    * Query condition: negation flag    */    const QCNEGATE = 16777216;    /**    * Query condition: no index flag    */    const QCNOIDX = 33554432;    /**    * Order type: string ascending    */    const QOSTRASC = 0;    /**    * Order type: string descending    */    const QOSTRDESC = 1;    /**    * Order type: number ascending    */    const QONUMASC = 2;    /**    * Order type: number descending    */    const QONUMDESC = 3;    /**    * Add a query argument for "string is equal to column"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function is($name, $expr)    {        $this->addCond($name, self::QCSTREQ, $expr);    }    /**    * Add a query argument for "string is included in column"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function like($name, $expr)    {        $this->addCond($name, self::QCSTRINC, $expr);    }    /**    * Add a query argument for "string includes at least one token from column"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function has($name, $expr)    {        $this->addCond($name, self::QCSTROR, $expr);    }    /**    * Add a query argument for "string includes all tokens from column"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function hasAll($name, $expr)    {        $this->addCond($name, self::QCSTRAND, $expr);    }    /**    * Add a query argument for "string is equal to at least one token from column"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function isOne($name, $expr)    {        $this->addCond($name, self::QCSTROREQ, $expr);    }    /**    * Add a query argument for "string begins with"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function starts($name, $expr)    {        $this->addCond($name, self::QCSTRBW, $expr);    }    /**    * Add a query argument for "string ends with"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function ends($name, $expr)    {        $this->addCond($name, self::QCSTREW, $expr);    }    /**    * Add a query argument for "string matches regular expressions of"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function matches($name, $expr)    {        $this->addCond($name, self::QCSTRRX, $expr);    }    /**    * Add a query argument for "number is equal to"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function eq($name, $expr)    {        $this->addCond($name, self::QCNUMEQ, $expr);    }    /**    * Add a query argument for "number is greater than"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function gt($name, $expr)    {        $this->addCond($name, self::QCNUMGT, $expr);    }    /**    * Add a query argument for "number is greater than or equal to"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function gte($name, $expr)    {        $this->addCond($name, self::QCNUMGE, $expr);    }    /**    * Add a query argument for "number is less than"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function lt($name, $expr)    {        $this->addCond($name, self::QCNUMLT, $expr);    }    /**    * Add a query argument for "number is less than or equal to"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function lte($name, $expr)    {        $this->addCond($name, self::QCNUMLE, $expr);    }    /**    * Add a query argument for "number is between two tokens of"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function between($name, $expr)    {        $this->addCond($name, self::QCNUMBT, $expr);    }    /**    * Add a query argument for "number is equal to at least one token in"    * @param    string  Column to query upon    * @param    string  Value to search    */    public function eqOne($name, $expr)    {        $this->addCond($name, self::QCNUMOREQ, $expr);    }    /**    * Add a sort parameter for the query    * @param    string  Column to sort    * @param    string  'numeric' or 'literal'    * @param    string  'asc' or 'desc'    */    public function sortBy($name, $type = 'numeric', $direction = 'asc')    {        if ($type != 'numeric') {            $type = $direction != 'asc' ? self::QOSTRDESC : self::QOSTRASC;        } else {            $type = $direction != 'asc' ? self::QONUMDESC : self::QONUMASC;        }        $this->setOrder($name, $type);    }    /**    * Add a narrowing condition for the query.    * @param    string  Name of a column.  An empty string means the primary key.    * @param    int     Operation type, see class constants.    * @param    mixed   Operand exression.    */    public function addCond($name, $op, $expr)    {        $this->args[] = "addcond\0" . $name . "\0" . $op . "\0" . $expr;    }    /**    * Add a sort parameter for the query    * @param    string  Name of a column.    * @param    int     Sort type, see class constants.    */    public function setOrder($name, $type)    {        $this->args['order'] = "setorder\0" . $name . "\0" . $type;    }    /**    * Limit the number of records returned by the query    * @param    int     Maximum number of records returned    * @param    int     Number of records to skip    */    public function setLimit($max = -1, $skip = -1)    {        $this->args['limit'] = "setlimit\0" . $max . "\0" . $skip;    }    /**    * Return the query arguments    * @return   array   Query arguments    */    public function args()    {        return $this->args;    }}

RDB.php

* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package    Tyrant* @author     Bertrand Mansion * @license    http://www.opensource.org/licenses/mit-license.php MIT License* @link       http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/Common.php';/*** Hash and other types of database connection, all except the Table type** @package    Tyrant* @author     Bertrand Mansion */class Tyrant_RDB extends Tyrant_Common{    /**    * Unconditionally set key to value    * If a record with the same key exists in the database,     * it is overwritten.    *    * @param    string|int  Specifies the key.    * @param    mixed       A scalar value (or an object with __toString)    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function put($key, $value)    {        $cmd = pack('CCNN', 0xC8, 0x10, strlen($key), strlen($value)) .                 $key . $value;        $code = $this->_send($cmd);        if ($code !== 0) {            throw new Tyrant_Exception("Put error");        }                return true;    }    /**    * Store a new record    * If a record with the same key exists in the database,    * this method has no effect.    *    * @param    string|int  Specifies the key.    * @param    mixed       A scalar value (or an object with __toString)    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function putkeep($key, $value)    {        $cmd = pack('CCNN', 0xC8, 0x11, strlen($key), strlen($value)) .                 $key . $value;        $code = $this->_send($cmd);        if ($code !== 0) {            throw new Tyrant_Exception("Put error");        }                return true;    }    /**    * Append value to the existing value for key, or set key to    * value if it does not already exist.    *    * @param    string|int  Specifies the key.    * @param    mixed       A scalar value (or an object with __toString)    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function putcat($key, $value)    {        $cmd = pack('CCNN', 0xC8, 0x12, strlen($key), strlen($value)) .                 $key . $value;        $code = $this->_send($cmd);        if ($code !== 0) {            throw new Tyrant_Exception("Put error");        }                return true;    }    /**    * Concatenate a value at the end of the existing record and     * shift it to the left    *    * @param    string|int  Specifies the key.    * @param    mixed       A scalar value (or an object with __toString)    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function putshl($key, $value, $width)    {        $width = $width _send($cmd);        if ($code !== 0) {            throw new Tyrant_Exception("Put error");        }                return true;    }    /**    * Set key to value without waiting for a server response    *    * @param    string|int  Specifies the key.    * @param    mixed       A scalar value (or an object with __toString)    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function putnr($key, $value)    {        $cmd = pack('CCNN', 0xC8, 0x18, strlen($key), strlen($value)) .                 $key . $value;        $status = $this->_socketWrite($cmd);        if ($status === false) {            throw new Tyrant_Exception("Put error");        }        return true;    }    /**    * Get the value of a key from the server    *    * @param    string|int  Specifies the key.    * @return   string|null The value    */    public function get($key)    {        $cmd = pack('CCN', 0xC8, 0x30, strlen($key)) . $key;        $code = $this->_send($cmd);        if ($code !== 0) {            return null;        }        $value = $this->_recv();        return $value;    }    /**    * Retrieve records    * As a result of this method, keys existing in the database have     * the corresponding values and keys not existing in the database     * are removed.    *    * @param    array   Associative array containing the retrieval keys    *                   The array is given by reference so it will be     *                   filled with the values found.    * @return   int|false   Number of retrieved records or false on failure.    */    public function mget(&$recs)    {        $rnum = 0;        $cmd = "";        foreach ($recs as $key => $value) {            $cmd .= pack("N", strlen($key)) . $key;            $rnum++;        }        $cmd = pack("CCN", 0xC8, 0x31, $rnum) . $cmd;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        $rnum = $this->_recvInt32();        if ($rnum === false) {            return false;        }        $recs = array();        for ($i = 0; $i _recvInt32();            $vsiz = $this->_recvInt32();            if ($ksiz === false || $vsiz === false) {                return false;            }            $kref = $this->_recv($ksiz);            $vref = $this->_recv($vsiz);            $recs[$kref] = $vref;        }        return $rnum;    }    /**    * Add an integer to a record    * If the corresponding record exists, the value is treated as     * an integer and is added to the existing value. If no record exists,     * a new record is created with the value.    *     * @param    string      The key    * @param    int         The additional value    * @return   int|false   The summation value or false    * @throws   Tyrant_Exception    */    public function addInt($key, $num = 0)    {        $cmd = pack("CCNN", 0xC8, 0x60, strlen($key), (int)$num) . $key;        $code = $this->_send($cmd);        if ($code !== 0) {            throw new Tyrant_Exception("Could not addInt to ".$key);        }        return $this->_recvInt32();    }    /**    * Add a real number to a record    * If the corresponding record exists, the value is treated as     * a real number and is added to the existing value. If no record exists,     * a new record is created with the value.    *     * @param    string      The key    * @param    int         The additional value    * @return   int|false   The summation value or false    * @throws   Tyrant_Exception    */    public function addDouble($key, $num = 0)    {        $integ = substr($num, 0, strpos($num, '.'));        $fract = (abs($num) - floor(abs($num)))*1000000000000;        $cmd = pack('CCN', 0xC8, 0x61, strlen($key)) .                 $this->_pack64($integ) . $this->_pack64($fract) . $key;        $code = $this->_send($cmd);        if ($code !== 0) {            throw new Tyrant_Exception("AddDouble error");        }        $integ = $this->_recvint64();        $fract = $this->_recvint64();        return $integ + ($fract / 1000000000000);    }}

RDBTable.php

** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.** @package    Tyrant* @author     Bertrand Mansion * @license    http://www.opensource.org/licenses/mit-license.php MIT License* @link       http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/Common.php';require_once dirname(__FILE__).'/Query.php';/*** Table type database connection** @package    Tyrant* @author     Bertrand Mansion */class Tyrant_RDBTable extends Tyrant_Common{    /**    * index type: lexical string    */    const ITLEXICAL = 0;    /**    * index type: decimal string    */    const ITDECIMAL = 1;    /**    * index type: token inverted index    */    const ITTOKEN = 2;    /**    * index type: q-gram inverted index    */    const ITQGRAM = 3;    /**    * index type: optimize    */    const ITOPT = 9998;    /**    * index type: void    */    const ITVOID = 9999;    /**    * index type: keep existing index    */    const ITKEEP = 16777216; // 1  $cvalue) {            $args[] = $ckey;            $args[] = $cvalue;        }        $rv = $this->misc('put', $args, 0);        if ($rv === false) {            throw new Tyrant_Exception("Put error");        }        return true;    }    /**    * Store a new record    * If a record with the same key exists in the database,    * this method has no effect.    *    * @param    string|int  Specifies the primary key.    * @param    array       Associative array containing key/values.    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function putkeep($key, Array $values)    {        $args = array($key);        foreach ($values as $ckey => $cvalue) {            $args[] = $ckey;            $args[] = $cvalue;        }        $rv = $this->misc('putkeep', $args, 0);        if ($rv === false) {            throw new Tyrant_Exception("Put error");        }        return true;    }    /**    * Concatenate columns of the existing record    * If there is no corresponding record, a new record is created.    *    * @param    string|int  Specifies the primary key.    * @param    array       Associative array containing key/values.    * @return   bool        True if successful, false otherwise    * @throws   Tyrant_Exception    */    public function putcat($key, Array $values)    {        $args = array($key);        foreach ($values as $ckey => $cvalue) {            $args[] = $ckey;            $args[] = $cvalue;        }        $rv = $this->misc('putcat', $args, 0);        if ($rv === false) {            throw new Tyrant_Exception("Put error");        }        return true;    }    /**    * Retrieve a record    * @param    int|string  Specifies the primary key.    * @return   array|false If successful, the return value is an    *                       associative array, false if no record were found.    */    public function get($key)    {        $args = array($key);        $rv = $this->misc('get', $args, Tyrant::MONOULOG);        if ($rv === false) {            $rnum = $this->_recvInt32();            return null;        }        $cols = array();        $cnum = count($rv) - 1;        $i = 0;        while ($i  $value) {            $cmd .= pack("N", strlen($key)) . $key;            $rnum++;        }        $cmd = pack("CCN", 0xC8, 0x31, $rnum) . $cmd;        $code = $this->_send($cmd);        if ($code !== 0) {            return false;        }        $rnum = $this->_recvInt32();        if ($rnum === false) {            return false;        }        $recs = array();        for ($i = 0; $i _recvInt32();            $vsiz = $this->_recvInt32();            if ($ksiz === false || $vsiz === false) {                return false;            }            $cols = array();            $kref = $this->_recv($ksiz);            $vref = $this->_recv($vsiz);            $cary = explode("\0", $vref);            $cnum = count($cary) - 1;            $j = 0;            while ($j misc('setindex', $args, 0);        if ($rv === false) {            throw new Tyrant_Exception("Could not set index on ".$name);        }        return true;    }    /**    * Generate a unique ID number    * @return   int   The new unique ID number    * @throws   Tyrant_Exception    */    public function genuid()    {        $rv = $this->misc('genuid', array());        if ($rv === false) {            throw new Tyrant_Exception("Could not generate a new unique ID");        }        return $rv[0];    }    /**    * Execute a search    * This method does never fail and return an empty array even    * if no record corresponds.    *    * @param    object  A Tyrant_Query object    * @return   array   Array of the primary keys of records found.    */    public function search(Tyrant_Query $query)    {        $rv = $this->misc("search", $query->args(), Tyrant::MONOULOG);        return empty($rv) ? array() : $rv;    }    /**    * Remove each corresponding records    *    * @param    object  A Tyrant_Query object    * @return bool True if successful, false otherwise    */    public function searchOut(Tyrant_Query $query)    {        $args = $query->args();        $args[] = "out";        $rv = $this->misc("search", $args, 0);        return empty($rv) ? array() : $rv;    }    /**    * Get records corresponding to the search of a query object    * The return value is an array of associative arrays with column of    * the corresponding records. This method does never fail and return    * an empty array even if no record corresponds.    * Due to the protocol restriction, this method can not handle records    * with binary columns including the "\0" chracter.    *    * @param    object  A Tyrant_Query object    * @param    string|array    Array of column names to be fetched.    *                           An empty string returns the primary key.    *                           If it is left null, every column is fetched.    * @return   array   Array of records found    */    public function searchGet(Tyrant_Query $query, $names = null)    {        $args = $query->args();        if (is_array($names)) {            $args[] = "get\0" . implode("\0", $names);        } else {            $args[] = "get";        }        $rv = $this->misc("search", $args, Tyrant::MONOULOG);        if (empty($rv)) {            return array();        }        foreach ($rv as $i => $v) {            $cols = array();            $cary = explode("\0", $v);            $cnum = count($cary) - 1;            $j = 0;            while ($j args();        $args[] = "count";        $rv = $this->misc("search", $args, Tyrant::MONOULOG);        return empty($rv) ? 0 : $rv[0];    }}

与Tyrant同级目录的文件

Tyrant.php

* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package    Tyrant* @author     Bertrand Mansion * @license    http://www.opensource.org/licenses/mit-license.php MIT License* @link       http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/Tyrant/Exception.php';/*** Factory for Tokyo Tyrant connections** @package    Tyrant* @author     Bertrand Mansion */class Tyrant{    /**    * Scripting extension option for record locking    */    const XOLCKREC = 1;    /**    * scripting extension option for global locking    */    const XOLCKGLB = 2;    /**    * Misc function option for omission of the update log    */    const MONOULOG = 1;    /**    * Restore function option for consistency checking    */    const ROCHKCON = 1;    /**    * Keeps track of the connection objects    * Makes it possible to easily reuse a connection.    * @var  array    */    protected static $connections = array();    /**    * Current connection object    * @var object    */    protected static $connection;    /**    * Opens a connection to a Tokyo Tyrant server    *     * try {    *     $tt = Tyrant::connect('localhost', 1978);    * } catch (Tyrant_Exception $e) {    *     echo $e->getMessage();    * }    *     *    * @param    string  Server hostname or IP address    * @param    string  Server port    * @param    string  Optional existing connection id    * @return   object  Database connection    */    public static function connect($host = 'localhost', $port = '1978', $id = 0)    {        $id = implode(':', array($host, $port, $id));                // Check if connection already exists                if (isset(self::$connections[$id])) {            $connection =& self::$connections[$id];            return $connection;        }        // Start a new connection        $ip = gethostbyname($host);        $addr = ip2long($ip);        if (empty($addr)) {            throw new Tyrant_Exception("Host not found");        }        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);        if (!is_resource($socket)){            throw new Tyrant_Exception("Connection refused");        }        if (!socket_connect($socket, $addr, $port)) {            throw new Tyrant_Exception("Connection refused");        }        if (defined('TCP_NODELAY')) {            socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1);        } else {            // See http://bugs.php.net/bug.php?id=46360            socket_set_option($socket, SOL_TCP, 1, 1);        }        // Determine the database type        if (socket_write($socket, pack('CC', 0xC8, 0x88)) === false) {            throw new Tyrant_Exception("Unable to get database type");        }        $str = '';        if (socket_recv($socket, $str, 1, 0) === false) {            throw new Tyrant_Exception("Unable to get database type");        }        $c = unpack("C", $str);        if (!isset($c[1]) || $c[1] !== 0) {            throw new Tyrant_Exception("Unable to get database type");        }        $str = '';        if (socket_recv($socket, $str, 4, 0) === false) {            throw new Tyrant_Exception("Unable to get database type");        }        $num = unpack("N", $str);        if (!isset($num[1])) {            throw new Tyrant_Exception("Unable to get database type");        }        $size = unpack("l", pack("l", $num[1]));        $len = $size[1];        $str = '';        if (socket_recv($socket, $str, $len, 0) === false) {            throw new Tyrant_Exception("Unable to get database type");        }        $value = explode("\n", trim($str));        $stats = array();        foreach ($value as $v) {            $v = explode("\t", $v);            $stats[$v[0]] = $v[1];        }        if (!isset($stats['type'])) {            throw new Tyrant_Exception("Unable to get database type");        }                // Get the right interface for the database type                if ($stats['type'] == 'table') {            include_once dirname(__FILE__).'/Tyrant/RDBTable.php';            $conn = new Tyrant_RDBTable($socket);        } else {            include_once dirname(__FILE__).'/Tyrant/RDB.php';            $conn = new Tyrant_RDB($socket);        }        self::$connections[$id] =& $conn;        self::$connection = $conn;        return $conn;    }    /**    * Return the current connection    * The current connection is set using Tyrant::setConnection() and    * defaults to the last connection made    *    * @return   object|null     First connection in the stack    */    public function getConnection()    {        return self::$connection;    }    /**    * Changes the current connection    * @param    string  Server hostname or IP address    * @param    string  Server port    * @param    string  Optional existing connection id    * @return   object|null     First connection in the stack    */    public function setConnection($host = 'localhost', $port = '1978', $id = 0)    {        $id = implode(':', array($host, $port, $id));        self::$connection =& self::$connections[$id];    }    /**    * Disconnects and removes a connection    * @param    string  Server hostname or IP address    * @param    string  Server port    * @param    string  Optional existing connection id    */    public function disconnect($host = 'localhost', $port = '1978', $id = 0)    {        $id = implode(':', array($host, $port, $id));        if (isset(self::$connections[$id])) {            $connection =& self::$connections[$id];            $connection->disconnect();            unset(self::$connections[$id]);            return true;        }        return false;    }}

cache的使用类

cache_ttserver.php

_conn = Tyrant::connect($host , $port);        $this->_query = new Tyrant_Query;    }    /**     * 写入一行记录     */    public function set($key , $value = null) {        $args_num = func_num_args();        if(is_array($key) && $args_num == 1) {            $values = $key;            foreach($values AS $_key => $_val) {                $this->_conn->put($_key , $_val);            }        } else {            return $this->_conn->put($key , $value);        }        return $this;    }        /**     * 读取一行记录     */    public function get($key) {        if(is_array($key)) {            $keys = $key;            $value = array();            foreach($keys AS $_key) {                $serialized_value = $this->_conn->get($_key);                $value[$_key] = $serialized_value;            }        } else {            $value = $this->_conn->get($key);        }        return $value;    }    /**     * 删除一行记录     */    public function remove($key) {        return $this->_conn->out($key);    }        /**     * 删除所有记录     */    public function removeAll() {        return $this->_conn->vanish();    }    /**     * 使用条件:TC HASH数据库     * 写入整形记录。若key存在,则更新记录,否则插入一条记录。     */    public function add($key , $increment) {        return $this->_conn->addInt($key , $increment);    }    /**     * 使用条件:TC TABLE数据库     * 获取一个连接对象遍历数据库中的所有键/值。     */    public function getIterator() {        return $this->_conn;    }    /**     * 获取记录数     */    public function rnum() {        return $this->_conn->rnum();    }        /**     * 使用条件:TC TABLE数据库     * 检索记录集,返回key     */    public function search() {        return $this->_conn->search($this->_query);    }        /**     * 使用条件:TC TABLE数据库     * 删除检索匹配的记录集     */    public function searchOut() {        return $this->_conn->searchOut($this->_query);    }        /**     * 使用条件:TC TABLE数据库     * 检索匹配的记录集,返回记录数组     */    public function searchGet($names = null) {        return $this->_conn->searchGet($this->_query, $names);    }        /**     * 使用条件:TC TABLE数据库     * 统计检索匹配的记录集个数     */    public function searchCount() {        return $this->_conn->searchCount($this->_query);    }}