## Tokyo Tyrant的PHP类

Tyrant文件夹里的文件

Common.php

<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * 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 <bmansion@mamasam.com>* @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 <bmansion@mamasam.com>*/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 < 0) {            $max = (1<<31); }$cmd = pack("CCNN", 0xC8, 0x58, strlen($prefix),$max) . $prefix;$code = $this->_send($cmd);        if ($code !== 0) { return$keys;        }        $knum =$this->_recvInt32();        if ($knum === false) { return$keys;        }        for ($i = 0;$i < $knum;$i++) {            $ksiz =$this->_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 <$rnum; $i++) {$esiz = $this->_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 < 0) {            return false;        }        $vbuf =$this->_recv($vsiz); return$vbuf;    }    protected function _socketWrite($cmd) {$len = strlen($cmd);$offset = 0;        while ($offset <$len) {            $sent = socket_write($this->socket, substr($cmd,$offset), $len-$offset);            if ($sent === false) { return false; }$offset += $sent; } return ($offset < $len) ? false : true; } protected function _send($cmd)    {        $status =$this->_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 < 1) {            return "";        }        $str = ""; if (($rec = socket_recv($this->socket,$str, $len, 0)) <= 0) { return false; } if (strlen($str) == $len) { return$str;        }        $len -= strlen($str);        while ($len > 0) {$tstr = "";            if (($rec = socket_recv($this->socket, $tstr,$len, 0)) <= 0) {                return false;            }            $len -= strlen($tstr);            $str .=$tstr;        }        return $str; } protected function _recvCode() { if (($rbuf = $this->_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 < 0 ? -1 : 0, $v); } // x32, bcmath if (function_exists("bcmul")) { if (bccomp($v, 0) == -1) {                $v = bcadd("18446744073709551616",$v);            }            $h = bcdiv($v, "4294967296", 0);            $l = bcmod($v, "4294967296");            return pack ("NN", (float)$h, (float)$l); // conversion to float is intentional; int would lose 31st bit        }        // x32, no-bcmath        $p = max(0, strlen($v) - 13);        $lo = abs((float)substr($v, $p));$hi = abs((float)substr($v, 0,$p));        $m =$lo + $hi*1316134912.0; // (10 ^ 13) % (1 << 32) = 1316134912$q = floor($m/4294967296.0);$l = $m - ($q*4294967296.0);        $h =$hi*2328.0 + $q; // (10 ^ 13) / (1 << 32) = 2328 if ($v < 0) {            if ($l == 0) {$h = 4294967296.0 - $h; } else {$h = 4294967295.0 - $h;$l = 4294967296.0 - $l; } } return pack("NN",$h, $l); } /** * Portability function to unpack a x64 value with PHP limitations * @return mixed Might return a string of numbers or the actual value */ protected function _unpack64($v)    {        list($hi,$lo) = array_values (unpack("N*N*", $v)); // x64 if (PHP_INT_SIZE >= 8) { if ($hi < 0) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again if ($lo < 0) $lo += (1<<32); return ($hi<<32) + $lo; } // x32, int if ($hi == 0) {            if ($lo > 0) { return$lo;            }            return sprintf("%u", $lo); } elseif ($hi == -1) {            // x32, int            if ($lo < 0) { return$lo;            }            return sprintf("%.0f", $lo - 4294967296.0); }$neg = "";        $c = 0; if ($hi < 0) {            $hi = ~$hi;            $lo = ~$lo;            $c = 1;$neg = "-";        }        $hi = sprintf ("%u",$hi);        $lo = sprintf ("%u",$lo);        // x32, bcmath        if (function_exists("bcmul")) {            return $neg . bcadd(bcadd($lo, bcmul($hi, "4294967296")),$c);        }        // x32, no-bcmath        $hi = (float)$hi;        $lo = (float)$lo;        $q = floor($hi/10000000.0);        $r =$hi - $q*10000000.0;$m = $lo +$r*4967296.0;        $mq = floor($m/10000000.0);        $l =$m - $mq*10000000.0 +$c;        $h =$q*4294967296.0 + $r*429.0 +$mq;        $h = sprintf("%.0f",$h);        $l = sprintf("%07.0f",$l);        if ($h == "0") { return$neg . sprintf("%.0f", (float)$l); } return$neg . $h .$l;    }    /**    * Store the current iterator key or false if no key is available    * @var string    */    protected $_current; /** * Rewind the Iterator to the first element. * Similar to the reset() function for arrays in PHP * @return void */ public function rewind() {$this->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 <?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * 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 <bmansion@mamasam.com>* @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 <?php/*** Tokyo Tyrant network API for PHP** Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>** 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 <bmansion@mamasam.com>* @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 <bmansion@mamasam.com>*/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

<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * 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 <bmansion@mamasam.com>* @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 <bmansion@mamasam.com>*/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 < 0 ? 0 : (int)$width;$cmd = pack('CCNNN', 0xC8, 0x13, strlen($key), strlen($value), $width) .$key . $value;$code = $this->_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 < $rnum;$i++) {            $ksiz =$this->_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 <?php/*** Tokyo Tyrant network API for PHP** Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>** 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 <bmansion@mamasam.com>* @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 <bmansion@mamasam.com>*/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 << 24 /** * Store a record * If a record with the same key exists in the database, * it is overwritten. * * @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 put($key, $value) {$args = array($key); foreach ($value as $ckey =>$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 < $cnum) {$cols[$rv[$i]] = $rv[$i+1];            $i += 2; } return$cols;    }    /**    * Retrieve records    * Due to the protocol restriction, this method can not handle records    * with binary columns including the "\0" chracter.    *    * @param    array   Associative array containing the primary keys.    *                   As a result of this method, keys existing in the    *                   database have the corresponding columns and keys    *                   not existing in the database are removed.    * @return   int|false   If successful, the return value is the number of    *                       records found. False if none found.    */    public function mget(Array &$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 <$rnum; $i++) {$ksiz = $this->_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 < $cnum) {$cols[$cary[$j]] = $cary[$j+1];                $j += 2; }$recs[$kref] =$cols;        }        return $rnum; } /** * Set a column index * @param string Name of a column. * If the name of an existing index is specified, * the index is rebuilt. An empty string means the * primary key. * @param int Specifies the index type: * - Tyrant_RDBTable::ITLEXICAL for lexical string * - Tyrant_RDBTable::ITDECIMAL for decimal string * - Tyrant::ITOPT for optimizing the index * - tyrant_RDBTable::ITVOID for removing the index * If Tyrant_RDBTable::ITKEEP is added by bitwise-or and * the index exists, this method merely returns failure. * * @return bool True if successful * @throws Tyrant_Exception */ public function setindex($name, $type) {$args = array($name,$type);        $rv =$this->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 < $cnum) {$cols[$cary[$j]] = $cary[$j+1];                $j += 2; }$rv[$i] =$cols;        }        return $rv; } /** * Get the count of corresponding records * * @param object A Tyrant_Query object * @return int Count of corresponding records or 0 on failure */ public function searchCount(Tyrant_Query$query)    {        $args =$query->args();        $args[] = "count";$rv = $this->misc("search",$args, Tyrant::MONOULOG);        return empty($rv) ? 0 :$rv[0];    }}

Tyrant.php

<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * 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 <bmansion@mamasam.com>* @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 <bmansion@mamasam.com>*/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    * <code>    * try {    *     $tt = Tyrant::connect('localhost', 1978); * } catch (Tyrant_Exception$e) {    *     echo $e->getMessage(); * } * </code> * * @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

<?php/** * TokyoCabinet数据库操作类 */require_once EXTENTION_PATH.'ttserver/Tyrant.php';require_once EXTENTION_PATH.'ttserver/Tyrant/Query.php';class cache_ttserver {    private $_conn = null; public$_query = object;    /**     * 构造函数-创建TTSERVER连接对象     */    public function __construct($host ,$port) {        $this->_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);    }}`

posted on 2011-11-24 20:34 kudosharry 阅读(...) 评论(...)  编辑 收藏

• 随笔 - 68
• 文章 - 234
• 评论 - 7
• 引用 - 0