Diffs
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/HTTP/TsvRpc/Parser.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * TSV-RPC parser.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use HTTP\TsvRpc
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/lib/TSVRPC/Parser.pm
+ */
+
+namespace HTTP\TsvRpc;
+use HTTP\TsvRpc;
+
+/**
+ * TSV-RPC parser.
+ *
+ * <pre>
+ * This module is port from Perl TSVRPC::Parser
+ * See also @link.
+ * </pre>
+ *
+ * @use HTTP\TsvRpc
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/lib/TSVRPC/Parser.pm
+ */
+class Parser
+{
+ /**
+ * Encode plain array to TSV with $encoding.
+ *
+ * @param array $data Array data to encode
+ * @param mixed $encoding Encode type
+ * @access public
+ * @return String Encoded string
+ */
+ public function encodeTsvrpc(array $data, $encoding = null)
+ {
+ $encoders = array(
+ 'U' => function($value) { return urlencode($value); },
+ 'Q' => function($value) { return quoted_printable_encode($value); },
+ 'B' => function($value) { return base64_encode($value); }
+ );
+
+ if (isset($encoders[$encoding])) {
+ $encoder = $encoders[$encoding];
+ } else {
+ // When $encoding is not in $encoders, nothing to do.
+ $encoder = function($value) { return $value; };
+ }
+ $res = array();
+ foreach ($data as $k => $v) {
+ $res[] = $encoder($k) . "\t" . $encoder($v);
+ }
+
+ return implode("\n", $res);
+ }
+
+ /**
+ * Decode TSV to plain array.
+ *
+ * @param mixed $data String data to decode
+ * @param mixed $encoding Encode type
+ * @access public
+ * @return array Decoded data
+ */
+ public function decodeTsvrpc($data, $encoding = null)
+ {
+ $decoders = array(
+ 'U' => function($value) { return urldecode($value); },
+ 'Q' => function($value) { return quoted_printable_decode($value); },
+ 'B' => function($value) { return base64_decode($value); }
+ );
+
+ if (isset($decoders[$encoding])) {
+ $decoder = $decoders[$encoding];
+ } else {
+ // When $encoding is not in $decoders, nothing to do.
+ $decoder = function($value) { return $value; };
+ }
+ $res = array();
+ if ($data === '') {
+ return $res;
+ }
+
+ $lines = explode("\n", $data);
+ foreach ($lines as $line) {
+ if ($line === '') {
+ continue;
+ }
+
+ list($k, $v) = array_map($decoder, explode("\t", $line));
+ $res[$k] = $v;
+ }
+
+ return $res;
+ }
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/HTTP/TsvRpc/Util.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * TSV-RPC util.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use HTTP\TsvRpc
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/lib/TSVRPC/Parser.pm
+ */
+
+namespace HTTP\TsvRpc;
+use HTTP\TsvRpc;
+
+/**
+ * TSV-RPC util.
+ *
+ * <pre>
+ * This module is port from Perl TSVRPC::Parser
+ * See also @link.
+ * </pre>
+ *
+ * @use HTTP\TsvRpc
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/lib/TSVRPC/Parser.pm
+ */
+class Util
+{
+ /**
+ * Parse content-type.
+ *
+ * @param mixed $contentType Content-type
+ * @access public
+ * @return mixed B|U|Q|'' or null
+ */
+ public static function parseContentType($contentType)
+ {
+ $pattern = '#text/tab-separated-values(?:; colenc=([BUQ]))?#';
+ if (preg_match_all($pattern, $contentType, $match)) {
+ return isset($match[1][0]) ? $match[1][0] : '';
+ }
+
+ return null;
+ }
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/HTTP/TsvRpc/Client.php
@@ -0,0 +1,223 @@
+<?php
+/**
+ * TSV-RPC client library.
+ *
+ * This module is port from Perl Cache::KyotoTycoon.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use HTTP\TsvRpc\Parser
+ * @use HTTP\TsvRpc\Util
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+
+namespace HTTP\TsvRpc;
+use HTTP\TsvRpc\Parser,
+ HTTP\TsvRpc\Util,
+ HTTP\TsvRpc\Exception;
+
+/**
+ * Client
+ *
+ * <pre>
+ * This module is port from Perl Cache::KyotoTycoon.
+ * See also @link.
+ * </pre>
+ *
+ * @use HTTP\TsvRpc\Parser
+ * @use HTTP\TsvRpc\Util
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+class Client
+{
+ /**
+ * Version.
+ */
+ const VERSION = '0.0.3';
+
+ /**
+ * Base url.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_base = null;
+
+ /**
+ * HTTP Client.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_client = null;
+
+ /**
+ * Content-Type parser.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_parser = null;
+
+ /**
+ * Last content data.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_lastContent = null;
+
+ /**
+ * Constructor
+ *
+ * @param array $args
+ * @access public
+ * @return void
+ */
+ public function __construct(array $args)
+ {
+ spl_autoload_register(array(__CLASS__, 'autoload'));
+ $base = '';
+ if (isset($args['base'])) {
+ $base = $args['base'];
+ } else {
+ throw new Exception("Missing argument named 'base' for rpc base url.");
+ }
+ $base = rtrim($base, '\//') . '/';
+ $timeout = isset($args['timeout']) ? $args['timeout'] : 1;
+ $agent = isset($args['agent']) ?: __CLASS__ . '/' . self::VERSION;
+
+ $adapter = isset($args['adapter']) ?: 'HTTP_Request2_Adapter_Socket';
+ $config = array('adapter' => $adapter, 'timeout' => $timeout);
+ $client = new \HTTP_Request2(
+ null, \HTTP_Request2::METHOD_POST, $config
+ );
+ $client->setHeader('user-agent', $agent);
+
+ $this->_client = $client;
+ $this->_base = $base;
+ $this->_parser = new Parser();
+ }
+
+ /**
+ * Send request.
+ *
+ * @param mixed $method Rpc method
+ * @param mixed $args Args
+ * @param string $encoding B(base64), U(Urlencode), Q(Quoted printable)
+ * @access public
+ * @return mixed Status code and HTTP body
+ */
+ public function call($method, $args = array(), $encoding = 'B')
+ {
+ $content = $this->_parser->encodeTsvrpc($args, $encoding);
+ $client = $this->_client;
+ $uri = $this->_base . $method;
+ $headers = array(
+ 'Content-Type' => "text/tab-separated-values; colenc=$encoding",
+ 'Content-Length' => strlen($content),
+ 'Connection' => 'Keep-Alive',
+ 'Keep-Alive' => 300,
+ );
+ $client->setHeader($headers)->setUrl($uri)->setBody($content);
+ $response = $client->send();
+ if ($response) {
+ $code = $response->getStatus();
+ $responseHeaders = $response->getHeader();
+ $contentType = $responseHeaders['content-type'];
+ $resEncoding = Util::parseContentType($contentType);
+
+ // Decode by content-type B|Q|U
+ $body = $this->_parser->decodeTsvrpc(
+ $response->getBody(), $resEncoding
+ );
+ $this->_lastContent = $body;
+ return array('code' => $code, 'body' => $body);
+ }
+
+ throw new Exception('Fail to call ' . $uri);
+ }
+
+ /**
+ * Get last content.
+ *
+ * <pre>
+ * This is a debug method.
+ * </pre>
+ *
+ * @access public
+ * @return mixed
+ */
+ public function getLastContent()
+ {
+ return $this->_lastContent;
+ }
+
+ /**
+ * Autoload class.
+ *
+ * @param mixed $class
+ * @access public
+ * @return void
+ */
+ public static function autoload($className)
+ {
+ // Autoload class.
+ // http://groups.google.com/group/php-standards/web/psr-0-final-proposal
+ if (!class_exists($className, false)) {
+ $className = ltrim($className, '\\');
+ $fileName = '';
+ $namespace = '';
+ if ($lastNsPos = strripos($className, '\\')) {
+ $namespace = substr($className, 0, $lastNsPos);
+ $className = substr($className, $lastNsPos + 1);
+ $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+ }
+ $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
+ require_once $fileName;
+ }
+ }
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/HTTP/TsvRpc/Exception.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Exception for \HTTP\TsvRpc.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use HTTP\TsvRpc
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ */
+
+namespace HTTP\TsvRpc;
+
+/**
+ * Exception.
+ *
+ * @use HTTP\TsvRpc
+ * @category HTTP
+ * @package HTTP\TsvRpc
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ */
+class Exception extends \Exception
+{
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/Net/KyotoTycoon/Cursor.php
@@ -0,0 +1,399 @@
+<?php
+/**
+ * Cursor class for KyotoTycoon.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use Net\KyotoTycoon
+ * @category Net
+ * @package Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+
+namespace Net\KyotoTycoon;
+use Net\KyotoTycoon;
+
+/**
+ * Cursor class for KyotoTycoon.
+ *
+ * <pre>
+ * This module is port from Perl Cache::KyotoTycoon.
+ * See also @link.
+ * </pre>
+ *
+ * @use Net\KyotoTycoon
+ * @category Net
+ * @package Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+
+ */
+class Cursor
+{
+ /**
+ * Db.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_db = null;
+
+ /**
+ * Cursor.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_cursor = null;
+
+ /**
+ * Client.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_client = null;
+
+ /**
+ * Status Code.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_statusCode = null;
+
+ /**
+ * Construct.
+ *
+ * @param mixed $id
+ * @param mixed $db
+ * @param mixed $client
+ * @access public
+ * @return void
+ */
+ public function __construct($id, $db, $client)
+ {
+ $this->_db = $db;
+ $this->_client = $client;
+ $this->_cursor = $id;
+
+ // Status code.
+ $this->_statusCode = new StatusCode();
+ }
+
+ /**
+ * Get error message.
+ *
+ * @param mixed $code Status code
+ * @access private
+ * @return String Error message
+ */
+ private function _errmsg($code)
+ {
+ return $this->_statusCode->errmsg($code);
+ }
+
+ /**
+ * Call jump.
+ *
+ * <pre>
+ * Jump the cursor to the first record for forward scan.
+ * </pre>
+ *
+ * @param mixed $key
+ * @access public
+ * @return mixed
+ */
+ public function jump($key = null)
+ {
+ $args = array('DB' => $this->_db, 'CUR' => $this->_cursor);
+ if (!is_null($key)) {
+ $args['key'] = $key;
+ }
+ $response = $this->_client->call('cur_jump', $args);
+
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call jump_back.
+ *
+ * <pre>
+ * Jump the cursor to the last record for backward scan.
+ * </pre>
+ *
+ * @param mixed $key
+ * @access public
+ * @return mixed
+ */
+ public function jumpBack($key = null)
+ {
+ $args = array('DB' => $this->_db, 'CUR' => $this->_cursor);
+ if (!is_null($key)) {
+ $args['key'] = $key;
+ }
+ $response = $this->_client->call('cur_jump_back', $args);
+
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call step.
+ *
+ * <pre>
+ * Step the cursor to the next record.
+ * </pre>
+ *
+ * @access public
+ * @return mixed
+ */
+ public function step()
+ {
+ $args = array('CUR' => $this->_cursor);
+ $response = $this->_client->call('cur_step', $args);
+
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call step_back.
+ *
+ * <pre>
+ * Step the cursor to the previous record.
+ * </pre>
+ *
+ * @access public
+ * @return mixed
+ */
+ public function stepBack()
+ {
+ $args = array('CUR' => $this->_cursor);
+ $response = array('code' => 0, 'body' => null);
+ $response = $this->_client->call('cur_step_back', $args);
+
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call set_value.
+ *
+ * <pre>
+ * Set the value of the current record.
+ * </pre>
+ *
+ * @param mixed $value
+ * @param mixed $xt
+ * @param mixed $step
+ * @access public
+ * @return mixed
+ */
+ public function setValue($value, $xt = null, $step = null)
+ {
+ $args = array('CUR' => $this->_cursor, 'value' => $value);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+ if (!is_null($step)) {
+ $args['step'] = '';
+ }
+
+ $response = $this->_client->call('cur_set_value', $args);
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call remove.
+ *
+ * <pre>
+ * Remove the current record.
+ * </pre>
+ *
+ * @access public
+ * @return mixed
+ */
+ public function remove()
+ {
+ $args = array('CUR' => $this->_cursor);
+ $response = $this->_client->call('cur_remove', $args);
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call get_key.
+ *
+ * <pre>
+ * Get the key of the current record.
+ * </pre>
+ *
+ * @param mixed $step
+ * @access public
+ * @return mixed
+ */
+ public function getKey($step = null)
+ {
+ $args = array('CUR' => $this->_cursor);
+ if (!is_null($step)) {
+ $args['step'] = '';
+ }
+ $response = $this->_client->call('cur_get_key', $args);
+
+ if ($response['code'] === 200) {
+ return $response['body']['key'];
+ } else if ($response['code'] === 450) {
+ return null;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call get_value.
+ *
+ * <pre>
+ * Get the value of the current record.
+ * </pre>
+ *
+ * @param mixed $step
+ * @access public
+ * @return mixed
+ */
+ public function getValue($step = null)
+ {
+ $args = array('CUR' => $this->_cursor);
+ if (!is_null($step)) {
+ $args['step'] = '';
+ }
+ $response = $this->_client->call('cur_get_value', $args);
+
+ if ($response['code'] === 200) {
+ return $response['body']['value'];
+ } else if ($response['code'] === 450) {
+ return null;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call get.
+ *
+ * <pre>
+ * Get a pair of the key and the value of the current record.
+ * </pre>
+ *
+ * @param mixed $step
+ * @access public
+ * @return mixed
+ */
+ public function get($step = null)
+ {
+ $args = array('CUR' => $this->_cursor);
+ if (!is_null($step)) {
+ $args['step'] = '';
+ }
+
+ $response = $this->_client->call('cur_get', $args);
+ if ($response['code'] === 200) {
+ return array($response['body']['key'], $response['body']['value']);
+ } else if ($response['code'] === 450) {
+ return null;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call delete.
+ *
+ * <pre>
+ * Delete the cursor immidiately.
+ * </pre>
+ *
+ * @access public
+ * @return mixed Fluent interface or error message.
+ */
+ public function delete()
+ {
+ $args = array('CUR' => $this->_cursor);
+ $response = $this->_client->call('cur_delete', $args);
+ if ($response['code'] === 200) {
+ return $this;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/Net/KyotoTycoon/Exception.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Exception for \Net\KyotoTycoon.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use Net
+ * @use KyotoTycoon
+ * @category Net
+ * @package \Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ */
+
+namespace Net\KyotoTycoon;
+use Net,
+ KyotoTycoon;
+
+/**
+ * Exception.
+ *
+ * @use Net
+ * @use KyotoTycoon
+ * @category Net
+ * @package \Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ */
+class Exception extends \Exception
+{
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/Net/KyotoTycoon/StatusCode.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Status code for \Net\KyotoTycoon.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use Net\KyotoTycoon
+ * @category Net
+ * @package Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+
+namespace Net\KyotoTycoon;
+use Net\KyotoTycoon;
+
+/**
+ * StatusCode
+ *
+ * @use Net\KyotoTycoon
+ * @category Net
+ * @package Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+class StatusCode
+{
+ /**
+ * Status code.
+ *
+ * @var array
+ * @access private
+ */
+ private $_statusCode = array(
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+ 102 => 'Processing', // RFC 2518 (WebDAV)
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+ 207 => 'Multi-Status', // RFC 2518 (WebDAV)
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Large',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Request Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity', // RFC 2518 (WebDAV)
+ 423 => 'Locked', // RFC 2518 (WebDAV)
+ 424 => 'Failed Dependency', // RFC 2518 (WebDAV)
+ 425 => 'No code', // WebDAV Advanced Collections
+ 426 => 'Upgrade Required', // RFC 2817
+ 449 => 'Retry with', // unofficial Microsoft
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ 506 => 'Variant Also Negotiates', // RFC 2295
+ 507 => 'Insufficient Storage', // RFC 2518 (WebDAV)
+ 509 => 'Bandwidth Limit Exceeded', // unofficial
+ 510 => 'Not Extended', // RFC 2774
+ );
+
+ /**
+ * Error message.
+ *
+ * @param mixed $code Status code
+ * @access private
+ * @return String Error message
+ */
+ public function errmsg($code)
+ {
+ $msg = isset($this->_statusCode[$code]) ?: 'Unknown';
+ return sprintf(
+ 'Net\KyotoTycoon unexpected response code: %s %s', $code, $msg
+ );
+ }
+}
Net_KyotoTycoon/tags/release-0.0.1-20101109223903/Net/KyotoTycoon.php
@@ -0,0 +1,735 @@
+<?php
+/**
+ * KyotoTycoon client library.
+ *
+ * PHP version 5.3
+ *
+ * Copyright (c) 2010 Shinya Ohyanagi, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Shinya Ohyanagi nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @use Net
+ * @category Net
+ * @package Net\KyotoTycoon
+ * @version $id$
+ * @copyright (c) 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://fallabs.com/kyototycoon/
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+namespace Net;
+use Net\KyotoTycoon\StatusCode,
+ Net\KyotoTycoon\Exception,
+ Net\KyotoTycoon\Cursor,
+ HTTP\TsvRpc\Client;
+
+/**
+ * KyotoTycoon
+ *
+ * <pre>
+ * This module is port from Perl Cache::KyotoTycoon.
+ * See also @link.
+ * </pre>
+ *
+ * @use Net
+ * @category Net
+ * @package Net\KyotoTycoon
+ * @version $id$
+ * @copyright 2010 Shinya Ohyanagi
+ * @author Shinya Ohyanagi <sohyanagi@gmail.com>
+ * @license New BSD License
+ * @link http://fallabs.com/kyototycoon/
+ * @link http://search.cpan.org/~tokuhirom/Cache-KyotoTycoon/
+ */
+class KyotoTycoon
+{
+ /**
+ * Version.
+ */
+ const VERSION = '0.0.1';
+
+ /**
+ * Status code.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_statusCode = null;
+
+ /**
+ * Client.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_client = null;
+
+ /**
+ * Db.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $_db = null;
+
+ /**
+ * Error message.
+ *
+ * @param mixed $code Status code.
+ * @access private
+ * @return String Error message.
+ */
+ private function _errmsg($code)
+ {
+ return $this->_statusCode->errmsg($code);
+ }
+
+ /**
+ * Create client to access KyotoTycoon.
+ *
+ * @param array $args
+ * @access public
+ * @return void
+ */
+ public function __construct(array $args = array())
+ {
+ spl_autoload_register(array(__CLASS__, 'autoload'));
+ $host = isset($args['host']) ? $args['host'] : '127.0.0.1';
+ $port = isset($args['port']) ? $args['port'] : 1978;
+ $base = "http://$host:$port/rpc/";
+ $timeout = isset($args['timeout']) ? $args['timeout'] : 1;
+ $client = new Client(
+ array(
+ 'timeout' => $timeout,
+ 'base' => $base
+ )
+ );
+
+ $this->_db = 0;
+ $this->_client = $client;
+ $this->_statusCode = new StatusCode();
+ }
+
+ /**
+ * Set TSV-RPC client.
+ *
+ * @param mixed $client TSV-RPC client
+ * @access public
+ * @return \Net\KyotoTycoon Fluent interface
+ */
+ public function setClient($client)
+ {
+ $this->_client = $client;
+ return $this;
+ }
+
+ /**
+ * Set db.
+ *
+ * @param mixed $db
+ * @access public
+ * @return \Net\KyotoTycoon Fluent interface.
+ */
+ public function db($db)
+ {
+ $this->_db = $db;
+ return $this;
+ }
+
+ /**
+ * Make cursor
+ *
+ * @param mixed $id
+ * @access public
+ * @return \Net\KyotoTycoon\Cursor
+ */
+ public function makeCursor($id)
+ {
+ $cursor = new Cursor($id, $this->_db, $this->_client);
+ return $cursor;
+ }
+
+ /**
+ * Call echo.
+ *
+ * <pre>
+ * Echo back the input data as the output data
+ * echo() is reserved name in PHP. This method is same as echo().
+ * </pre>
+ *
+ * @param mixed $args
+ * @access public
+ * @return mixed Response of RPC call
+ */
+ public function echoBack($args)
+ {
+ $response = $this->_client->call('echo', $args);
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return $response['body'];
+ }
+
+ /**
+ * Call report.
+ *
+ * <pre>
+ * Get the report of the server information.
+ * </pre>
+ *
+ * @access public
+ * @return mixed Response of RPC call
+ */
+ public function report()
+ {
+ $response = $this->_client->call('report');
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return $response['body'];
+ }
+
+ /**
+ * Call play_script.
+ *
+ * <pre>
+ * Call a procedure of the scripting extension.
+ * </pre>
+ *
+ * @param mixed $name
+ * @param array $input
+ * @access public
+ * @return mixed Response of RPC call
+ */
+ public function playScript($name, array $input)
+ {
+ $args = array('name' => $name);
+ foreach ($input as $k => $v) {
+ $args["_$k"] = $v;
+ }
+ $response = $this->_client->call('play_script', $args);
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+ $body = $response['body'];
+ $res = array();
+ foreach ($body as $k => $v) {
+ $res[ltrim($k, '_')] = $v;
+ }
+
+ return $res;
+ }
+
+ /**
+ * Call status.
+ *
+ * <pre>
+ * Get the miscellaneous status information.
+ * </pre>
+ *
+ * @access public
+ * @return mixed Response of RPC call
+ */
+ public function status()
+ {
+ $response = $this->_client->call('status', array('DB' => $this->_db));
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return $response['body'];
+ }
+
+ /**
+ * Call clear
+ *
+ * <pre>
+ * Remove all records.
+ * </pre>
+ *
+ * @access public
+ * @return mixed Fluent interface when clear success or error message.
+ */
+ public function clear()
+ {
+ $response = $this->_client->call('clear', array('DB' => $this->_db));
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Call synchronize
+ *
+ * <pre>
+ * Synchronize updated contents with the file and the device.
+ * </pre>
+ *
+ * @param mixed $hard
+ * @param mixed $command
+ * @access public
+ * @return mixed Status 200 return true, status 450 return false
+ */
+ public function synchronize($hard = null, $command = null)
+ {
+ $args = array('DB' => $this->_db);
+ $args['hard'] = $hard;
+ if (!is_null($command)) {
+ $args['command'] = $command;
+ }
+
+ $response = $this->_client->call('synchronize', $args);
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call set.
+ *
+ * <pre>
+ * Set the value of a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @param mixed $xt
+ * @access public
+ * @return mixed Fluent interface or error message
+ */
+ public function set($key, $value, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key, 'value' => $value);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+
+ $response = $this->_client->call('set', $args);
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Call add.
+ *
+ * <pre>
+ * Add a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @param mixed $xt
+ * @access public
+ * @return mixed true:Success to add, false: Fail to add or error message
+ */
+ public function add($key, $value, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key, 'value' => $value);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+
+ $response = $this->_client->call('add', $args);
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call replace.
+ *
+ * <pre>
+ * Replace a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @param mixed $xt
+ * @access public
+ * @return mixed True:success, False:fail or error message.
+ */
+ public function replace($key, $value, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key, 'value' => $value);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+
+ $response = $this->_client->call('replace', $args);
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ return $this->_errmsg($response['code']);
+ }
+
+ /**
+ * Call append.
+ *
+ * <pre>
+ * Set the value of a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @param mixed $xt
+ * @access public
+ * @return mixed Fluent interface or error message
+ */
+ public function append($key, $value, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key, 'value' => $value);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+ $response = $this->_client->call('append', $args);
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Call increment.
+ *
+ * <pre>
+ * Add a number to the numeric integer value of a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $num
+ * @param mixed $xt
+ * @access public
+ * @return mixed Response of RPC call
+ */
+ public function increment($key, $num, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key, 'num' => $num);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+ $response = $this->_client->call('increment', $args);
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return intval($response['body']['num']);
+ }
+
+ /**
+ * Call incrementDouble.
+ *
+ * <pre>
+ * Add a number to the numeric double value of a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $num
+ * @param mixed $xt
+ * @access public
+ * @return mixed Response of RPC call
+ */
+ public function incrementDouble($key, $num, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key, 'num' => $num);
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+ $response = $this->_client->call('increment_double', $args);
+ if ($response['code'] !== 200) {
+ return $this->_errmsg($response['code']);
+ }
+
+ return doubleval($response['body']['num']);
+ }
+
+ /**
+ * Call cas.
+ *
+ * <pre>
+ * Perform compare-and-swap.
+ * </pre>
+ *
+ * @param mixed $key
+ * @param mixed $oval
+ * @param mixed $nval
+ * @param mixed $xt
+ * @access public
+ * @throws \Net\KyotoTycoon\Exception
+ * @return Bool True: Status code is 200, False: Status code is 450
+ */
+ public function cas($key, $oval = null, $nval = null, $xt = null)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key);
+ $list = array('oval' => $oval, 'nval' => $nval, 'xt' => $xt);
+
+ foreach ($list as $k => $v) {
+ if (!is_null($v)) {
+ $args[$k] = $v;
+ }
+ }
+ $response = $this->_client->call('cas', $args);
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ throw new Exception($this->_errmsg($response['code']));
+ }
+
+ /**
+ * Call remove.
+ *
+ * <pre>
+ * Remove a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @access public
+ * @throws \Net\KyotoTycoon\Exception
+ * @return Bool True: Status code is 200, False: Status code is 450.
+ */
+ public function remove($key)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key);
+ $response = $this->_client->call('remove', $args);
+
+ if ($response['code'] === 200) {
+ return true;
+ } else if ($response['code'] === 450) {
+ return false;
+ }
+
+ throw new Exception($this->_errmsg($response['code']));
+ }
+
+ /**
+ * Call get.
+ *
+ * <pre>
+ * Retrieve the value of a record.
+ * </pre>
+ *
+ * @param mixed $key
+ * @access public
+ * @throws \Net\KyotoTycoon\Exception
+ * @return mixed Response of RPC call
+ */
+ public function get($key)
+ {
+ $args = array('DB' => $this->_db, 'key' => $key);
+ $response = $this->_client->call('get', $args);
+
+ if ($response['code'] === 200) {
+ return $response['body']['value'];
+ } else if ($response['code'] === 450) {
+ return null;
+ }
+
+ throw new Exception($this->_errmsg($response['code']));
+ }
+
+ /**
+ * Call set_bulk.
+ *
+ * <pre>
+ * Store records at once.
+ * </pre>
+ *
+ * @param array $vals
+ * @param mixed $xt
+ * @access public
+ * @throws \Net\KyotoTycoon\Exception
+ * @return mixed Response of RPC call
+ */
+ public function setBulk(array $vals, $xt = null)
+ {
+ $args = array('DB' => $this->_db);
+ foreach ($vals as $k => $v) {
+ $args["_$k"] = $v;
+ }
+ if (!is_null($xt)) {
+ $args['xt'] = $xt;
+ }
+ $response = $this->_client->call('set_bulk', $args);
+ if ($response['code'] !== 200) {
+ throw new Exception($this->_errmsg($response['code']));
+ }
+
+ return intval($response['body']['num']);
+ }
+
+ /**
+ * Call remove_bulk.
+ *
+ * <pre>
+ * Store records at once.
+ * </pre>
+ *
+ * @param mixed $keys
+ * @access public
+ * @throws \Net\KyotoTycoon\Exception
+ * @return mixed
+ */
+ public function removeBulk($keys)
+ {
+ $args = array('DB' => $this->_db);
+ foreach ($keys as $k => $v) {
+ $args["_$k"] = '';
+ }
+
+ $response = $this->_client->call('remove_bulk', $args);
+ if ($response['code'] !== 200) {
+ throw new Exception($this->_errmsg($response['code']));
+ }
+
+ return intval($response['body']['num']);
+ }
+
+ /**
+ * Call get_bulk.
+ *
+ * <pre>
+ * Retrieve records at once.
+ * </pre>
+ *
+ * @param array $keys
+ * @access public
+ * @throws \Net\KyotoTycoon\Exception
+ * @return mixed Response of RPC call
+ */
+ public function getBulk(array $keys)
+ {
+ $args = array('DB' => $this->_db);
+ foreach ($keys as $k) {
+ $args["_$k"] = '';
+ }
+
+ $response = $this->_client->call('get_bulk', $args);
+ if ($response['code'] !== 200) {
+ throw new Exception($this->_errmsg($response['code']));
+ }
+ $body = $response['body'];
+ $ret = array();
+ foreach ($body as $k => $v) {
+ if (preg_match('/^_(.+)$/', $k, $match)) {
+ $ret[$match[1]] = $v;
+ }
+ }
+
+ if (intval($body['num']) !== count($ret)) {
+ throw new Exception('Fatal error');
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Call vacuum.
+ *
+ * <pre>
+ * Scan the database and eliminate regions of expired records.
+ * </pre>
+ *
+ * @param mixed $step
+ * @access public
+ * @return \Net\KyotoTycoon Fluent interface.
+ */
+ public function vacuum($step = null)
+ {
+ $args = array('DB' => $this->_db);
+ if (!is_null($step)) {
+ $args['step'] = $step;
+ }
+ $response = $this->_client->call('vacuum', $args);
+ if ($response['code'] !== 200) {
+ throw new Exception($this->_errmsg($response['code']));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get last content.
+ *
+ * @access public
+ * @return mixed Last content or null
+ */
+ public function getLastContent()
+ {
+ return $this->_client->getLastContent();
+ }
+
+ /**
+ * Autoload class.
+ *
+ * @param mixed $class
+ * @access public
+ * @return void
+ */
+ public static function autoload($className)
+ {
+ // Autoload class.
+ // http://groups.google.com/group/php-standards/web/psr-0-final-proposal
+ if (!class_exists($className, false)) {
+ $className = ltrim($className, '\\');
+ $fileName = '';
+ $namespace = '';
+ if ($lastNsPos = strripos($className, '\\')) {
+ $namespace = substr($className, 0, $lastNsPos);
+ $className = substr($className, $lastNsPos + 1);
+ $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+ }
+ $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
+
+ require_once $fileName;
+ }
+ }
+}