mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Added HandlerSocket plugin
- Fixed compiler errors - Modified Makefiles to be part of plugin directory - Some minor changes in database.cpp to use the new MariaDB handler interface
This commit is contained in:
@ -1943,3 +1943,4 @@ storage/pbxt/bin/xtstat
|
||||
libmysqld/sql_expression_cache.cc
|
||||
mysql-test/mtr_command
|
||||
scripts/convert-debug-for-diff
|
||||
plugin/handler_socket/client/hsclient
|
||||
|
31
README
31
README
@ -1291,3 +1291,34 @@ Use of any of this software is governed by the terms of the license below:
|
||||
*/
|
||||
|
||||
***************************************************************************
|
||||
|
||||
%%The following software may be included in this product:
|
||||
HandlerSocket plugin for MySQL
|
||||
|
||||
Copyright (c) 2010 DeNA Co.,Ltd.
|
||||
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 DeNA Co.,Ltd. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DeNA Co.,Ltd. "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 DeNA Co.,Ltd. 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.
|
||||
|
||||
***************************************************************************
|
||||
|
19
plugin/handler_socket/AUTHORS
Normal file
19
plugin/handler_socket/AUTHORS
Normal file
@ -0,0 +1,19 @@
|
||||
Akira Higuchi (https://github.com/ahiguti)
|
||||
- developed HanderSocket plugin, libhsclient, and perl-Net-HandlerSocket
|
||||
|
||||
Yoshinori Matsunobu (https://github.com/yoshinorim)
|
||||
- introduced autotools, added support for MySQL 5.5.6, added statistics
|
||||
variables
|
||||
|
||||
Jeff Hodges (https://github.com/jmhodges)
|
||||
- fixed some autotools scripts
|
||||
|
||||
Toru Yamaguchi (https://github.com/zigorou)
|
||||
- ported to MacOS X
|
||||
|
||||
Moriyoshi Koizumi (https://github.com/moriyoshi)
|
||||
- fixed some autotools scripts
|
||||
|
||||
takeda-at (https://github.com/takada-at)
|
||||
- added simple authorization function
|
||||
|
19
plugin/handler_socket/ChangeLog
Normal file
19
plugin/handler_socket/ChangeLog
Normal file
@ -0,0 +1,19 @@
|
||||
1.0.6 - For MariaDB
|
||||
* Modifications to Makefiles to be part of plugin directory
|
||||
* Compiled by default in max builds
|
||||
* Some minor changes in database.cpp to use the new MariaDB handler
|
||||
interface
|
||||
o * Fixed compiler warnings
|
||||
|
||||
1.0.6 - 2010-10-29
|
||||
* Changed build instruction (autoreconf/configure/make), removed auto-generated files (Contributed by jmhodges)
|
||||
*
|
||||
|
||||
1.0.5 - 2010-10-18
|
||||
* Changed build procedures (using typical configure/make)
|
||||
* Supported 5.5.6
|
||||
* Added status variables
|
||||
|
||||
1.0.4 - 2010-08-15
|
||||
* Initial public release
|
||||
|
88
plugin/handler_socket/Makefile.am
Normal file
88
plugin/handler_socket/Makefile.am
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = @HANDLERSOCKET_SUBDIRS@
|
||||
EXTRA_DIST= plug.in
|
||||
|
||||
perl:
|
||||
cd perl-Net-HandlerSocket && perl Makefile.PL && make
|
||||
|
||||
install_perl:
|
||||
cd perl-Net-HandlerSocket && make install
|
||||
|
||||
rpms: rpm_cli rpm_perl rpm_c
|
||||
|
||||
rpm_dir:
|
||||
- mkdir dist
|
||||
- mkdir dist/BUILD dist/RPMS dist/SOURCES dist/SPECS dist/SRPMS
|
||||
|
||||
rpm_cli: clean_cli rpm_dir
|
||||
sed -e "s/HANDLERSOCKET_VERSION/$(VERSION)/" \
|
||||
libhsclient/libhsclient.spec.template \
|
||||
> libhsclient/libhsclient.spec
|
||||
tar cvfz dist/libhsclient.tar.gz libhsclient
|
||||
rpmbuild --define "_topdir `pwd`/dist" -ta \
|
||||
dist/libhsclient.tar.gz
|
||||
|
||||
rpm_perl: clean_perl rpm_dir
|
||||
sed -e "s/HANDLERSOCKET_VERSION/$(VERSION)/" \
|
||||
perl-Net-HandlerSocket/perl-Net-HandlerSocket.spec.template \
|
||||
> perl-Net-HandlerSocket/perl-Net-HandlerSocket.spec
|
||||
cd perl-Net-HandlerSocket && perl Makefile.PL && make clean && \
|
||||
rm -f Makefile.old
|
||||
tar cvfz dist/perl-Net-HandlerSocket.tar.gz perl-Net-HandlerSocket
|
||||
rpmbuild --define "_topdir `pwd`/dist" -ta \
|
||||
dist/perl-Net-HandlerSocket.tar.gz
|
||||
|
||||
rpm_c: clean_c rpm_dir
|
||||
sed -e "s/HANDLERSOCKET_VERSION/$(VERSION)/" \
|
||||
handlersocket/handlersocket.spec.template \
|
||||
> handlersocket/handlersocket.spec
|
||||
sed -e "s|HANDLERSOCKET_MYSQL_INC|$(MYSQL_CFLAGS) $(MYSQL_INC)|" \
|
||||
-e "s|HANDLERSOCKET_MYSQL_LIB|$(MYSQL_LIB)|" \
|
||||
handlersocket/Makefile.plain.template \
|
||||
> handlersocket/Makefile.plain
|
||||
tar cvfz dist/handlersocket.tar.gz handlersocket
|
||||
rpmbuild --define "_topdir `pwd`/dist" -ta \
|
||||
dist/handlersocket.tar.gz
|
||||
|
||||
install_rpm_pl:
|
||||
- sudo rpm -e perl-Net-HandlerSocket
|
||||
- sudo rpm -e perl-Net-HandlerSocket-debuginfo
|
||||
make clean
|
||||
make rpm_perl
|
||||
- sudo rpm -U dist/RPMS/*/perl*.rpm
|
||||
|
||||
installrpms:
|
||||
- sudo rpm -e handlersocket
|
||||
- sudo rpm -e handlersocket-debuginfo
|
||||
- sudo rpm -e perl-Net-HandlerSocket
|
||||
- sudo rpm -e perl-Net-HandlerSocket-debuginfo
|
||||
- sudo rpm -e libhsclient
|
||||
- sudo rpm -e libhsclient-debuginfo
|
||||
make clean
|
||||
make rpm_cli
|
||||
- sudo rpm -U dist/RPMS/*/libhsclient*.rpm
|
||||
make clean
|
||||
make rpm_perl
|
||||
- sudo rpm -U dist/RPMS/*/perl*.rpm
|
||||
make clean
|
||||
make rpm_c
|
||||
- sudo rpm -U dist/RPMS/*/handlersocket*.rpm
|
||||
|
||||
clean_cli:
|
||||
cd libhsclient && make clean
|
||||
cd client && make clean
|
||||
|
||||
clean_perl:
|
||||
cd perl-Net-HandlerSocket && perl Makefile.PL && make clean && \
|
||||
rm -f Makefile.old
|
||||
|
||||
clean_c:
|
||||
cd handlersocket && make clean
|
||||
|
||||
clean_all: clean_cli clean_perl clean_c
|
||||
cd regtest && make clean
|
||||
rm -rf dist/*/*
|
||||
rm -f dist/*.tar.gz
|
||||
|
82
plugin/handler_socket/README
Normal file
82
plugin/handler_socket/README
Normal file
@ -0,0 +1,82 @@
|
||||
Notes added by Monty:
|
||||
|
||||
This is HandlerSocket version 1.0.6 (See ChangeLog file)
|
||||
The original code can be found at:
|
||||
|
||||
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
HandlerSocket plugin for MySQL
|
||||
|
||||
Copyright (c) 2010 DeNA Co.,Ltd.
|
||||
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 DeNA Co.,Ltd. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DeNA Co.,Ltd. "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 DeNA Co.,Ltd. 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.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
About HandlerSocket
|
||||
|
||||
HandlerSocket is a NoSQL plugin for MySQL. It works as a daemon inside the
|
||||
mysqld process, accept tcp connections, and execute requests from clients.
|
||||
HandlerSocket does not support SQL queries. Instead, it supports simple CRUD
|
||||
operations on tables.
|
||||
|
||||
Because of the following reasons, HandlerSocket is much faster than the
|
||||
mysqld/libmysql pair in some circumstances:
|
||||
|
||||
- HandlerSocket manipulates data without parsing SQL, which causes less
|
||||
CPU usage.
|
||||
- HandlerSocket reads many requests from clients and executes their
|
||||
requests in bulk, which causes less CPU and disk usage.
|
||||
- HandlerSocket client/server protocol is more compact than the
|
||||
mysql/libmysql pair, which causes less network usage.
|
||||
|
||||
The current version of HandlerSocket only works with GNU/Linux. The source
|
||||
archive of HandlerSocket includes a C++ and a Perl client libraries.
|
||||
Here is a list of client libraries for other languages:
|
||||
|
||||
- PHP
|
||||
http://openpear.org/package/Net_HandlerSocket
|
||||
http://github.com/tz-lom/HSPHP
|
||||
http://code.google.com/p/php-handlersocket/
|
||||
- Java
|
||||
http://code.google.com/p/hs4j/
|
||||
http://code.google.com/p/handlersocketforjava/
|
||||
- Python
|
||||
http://pypi.python.org/pypi/python-handler-socket
|
||||
https://code.launchpad.net/~songofacandy/+junk/pyhandlersocket
|
||||
- Ruby
|
||||
https://github.com/winebarrel/ruby-handlersocket
|
||||
https://github.com/miyucy/handlersocket
|
||||
- JavaScript
|
||||
https://github.com/koichik/node-handlersocket
|
||||
- Scala
|
||||
https://github.com/fujohnwang/hs2client
|
||||
|
||||
The home of HandlerSocket is here:
|
||||
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
|
||||
|
||||
More documents are available in docs-en/ and docs-ja/ directories.
|
||||
|
117
plugin/handler_socket/autogen.sh
Executable file
117
plugin/handler_socket/autogen.sh
Executable file
@ -0,0 +1,117 @@
|
||||
#!/bin/sh
|
||||
|
||||
warn() {
|
||||
echo -e "\tWARNING: $@" 1>&2
|
||||
}
|
||||
|
||||
# init
|
||||
|
||||
LIBTOOLIZE=libtoolize
|
||||
ACLOCAL=aclocal
|
||||
AUTOCONF=autoconf
|
||||
AUTOHEADER=autoheader
|
||||
AUTOMAKE=automake
|
||||
|
||||
case `uname -s` in
|
||||
Darwin)
|
||||
LIBTOOLIZE=glibtoolize
|
||||
;;
|
||||
FreeBSD)
|
||||
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /usr/local/share/aclocal/"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# libtoolize
|
||||
echo "Searching libtoolize..."
|
||||
if [ `which $LIBTOOLIZE` ] ; then
|
||||
echo -e "\tFOUND: libtoolize -> $LIBTOOLIZE"
|
||||
else
|
||||
warn "Cannot Found libtoolize... input libtool command"
|
||||
read LIBTOOLIZE
|
||||
LIBTOOLIZE=`which $LIBTOOLIZE`
|
||||
if [ `which $LIBTOOLIZE` ] ; then
|
||||
echo -e "\tSET: libtoolize -> $LIBTOOLIZE"
|
||||
else
|
||||
warn "$LIBTOOLIZE: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# aclocal
|
||||
echo "Searching aclocal..."
|
||||
if [ `which $ACLOCAL` ] ; then
|
||||
echo -e "\tFOUND: aclocal -> $ACLOCAL"
|
||||
else
|
||||
warn "Cannot Found aclocal... input aclocal command"
|
||||
read ACLOCAL
|
||||
ACLOCAL=`which $ACLOCAL`
|
||||
if [ `which $ACLOCAL` ] ; then
|
||||
echo -e "\tSET: aclocal -> $ACLOCAL"
|
||||
else
|
||||
warn "$ACLOCAL: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# automake
|
||||
echo "Searching automake..."
|
||||
if [ `which $AUTOMAKE` ] ; then
|
||||
echo -e "\tFOUND: automake -> $AUTOMAKE"
|
||||
else
|
||||
warn "Cannot Found automake... input automake command"
|
||||
read AUTOMAKE
|
||||
ACLOCAL=`which $AUTOMAKE`
|
||||
if [ `which $AUTOMAKE` ] ; then
|
||||
echo -e "\tSET: automake -> $AUTOMAKE"
|
||||
else
|
||||
warn "$AUTOMAKE: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# autoheader
|
||||
echo "Searching autoheader..."
|
||||
if [ `which $AUTOHEADER` ] ; then
|
||||
echo -e "\tFOUND: autoheader -> $AUTOHEADER"
|
||||
else
|
||||
warn "Cannot Found autoheader... input autoheader command"
|
||||
read AUTOHEADER
|
||||
ACLOCAL=`which $AUTOHEADER`
|
||||
if [ `which $AUTOHEADER` ] ; then
|
||||
echo -e "\tSET: autoheader -> $AUTOHEADER"
|
||||
else
|
||||
warn "$AUTOHEADER: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# autoconf
|
||||
echo "Searching autoconf..."
|
||||
if [ `which $AUTOCONF` ] ; then
|
||||
echo -e "\tFOUND: autoconf -> $AUTOCONF"
|
||||
else
|
||||
warn "Cannot Found autoconf... input autoconf command"
|
||||
read AUTOCONF
|
||||
ACLOCAL=`which $AUTOCONF`
|
||||
if [ `which $AUTOCONF` ] ; then
|
||||
echo -e "\tSET: autoconf -> $AUTOCONF"
|
||||
else
|
||||
warn "$AUTOCONF: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Running libtoolize ..."
|
||||
$LIBTOOLIZE --force --copy
|
||||
echo "Running aclocal ..."
|
||||
$ACLOCAL ${ACLOCAL_ARGS} -I .
|
||||
echo "Running autoheader..."
|
||||
$AUTOHEADER
|
||||
echo "Running automake ..."
|
||||
$AUTOMAKE --add-missing --copy
|
||||
echo "Running autoconf ..."
|
||||
$AUTOCONF
|
||||
|
||||
mkdir m4 2> /dev/null
|
||||
|
14
plugin/handler_socket/client/Makefile.am
Normal file
14
plugin/handler_socket/client/Makefile.am
Normal file
@ -0,0 +1,14 @@
|
||||
CXXFLAGS += -fimplicit-templates
|
||||
AM_INCLUDES= -I$(srcdir)/../libhsclient
|
||||
bin_PROGRAMS=hsclient
|
||||
hsclient_SOURCES= hsclient.cpp
|
||||
hsclient_LDFLAGS= -static -L../libhsclient -lhsclient
|
||||
hsclient_CXXFLAGS= $(AM_INCLUDES)
|
||||
|
||||
hstest: hstest.o
|
||||
$(CXX) $(CXXFLAGS) $(LFLAGS) hstest.o \
|
||||
-L../libhsclient/.libs -lhsclient $(MYSQL_LIB) -o hstest
|
||||
|
||||
hstest.o: hstest.cpp
|
||||
$(CXX) $(CXXFLAGS) $(MYSQL_INC) $(AM_INCLUDES) -c hstest.cpp
|
||||
|
88
plugin/handler_socket/client/hsclient.cpp
Normal file
88
plugin/handler_socket/client/hsclient.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
#include "hstcpcli.hpp"
|
||||
#include "string_util.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
int
|
||||
hstcpcli_main(int argc, char **argv)
|
||||
{
|
||||
config conf;
|
||||
parse_args(argc, argv, conf);
|
||||
socket_args sockargs;
|
||||
sockargs.set(conf);
|
||||
hstcpcli_ptr cli = hstcpcli_i::create(sockargs);
|
||||
const std::string dbname = conf.get_str("dbname", "hstest");
|
||||
const std::string table = conf.get_str("table", "hstest_table1");
|
||||
const std::string index = conf.get_str("index", "PRIMARY");
|
||||
const std::string fields = conf.get_str("fields", "k,v");
|
||||
const int limit = conf.get_int("limit", 0);
|
||||
const int skip = conf.get_int("skip", 0);
|
||||
std::vector<std::string> keys;
|
||||
std::vector<string_ref> keyrefs;
|
||||
size_t num_keys = 0;
|
||||
while (true) {
|
||||
const std::string conf_key = std::string("k") + to_stdstring(num_keys);
|
||||
const std::string k = conf.get_str(conf_key, "");
|
||||
const std::string kx = conf.get_str(conf_key, "x");
|
||||
if (k.empty() && kx == "x") {
|
||||
break;
|
||||
}
|
||||
++num_keys;
|
||||
keys.push_back(k);
|
||||
}
|
||||
for (size_t i = 0; i < keys.size(); ++i) {
|
||||
const string_ref ref(keys[i].data(), keys[i].size());
|
||||
keyrefs.push_back(ref);
|
||||
}
|
||||
const std::string op = conf.get_str("op", "=");
|
||||
const string_ref op_ref(op.data(), op.size());
|
||||
cli->request_buf_open_index(0, dbname.c_str(), table.c_str(),
|
||||
index.c_str(), fields.c_str());
|
||||
cli->request_buf_exec_generic(0, op_ref, num_keys == 0 ? 0 : &keyrefs[0],
|
||||
num_keys, limit, skip, string_ref(), 0, 0);
|
||||
int code = 0;
|
||||
size_t numflds = 0;
|
||||
do {
|
||||
if (cli->request_send() != 0) {
|
||||
fprintf(stderr, "request_send: %s\n", cli->get_error().c_str());
|
||||
break;
|
||||
}
|
||||
if ((code = cli->response_recv(numflds)) != 0) {
|
||||
fprintf(stderr, "response_recv: %s\n", cli->get_error().c_str());
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
cli->response_buf_remove();
|
||||
do {
|
||||
if ((code = cli->response_recv(numflds)) != 0) {
|
||||
fprintf(stderr, "response_recv: %s\n", cli->get_error().c_str());
|
||||
break;
|
||||
}
|
||||
while (true) {
|
||||
const string_ref *const row = cli->get_next_row();
|
||||
if (row == 0) {
|
||||
break;
|
||||
}
|
||||
printf("REC:");
|
||||
for (size_t i = 0; i < numflds; ++i) {
|
||||
const std::string val(row[i].begin(), row[i].size());
|
||||
printf(" %s", val.c_str());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
} while (false);
|
||||
cli->response_buf_remove();
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
return dena::hstcpcli_main(argc, argv);
|
||||
}
|
||||
|
224
plugin/handler_socket/client/hspool_test.pl
Executable file
224
plugin/handler_socket/client/hspool_test.pl
Executable file
@ -0,0 +1,224 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use DB::HandlerSocket::Pool;
|
||||
use DBI;
|
||||
|
||||
my %conf = ();
|
||||
for my $i (@ARGV) {
|
||||
my ($k, $v) = split(/=/, $i);
|
||||
$conf{$k} = $v;
|
||||
}
|
||||
|
||||
my $verbose = get_conf("verbose", 0);
|
||||
my $actions_str = get_conf("actions",
|
||||
"create,insert,verify,verify2,verify3,verify4,clean");
|
||||
my $tablesize = get_conf("tablesize", 1000);
|
||||
my $db = get_conf("db", "hstestdb");
|
||||
my $table = get_conf("table", "testtbl");
|
||||
my $table_schema = get_conf("table_schema", undef);
|
||||
my $engine = get_conf("engine", "innodb");
|
||||
my $host = get_conf("host", "localhost");
|
||||
my $mysqlport = get_conf("mysqlport", 3306);
|
||||
my $hsport_rd = get_conf("hsport_rd", 9998);
|
||||
my $hsport_wr = get_conf("hsport_wr", 9999);
|
||||
my $loop = get_conf("loop", 10000);
|
||||
my $op = get_conf("op", "=");
|
||||
my $ssps = get_conf("ssps", 0);
|
||||
my $num_moreflds = get_conf("moreflds", 0);
|
||||
my $moreflds_prefix = get_conf("moreflds_prefix", "f");
|
||||
my $mysql_user = 'root';
|
||||
my $mysql_password = '';
|
||||
|
||||
my $dsn = "DBI:mysql:database=;host=$host;port=$mysqlport"
|
||||
. ";mysql_server_prepare=$ssps";
|
||||
my $dbh = DBI->connect($dsn, $mysql_user, $mysql_password,
|
||||
{ RaiseError => 1 });
|
||||
my $hsargs = { 'host' => $host, 'port' => $hsport_rd };
|
||||
my $hspool = new DB::HandlerSocket::Pool({
|
||||
hostmap => {
|
||||
"$db.$table" => {
|
||||
host => $host,
|
||||
port => $hsport_rd,
|
||||
},
|
||||
},
|
||||
resolve => undef,
|
||||
error => undef,
|
||||
});
|
||||
$table_schema = "(k int primary key, fc30 varchar(30), ft text)"
|
||||
if (!defined($table_schema));
|
||||
|
||||
my @actions = split(/,/, $actions_str);
|
||||
for my $action (@actions) {
|
||||
print "ACTION: $action\n";
|
||||
eval "hstest_$action()";
|
||||
if ($@) {
|
||||
die $@;
|
||||
}
|
||||
print "ACTION: $action DONE\n";
|
||||
}
|
||||
|
||||
sub get_conf {
|
||||
my ($key, $def) = @_;
|
||||
my $val = $conf{$key};
|
||||
if ($val) {
|
||||
print "$key=$val\n";
|
||||
} else {
|
||||
$val = $def;
|
||||
my $defstr = $def || "(undef)";
|
||||
print "$key=$defstr(default)\n";
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
sub hstest_create {
|
||||
$dbh->do("drop database if exists $db");
|
||||
$dbh->do("create database $db");
|
||||
$dbh->do("use $db");
|
||||
$dbh->do("create table $table $table_schema engine=$engine");
|
||||
}
|
||||
|
||||
sub hstest_dump {
|
||||
$dbh->do("use $db");
|
||||
my $sth = $dbh->prepare("select * from $table");
|
||||
$sth->execute();
|
||||
my $arr = $sth->fetchall_arrayref();
|
||||
for my $rec (@$arr) {
|
||||
print "REC:";
|
||||
for my $row (@$rec) {
|
||||
print " $row";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub hstest_insert {
|
||||
$dbh->do("use $db");
|
||||
my $sth = $dbh->prepare("insert into $table values (?, ?, ?)");
|
||||
for (my $k = 0; $k < $tablesize; ++$k) {
|
||||
my $fc30 = "fc30_$k";
|
||||
my $ft = "ft_$k";
|
||||
$sth->execute($k, $fc30, $ft);
|
||||
}
|
||||
}
|
||||
|
||||
sub hstest_verify {
|
||||
$dbh->do("use $db");
|
||||
my $sth = $dbh->prepare("select * from $table order by k");
|
||||
$sth->execute();
|
||||
my $arr = $sth->fetchall_arrayref();
|
||||
my $hsres = $hspool->index_find($db, $table, "PRIMARY", "k,fc30,ft",
|
||||
">=", [ 0 ], $tablesize, 0);
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $rec = $arr->[$i];
|
||||
my $differ = 0;
|
||||
print "REC:" if $verbose;
|
||||
for (my $j = 0; $j < 3; ++$j) {
|
||||
my $fld = $rec->[$j];
|
||||
my $hsidx = $i * 3 + $j;
|
||||
my $hsfld = $hsres->[$hsidx];
|
||||
if ($hsfld ne $fld) {
|
||||
$differ = 1;
|
||||
}
|
||||
if ($differ) {
|
||||
print " $fld:$hsfld" if $verbose;
|
||||
} else {
|
||||
print " $hsfld" if $verbose;
|
||||
}
|
||||
}
|
||||
print "\n" if $verbose;
|
||||
if ($differ) {
|
||||
die "verification failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub hstest_verify2 {
|
||||
$dbh->do("use $db");
|
||||
my $sth = $dbh->prepare("select * from $table order by k");
|
||||
$sth->execute();
|
||||
my $arr = $sth->fetchall_arrayref();
|
||||
my $hsresa = $hspool->index_find_multi($db, $table, "PRIMARY",
|
||||
"k,fc30,ft", [ [ -1, ">=", [ 0 ], $tablesize, 0 ] ]);
|
||||
my $hsres = $hsresa->[0];
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $rec = $arr->[$i];
|
||||
my $differ = 0;
|
||||
print "REC:" if $verbose;
|
||||
for (my $j = 0; $j < 3; ++$j) {
|
||||
my $fld = $rec->[$j];
|
||||
my $hsidx = $i * 3 + $j;
|
||||
my $hsfld = $hsres->[$hsidx];
|
||||
if ($hsfld ne $fld) {
|
||||
$differ = 1;
|
||||
}
|
||||
if ($differ) {
|
||||
print " $fld:$hsfld" if $verbose;
|
||||
} else {
|
||||
print " $hsfld" if $verbose;
|
||||
}
|
||||
}
|
||||
print "\n" if $verbose;
|
||||
if ($differ) {
|
||||
die "verification failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub hashref_to_str {
|
||||
my $href = $_[0];
|
||||
my $r = '';
|
||||
for my $k (sort keys %$href) {
|
||||
my $v = $href->{$k};
|
||||
$r .= "($k=>$v)";
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
sub hstest_verify3 {
|
||||
$dbh->do("use $db");
|
||||
my $sth = $dbh->prepare("select * from $table order by k");
|
||||
$sth->execute();
|
||||
my $hsres_t = $hspool->index_find($db, $table, "PRIMARY", "k,fc30,ft",
|
||||
">=", [ 0 ], $tablesize, 0);
|
||||
my $hsres = DB::HandlerSocket::Pool::result_single_to_hasharr(
|
||||
[ 'k', 'fc30', 'ft' ], $hsres_t);
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $mystr = hashref_to_str($sth->fetchrow_hashref());
|
||||
my $hsstr = hashref_to_str($hsres->[$i]);
|
||||
if ($mystr ne $hsstr) {
|
||||
print "DIFF my=[$mystr] hs=[$hsstr]\n" if $verbose;
|
||||
die "verification failed";
|
||||
} else {
|
||||
print "OK $hsstr\n" if $verbose;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub hstest_verify4 {
|
||||
$dbh->do("use $db");
|
||||
my $sth = $dbh->prepare("select * from $table order by k");
|
||||
$sth->execute();
|
||||
my $hsres_t = $hspool->index_find($db, $table, "PRIMARY", "k,fc30,ft",
|
||||
">=", [ 0 ], $tablesize, 0);
|
||||
my $hsres = DB::HandlerSocket::Pool::result_single_to_hashhash(
|
||||
[ 'k', 'fc30', 'ft' ], 'k', $hsres_t);
|
||||
my $rechash = $sth->fetchall_hashref('k');
|
||||
while (my ($k, $href) = each (%$rechash)) {
|
||||
my $mystr = hashref_to_str($href);
|
||||
my $hsstr = hashref_to_str($hsres->{$k});
|
||||
if ($mystr ne $hsstr) {
|
||||
print "DIFF my=[$mystr] hs=[$hsstr]\n" if $verbose;
|
||||
die "verification failed";
|
||||
} else {
|
||||
print "OK $hsstr\n" if $verbose;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub hstest_clean {
|
||||
$hspool->clear_pool();
|
||||
$dbh->do("drop database if exists $db");
|
||||
}
|
||||
|
1494
plugin/handler_socket/client/hstest.cpp
Normal file
1494
plugin/handler_socket/client/hstest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
228
plugin/handler_socket/client/hstest.pl
Executable file
228
plugin/handler_socket/client/hstest.pl
Executable file
@ -0,0 +1,228 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=8:ai:ts=8
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use DBI;
|
||||
use Net::HandlerSocket;
|
||||
|
||||
my %conf = ();
|
||||
for my $i (@ARGV) {
|
||||
my ($k, $v) = split(/=/, $i);
|
||||
$conf{$k} = $v;
|
||||
}
|
||||
|
||||
my $verbose = get_conf("verbose", 0);
|
||||
my $actions_str = get_conf("actions", "hsread");
|
||||
my $tablesize = get_conf("tablesize", 10000);
|
||||
my $db = get_conf("db", "hstest");
|
||||
my $table = get_conf("table", "hstest_table1");
|
||||
my $engine = get_conf("engine", "innodb");
|
||||
my $host = get_conf("host", "localhost");
|
||||
my $mysqlport = get_conf("mysqlport", 3306);
|
||||
my $mysqluser = get_conf("mysqluser", "root");
|
||||
my $mysqlpass = get_conf("mysqlpass", "");
|
||||
my $hsport = get_conf("hsport", 9999);
|
||||
my $loop = get_conf("loop", 10000);
|
||||
my $op = get_conf("op", "=");
|
||||
my $ssps = get_conf("ssps", 0);
|
||||
my $num_moreflds = get_conf("moreflds", 0);
|
||||
my $moreflds_prefix = get_conf("moreflds_prefix", "column0123456789_");
|
||||
my $keytype = get_conf("keytype", "varchar(32)");
|
||||
my $file = get_conf("file", undef);
|
||||
|
||||
my $dsn = "DBI:mysql:database=;host=$host;port=$mysqlport"
|
||||
. ";mysql_server_prepare=$ssps";
|
||||
my $dbh = DBI->connect($dsn, $mysqluser, $mysqlpass, { RaiseError => 1 });
|
||||
my $hsargs = { 'host' => $host, 'port' => $hsport };
|
||||
my $cli = new Net::HandlerSocket($hsargs);
|
||||
|
||||
my @actions = split(/,/, $actions_str);
|
||||
for my $action (@actions) {
|
||||
if ($action eq "table") {
|
||||
print("TABLE $db.$table\n");
|
||||
$dbh->do("drop database if exists $db");
|
||||
$dbh->do("create database $db");
|
||||
$dbh->do("use $db");
|
||||
my $moreflds = get_createtbl_moreflds_str();
|
||||
$dbh->do(
|
||||
"create table $table (" .
|
||||
"k $keytype primary key" .
|
||||
",v varchar(32) not null" .
|
||||
$moreflds .
|
||||
") character set utf8 collate utf8_bin " .
|
||||
"engine = $engine");
|
||||
} elsif ($action eq "insert") {
|
||||
print("INSERT $db.$table tablesize=$tablesize\n");
|
||||
$dbh->do("use $db");
|
||||
my $moreflds = get_insert_moreflds_str();
|
||||
for (my $i = 0; $i < $tablesize; $i += 100) {
|
||||
my $qstr = "insert into $db.$table values";
|
||||
for (my $j = 0; $j < 100; ++$j) {
|
||||
if ($j != 0) {
|
||||
$qstr .= ",";
|
||||
}
|
||||
my $k = "" . ($i + $j);
|
||||
my $v = "v" . int(rand(1000)) . ($i + $j);
|
||||
$qstr .= "('$k', '$v'";
|
||||
for (my $j = 0; $j < $num_moreflds; ++$j) {
|
||||
$qstr .= ",'$j'";
|
||||
}
|
||||
$qstr .= ")";
|
||||
}
|
||||
$dbh->do($qstr);
|
||||
print "$i/$tablesize\n" if $i % 1000 == 0;
|
||||
}
|
||||
} elsif ($action eq "read") {
|
||||
print("READ $db.$table op=$op loop=$loop\n");
|
||||
$dbh->do("use $db");
|
||||
my $moreflds = get_select_moreflds_str();
|
||||
my $sth = $dbh->prepare(
|
||||
"select k,v$moreflds from $db.$table where k = ?");
|
||||
for (my $i = 0; $i < $loop; ++$i) {
|
||||
my $k = "" . int(rand($tablesize));
|
||||
# print "k=$k\n";
|
||||
$sth->execute($k);
|
||||
if ($verbose >= 10) {
|
||||
print "RET:";
|
||||
while (my $ref = $sth->fetchrow_arrayref()) {
|
||||
my $rk = $ref->[0];
|
||||
my $rv = $ref->[1];
|
||||
print " $rk $rv";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "$i/$loop\n" if $i % 1000 == 0;
|
||||
}
|
||||
} elsif ($action eq "hsinsert") {
|
||||
print("HSINSERT $db.$table tablesize=$tablesize\n");
|
||||
$cli->open_index(1, $db, $table, '', 'k,v');
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v = "v" . int(rand(1000)) . $i;
|
||||
my $r = $cli->execute_insert(1, [ $k, $v ]);
|
||||
if ($r->[0] != 0) {
|
||||
die;
|
||||
}
|
||||
print "$i/$tablesize\n" if $i % 1000 == 0;
|
||||
}
|
||||
} elsif ($action eq "hsread") {
|
||||
print("HSREAD $db.$table op=$op loop=$loop\n");
|
||||
my $moreflds = get_select_moreflds_str();
|
||||
$cli->open_index(1, $db, $table, '', "k,v$moreflds");
|
||||
for (my $i = 0; $i < $loop; ++$i) {
|
||||
my $k = "" . int(rand($tablesize));
|
||||
# print "k=$k\n";
|
||||
my $r = $cli->execute_find(1, $op, [ $k ], 1, 0);
|
||||
if ($verbose >= 10) {
|
||||
my $len = scalar(@{$r});
|
||||
print "LEN=$len";
|
||||
for my $e (@{$r}) {
|
||||
print " [$e]";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "$i/$loop\n" if $i % 1000 == 0;
|
||||
}
|
||||
} elsif ($action eq "hsupdate") {
|
||||
my $vbase = "v" . int(rand(1000));
|
||||
print("HSUPDATE $db.$table op=$op loop=$loop vbase=$vbase\n");
|
||||
$cli->open_index(1, $db, $table, '', 'v');
|
||||
for (my $i = 0; $i < $loop; ++$i) {
|
||||
my $k = "" . int(rand($tablesize));
|
||||
my $v = $vbase . $i;
|
||||
print "k=$k v=$v\n";
|
||||
my $r = $cli->execute_update(1, $op, [ $k ], 1, 0,
|
||||
[ $v ]);
|
||||
if ($verbose >= 10) {
|
||||
print "UP k=$k v=$v\n";
|
||||
}
|
||||
print "$i/$loop\n" if $i % 1000 == 0;
|
||||
}
|
||||
} elsif ($action eq "hsdelete") {
|
||||
print("HSDELETE $db.$table op=$op loop=$loop\n");
|
||||
$cli->open_index(1, $db, $table, '', '');
|
||||
for (my $i = 0; $i < $loop; ++$i) {
|
||||
my $k = "" . int(rand($tablesize));
|
||||
print "k=$k\n";
|
||||
my $r = $cli->execute_delete(1, $op, [ $k ], 1, 0);
|
||||
if ($verbose >= 10) {
|
||||
print "DEL k=$k\n";
|
||||
}
|
||||
print "$i/$loop\n" if $i % 1000 == 0;
|
||||
}
|
||||
} elsif ($action eq "verify") {
|
||||
verify_do();
|
||||
}
|
||||
}
|
||||
|
||||
sub verify_do {
|
||||
my ($fail_cnt, $ok_cnt) = (0, 0);
|
||||
my $sth = $dbh->prepare("select v from $db.$table where k = ?");
|
||||
use FileHandle;
|
||||
my $fh = new FileHandle($file, "r");
|
||||
while (my $line = <$fh>) {
|
||||
chomp($line);
|
||||
my @vec = split(/\t/, $line);
|
||||
my $k = $vec[3];
|
||||
my $v = $vec[7];
|
||||
next if (!defined($k) || !defined($v));
|
||||
# print "$k $v\n";
|
||||
$sth->execute($k);
|
||||
my $aref = $sth->fetchrow_arrayref();
|
||||
if (!defined($aref)) {
|
||||
print "FAILED: $k notfound\n";
|
||||
++$fail_cnt;
|
||||
} else {
|
||||
my $gv = $aref->[0];
|
||||
if ($gv ne $v) {
|
||||
print "FAILED: $k got=$gv expected=$v\n";
|
||||
++$fail_cnt;
|
||||
} else {
|
||||
print "OK: $k $v $gv\n" if $verbose >= 10;
|
||||
++$ok_cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
print "OK=$ok_cnt FAIL=$fail_cnt\n";
|
||||
}
|
||||
|
||||
sub get_conf {
|
||||
my ($key, $def) = @_;
|
||||
my $val = $conf{$key};
|
||||
if ($val) {
|
||||
print "$key=$val\n";
|
||||
} else {
|
||||
$val = $def;
|
||||
$def ||= '';
|
||||
print "$key=$def(default)\n";
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
sub get_createtbl_moreflds_str {
|
||||
my $s = "";
|
||||
for (my $j = 0; $j < $num_moreflds; ++$j) {
|
||||
$s .= ",$moreflds_prefix$j varchar(30)";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub get_select_moreflds_str {
|
||||
my $s = "";
|
||||
for (my $i = 0; $i < $num_moreflds; ++$i) {
|
||||
$s .= ",$moreflds_prefix$i";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub get_insert_moreflds_str {
|
||||
my $s = "";
|
||||
for (my $i = 0; $i < $num_moreflds; ++$i) {
|
||||
$s .= ",?";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
4
plugin/handler_socket/client/hstest_hs.sh
Executable file
4
plugin/handler_socket/client/hstest_hs.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
exec ./hstest test=10 tablesize=10000 host=localhost hsport=9998 num=10000000 \
|
||||
num_threads=100 timelimit=10 $@
|
4
plugin/handler_socket/client/hstest_hs_more50.sh
Executable file
4
plugin/handler_socket/client/hstest_hs_more50.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
exec ./hstest test=10 key_mask=9999 host=localhost port=9998 num=10000000 \
|
||||
num_threads=100 timelimit=10 moreflds=50 $@
|
7
plugin/handler_socket/client/hstest_md.sh
Executable file
7
plugin/handler_socket/client/hstest_md.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
./hstest test=7 key_mask=9999 host=localhost port=11211 num=10000 \
|
||||
num_threads=10 timelimit=10 op=R $@
|
||||
./hstest test=7 key_mask=9999 host=localhost port=11211 num=1000000 \
|
||||
num_threads=100 timelimit=10 op=G $@
|
||||
|
3
plugin/handler_socket/client/hstest_my.sh
Executable file
3
plugin/handler_socket/client/hstest_my.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
exec ./hstest test=9 tablesize=9999 host=localhost mysqlport=3306 num=1000000 \
|
||||
num_threads=100 verbose=1 timelimit=10 $@
|
3
plugin/handler_socket/client/hstest_my_more50.sh
Executable file
3
plugin/handler_socket/client/hstest_my_more50.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
exec ./hstest test=9 key_mask=9999 host=localhost port=3306 num=1000000 \
|
||||
num_threads=100 verbose=1 timelimit=10 moreflds=50 $@
|
134
plugin/handler_socket/configure.ac
Normal file
134
plugin/handler_socket/configure.ac
Normal file
@ -0,0 +1,134 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
#AC_PREREQ([2.63b])
|
||||
AC_INIT([handlersocket-plugin], [1.0.6], [https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL/issues])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
|
||||
AC_CONFIG_SRCDIR([libhsclient/fatal.cpp])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_DEFUN([CONFIG_OPTION_MYSQL],[
|
||||
AC_MSG_CHECKING([mysql source])
|
||||
|
||||
MYSQL_SOURCE_VERSION=
|
||||
MYSQL_INC=
|
||||
ac_mysql_source_dir=
|
||||
AC_ARG_WITH([mysql-source],
|
||||
[AS_HELP_STRING([--with-mysql-source=PATH], [MySQL source directory PATH])],
|
||||
[
|
||||
ac_mysql_source_dir=`cd $withval && pwd`
|
||||
if test -f "$ac_mysql_source_dir/sql/handler.h" ; then
|
||||
MYSQL_INC="-I$ac_mysql_source_dir/sql"
|
||||
MYSQL_INC="$MYSQL_INC -I$ac_mysql_source_dir/include"
|
||||
MYSQL_INC="$MYSQL_INC -I$ac_mysql_source_dir/regex"
|
||||
MYSQL_INC="$MYSQL_INC -I$ac_mysql_source_dir"
|
||||
AC_SUBST(MYSQL_INC)
|
||||
if test -f "$ac_mysql_source_dir/VERSION"; then
|
||||
source "$ac_mysql_source_dir/VERSION"
|
||||
MYSQL_SOURCE_VERSION="$MYSQL_VERSION_MAJOR.$MYSQL_VERSION_MINOR.$MYSQL_VERSION_PATCH"
|
||||
else
|
||||
if test -f "$ac_mysql_source_dir/configure.in"; then
|
||||
MYSQL_SOURCE_VERSION=`cat $ac_mysql_source_dir/configure.in | grep "\[[MySQL Server\]]" | sed -e "s|.*\([[0-9]]\+\.[[0-9]]\+\.[[0-9]]\+[[0-9a-zA-Z\_\-]]*\).*|\1|"`
|
||||
else
|
||||
AC_MSG_ERROR([invalid MySQL source directory: $ac_mysql_source_dir])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([yes: Using $ac_mysql_source_dir, version $MYSQL_SOURCE_VERSION])
|
||||
else
|
||||
AC_MSG_ERROR([invalid MySQL source directory: $ac_mysql_source_dir])
|
||||
fi
|
||||
],
|
||||
[AC_MSG_ERROR([--with-mysql-source=PATH is required for standalone build])]
|
||||
)
|
||||
|
||||
MYSQL_BIN_VERSION=
|
||||
ac_mysql_config=
|
||||
AC_ARG_WITH([mysql-bindir],
|
||||
[AS_HELP_STRING([--with-mysql-bindir=PATH], [MySQL binary directory PATH. This should be the directory where mysql_config is located.])],
|
||||
[
|
||||
mysql_bin_dir=`cd $withval 2> /dev/null && pwd || echo ""`
|
||||
ac_mysql_config="$mysql_bin_dir/mysql_config"
|
||||
],
|
||||
[
|
||||
AC_PATH_PROG([ac_mysql_config], [mysql_config])
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([mysql binary])
|
||||
if test ! -x "$ac_mysql_config" ; then
|
||||
AC_MSG_ERROR([mysql_config not found! You have to specify the directory where mysql_config resides to --with-mysql-bindir=PATH.])
|
||||
fi
|
||||
|
||||
MYSQL_CFLAGS_ADD=`"$ac_mysql_config" --cflags`
|
||||
MYSQL_CFLAGS="$MYSQL_CFLAGS $MYSQL_CFLAGS_ADD -DFORCE_DBUG_OFF"
|
||||
# FIXME
|
||||
AC_SUBST(MYSQL_CFLAGS)
|
||||
|
||||
MYSQL_BIN_VERSION=`"$ac_mysql_config" --version`
|
||||
AC_MSG_RESULT([yes: Using $ac_mysql_config, version $MYSQL_BIN_VERSION])
|
||||
|
||||
MYSQL_LIB=`"$ac_mysql_config" --libs_r`
|
||||
LIB_DIR=`echo $MYSQL_LIB | sed -e "s|.*-L/|/|" | sed -e "s| .*||"`
|
||||
# FIXME
|
||||
if test a`basename "$LIB_DIR"` = amysql ; then
|
||||
MYSQL_LIB="-L`dirname $LIB_DIR` $MYSQL_LIB"
|
||||
# FIXME
|
||||
fi
|
||||
AC_SUBST(MYSQL_LIB)
|
||||
|
||||
if test a$MYSQL_SOURCE_VERSION != a$MYSQL_BIN_VERSION ; then
|
||||
AC_MSG_ERROR([MySQL source version does not match MySQL binary version])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([mysql plugin dir])
|
||||
ac_mysql_plugin_dir=
|
||||
AC_ARG_WITH([mysql-plugindir],
|
||||
[AS_HELP_STRING([--with-mysql-plugindir=PATH], [MySQL plugin directory where handlersocket.so to be copied])],
|
||||
[
|
||||
ac_mysql_plugin_dir=`cd $withval && pwd`
|
||||
if test -d "$ac_mysql_plugin_dir/" ; then
|
||||
PLUGIN_DIR="$ac_mysql_plugin_dir"
|
||||
AC_SUBST(PLUGIN_DIR)
|
||||
AC_MSG_RESULT([yes: Using $ac_mysql_plugin_dir])
|
||||
else
|
||||
AC_MSG_ERROR([invalid MySQL plugin directory : $ac_mysql_plugin_dir])
|
||||
fi
|
||||
],
|
||||
[
|
||||
LIB_DIR_TMP=`"$ac_mysql_config" --plugindir`
|
||||
if test ! -d "$LIB_DIR_TMP"; then
|
||||
LIB_DIR_TMP=`"$ac_mysql_config" --libs_r | sed -e "s|.*-L/|/|" | sed -e "s| .*||"`/plugin
|
||||
# FIXME
|
||||
fi
|
||||
ac_mysql_plugin_dir=$LIB_DIR_TMP
|
||||
PLUGIN_DIR="$ac_mysql_plugin_dir"
|
||||
AC_SUBST(PLUGIN_DIR)
|
||||
AC_MSG_RESULT([--with-mysql-plugindir was not set. Using $ac_mysql_plugin_dir])
|
||||
]
|
||||
)
|
||||
])
|
||||
|
||||
HANDLERSOCKET_SUBDIRS="libhsclient"
|
||||
AC_ARG_ENABLE(handlersocket_server,
|
||||
[ --enable-handlersocket-server build HandlerSocket plugin (defalut=yes)])
|
||||
if test "$enable_handlersocket_server" != "no"; then
|
||||
CONFIG_OPTION_MYSQL
|
||||
HANDLERSOCKET_SUBDIRS="libhsclient handlersocket client"
|
||||
fi
|
||||
AC_SUBST(HANDLERSOCKET_SUBDIRS)
|
||||
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
CXXFLAGS="$CXXFLAGS -Wall -g -fno-rtti -fno-exceptions -fPIC -DPIC"
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
handlersocket/Makefile
|
||||
libhsclient/Makefile
|
||||
client/Makefile])
|
||||
|
||||
AC_OUTPUT
|
72
plugin/handler_socket/docs-en/about-handlersocket.en.txt
Normal file
72
plugin/handler_socket/docs-en/about-handlersocket.en.txt
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
HandlerSocket plugin for MySQL
|
||||
|
||||
Copyright (c) 2010 DeNA Co.,Ltd.
|
||||
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 DeNA Co.,Ltd. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DeNA Co.,Ltd. "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 DeNA Co.,Ltd. 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.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
About HandlerSocket
|
||||
|
||||
HandlerSocket is a NoSQL plugin for MySQL. It works as a daemon inside the
|
||||
mysqld process, accept tcp connections, and execute requests from clients.
|
||||
HandlerSocket does not support SQL queries. Instead, it supports simple CRUD
|
||||
operations on tables.
|
||||
|
||||
Because of the following reasons, HandlerSocket is much faster than the
|
||||
mysqld/libmysql pair in some circumstances:
|
||||
|
||||
- HandlerSocket manipulates data without parsing SQL, which causes less
|
||||
CPU usage.
|
||||
- HandlerSocket reads many requests from clients and executes their
|
||||
requests in bulk, which causes less CPU and disk usage.
|
||||
- HandlerSocket client/server protocol is more compact than the
|
||||
mysql/libmysql pair, which causes less network usage.
|
||||
|
||||
The current version of HandlerSocket only works with GNU/Linux. The source
|
||||
archive of HandlerSocket includes a C++ and a Perl client libraries.
|
||||
Here is a list of other language bindings:
|
||||
|
||||
- PHP
|
||||
http://openpear.org/package/Net_HandlerSocket
|
||||
http://github.com/tz-lom/HSPHP
|
||||
http://code.google.com/p/php-handlersocket/
|
||||
- Java
|
||||
http://code.google.com/p/handlersocketforjava/
|
||||
- Python
|
||||
https://code.launchpad.net/~songofacandy/+junk/pyhandlersocket
|
||||
- Ruby
|
||||
https://github.com/winebarrel/ruby-handlersocket
|
||||
https://github.com/miyucy/handlersocket
|
||||
- JavaScript(Node.js)
|
||||
https://github.com/koichik/node-handlersocket
|
||||
|
||||
The home of HandlerSocket is here:
|
||||
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
|
||||
|
||||
More documents are available in docs-en/ and docs-ja/ directories.
|
||||
|
87
plugin/handler_socket/docs-en/configuration-options.en.txt
Normal file
87
plugin/handler_socket/docs-en/configuration-options.en.txt
Normal file
@ -0,0 +1,87 @@
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_verbose (default = 10, min = 0, max = 10000)
|
||||
|
||||
Specify the logging verboseness.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_address (default = '')
|
||||
|
||||
Specify the address to bind. If empty, it binds to 0.0.0.0.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_port (default = '9998')
|
||||
|
||||
Specify the port to bind. This option is for the listener for
|
||||
read requests. If empty, the listener is disabled.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_port_wr (default = '9999')
|
||||
|
||||
Specify the port to bind. This option is for the listener for
|
||||
write requests. If empty, the listener is disabled.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_epoll (default = 1, min = 0, max = 1)
|
||||
|
||||
Specify whether handlersocket uses epoll for I/O multiplexing.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_threads (default = 16, min = 1, max = 3000)
|
||||
|
||||
Specify the number of handlersocket worker threads. This option
|
||||
is for the listener for read requests. Recommended value is
|
||||
(the number of CPU cores * 2).
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_threads_wr (default = 1, min = 1, max = 3000)
|
||||
|
||||
Specify the number of handlersocket worker threads. This option
|
||||
is for the listener for write requests. Recommended value is 1.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_timeout (default = 300, min = 30, max = 3600)
|
||||
|
||||
Specify the socket timeout in seconds.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_backlog (default = 32768, min = 5, max = 1000000)
|
||||
|
||||
Specify the length of the listen backlog.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_sndbuf (default = 0, min = 0, max = 1677216)
|
||||
|
||||
Specify the maximum socket send buffer in bytes. If 0, the
|
||||
system-wide default value is set.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_rcvbuf (default = 0, min = 0, max = 1677216)
|
||||
|
||||
Specify the maximum socket receive buffer in bytes. If 0, the
|
||||
system-wide default value is set.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_readsize (default = 0, min = 0, max = 1677216)
|
||||
|
||||
Specify the minimum length of the handlersocket request buffer.
|
||||
Larger value can make handlersocket faster for large requests,
|
||||
but can consume memory. The default value is possibly 4096.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_accept_balance (default = 0, min = 0, max = 10000)
|
||||
|
||||
When this option is set to non-zero, handlersocket tries to
|
||||
balance accepted connections among threads. Non-zero is
|
||||
recommended if you use persistent connections (i.e., connection
|
||||
pooling on the client side).
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket_wrlock_timeout (default = 12, min = 0, max = 3600)
|
||||
|
||||
Specify the lock timeout in seconds. When a write request is
|
||||
performed, handlersocket locks an advisory lock named
|
||||
'handlersocket_wr'. This option sets the timeout for the
|
||||
locking.
|
||||
|
||||
|
91
plugin/handler_socket/docs-en/installation.en.txt
Normal file
91
plugin/handler_socket/docs-en/installation.en.txt
Normal file
@ -0,0 +1,91 @@
|
||||
1. Building Handlersocket
|
||||
|
||||
Handlersocket mainly consists of libhsclient, handlersocket, and C++/Perl clients. libhsclient is a common library shared from both client and server(plugin). handlersocket is a MySQL daemon plugin.
|
||||
To build Handlersocket, you need both MySQL source code and MySQL binary. It is not required to pre-build MySQL source code, but source itself is needed because Handlersocket depends on MySQL header files that only MySQL source distribution contains. MySQL binary is just a normal MySQL binary distribution. You can use official MySQL binaries provided by Oracle.
|
||||
Since Handlersocket uses daemon plugin interface supported from MySQL 5.1,
|
||||
MySQL 5.1 or higher version is required.
|
||||
Please make sure that you use identical MySQL version between MySQL source
|
||||
and MySQL binary. Otherwise you might encounter serious problems (i.e. server
|
||||
crash, etc).
|
||||
Here are steps to build Handlersocket.
|
||||
|
||||
* Get MySQL source code
|
||||
|
||||
* Get MySQL binary
|
||||
|
||||
* Build Handlersocket
|
||||
$ ./autogen.sh
|
||||
$ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin
|
||||
|
||||
--with-mysql-source refers to the top of MySQL source directory,
|
||||
--with-mysql-bindir refers to where MySQL binary executables (i.e.
|
||||
mysql_config) are located, and --with-mysql-plugindir refers to a plugin
|
||||
directory where plugin libraries (*.so) are installed.
|
||||
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
Both libhsclient and the handlersocket plugin will be installed.
|
||||
|
||||
|
||||
2. Using Handlersocket
|
||||
|
||||
Append configuration options for handlersocket to my.cnf.
|
||||
|
||||
[mysqld]
|
||||
loose_handlersocket_port = 9998
|
||||
# the port number to bind to (for read requests)
|
||||
loose_handlersocket_port_wr = 9999
|
||||
# the port number to bind to (for write requests)
|
||||
loose_handlersocket_threads = 16
|
||||
# the number of worker threads (for read requests)
|
||||
loose_handlersocket_threads_wr = 1
|
||||
# the number of worker threads (for write requests)
|
||||
open_files_limit = 65535
|
||||
# to allow handlersocket accept many concurrent
|
||||
# connections, make open_files_limit as large as
|
||||
# possible.
|
||||
|
||||
Log in to mysql as root, and execute the following query.
|
||||
|
||||
mysql> install plugin handlersocket soname 'handlersocket.so';
|
||||
|
||||
If handlersocket.so is successfully installed, it starts
|
||||
accepting connections on port 9998 and 9999. Running
|
||||
'show processlist' should show handlersocket worker threads.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
On the client side, you need to install libhsclient for c++ apps
|
||||
and perl-Net-HandlerSocket for perl apps. They do not require
|
||||
MySQL to compile.
|
||||
|
||||
$ ./autogen.sh
|
||||
$ ./configure --disable-handlersocket-server
|
||||
$ make
|
||||
$ sudo make install
|
||||
$ cd perl-Net-HandlerSocket
|
||||
$ perl Makefile.PL
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Alternatively, you can use the rpm installation. If your OS
|
||||
supports rpms, you can use the following commands to build and
|
||||
install handlersocket rpm packages.
|
||||
|
||||
(Server side, installs HandlerSocket plugin)
|
||||
$ ./autogen.sh
|
||||
$ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin
|
||||
$ make rpm_cli
|
||||
$ sudo rpm -U dist/RPMS/*/libhsclient*.rpm
|
||||
$ make rpm_c
|
||||
$ sudo rpm -U dist/RPMS/*/handlersocket*.rpm
|
||||
|
||||
(Client side, installs client libraries)
|
||||
$ ./autogen.sh
|
||||
$ ./configure --disable-handlersocket-server
|
||||
$ make rpm_cli
|
||||
$ sudo rpm -U dist/RPMS/*/libhsclient*.rpm
|
||||
$ make rpm_perl
|
||||
$ sudo rpm -U dist/RPMS/*/perl-Net-HandlerSocket*.rpm
|
||||
|
126
plugin/handler_socket/docs-en/perl-client.en.txt
Normal file
126
plugin/handler_socket/docs-en/perl-client.en.txt
Normal file
@ -0,0 +1,126 @@
|
||||
|
||||
-----------------------------------------------------------------
|
||||
To open a connection to the handlersocket plugin, you need to
|
||||
create a Net::HandlerSocket object.
|
||||
|
||||
use Net::HandlerSocket;
|
||||
my $args = { host => 'localhost', port => 9998 };
|
||||
my $hs = new Net::HandlerSocket($args);
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Before executing table operations, you need to open an index to
|
||||
work with.
|
||||
|
||||
my $err = $hs->open_index(3, 'database1', 'table1', 'PRIMARY',
|
||||
'f1,f2');
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
|
||||
The first argument for open_index is an integer value which is
|
||||
used to identify an open table, which is only valid within the
|
||||
same Net::HandlerSocket object. The 4th argument is the name of
|
||||
index to open. If 'PRIMARY' is specified, the primary index is
|
||||
open. The 5th argument is a comma-separated list of column names.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
To read a record from a table using an index, call the
|
||||
execute_single method.
|
||||
|
||||
my $res = $hs->execute_single(3, '=', [ 'foo' ], 1, 0);
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
shift(@$res);
|
||||
|
||||
The first argument must be an integer which has specified as the
|
||||
first argument for open_index on the same Net::HandlerSocket
|
||||
object. The second argument specifies the search operation. The
|
||||
current version of handlersocket supports '=', '>=', '<=', '>',
|
||||
and '<'. The 3rd argument specifies the key to find, which must
|
||||
an arrayref whose length is equal to or smaller than the number
|
||||
of key columns of the index. The 4th and the 5th arguments
|
||||
specify the maximum number of records to be retrieved, and the
|
||||
number of records skipped before retrieving records. The columns
|
||||
to be retrieved are specified by the 5th argument for the
|
||||
corresponding open_index call.
|
||||
|
||||
The execute_single method always returns an arrayref. The first
|
||||
element is the error code, which is 0 when no error is occured.
|
||||
The remaining are the field values. If more than one record is
|
||||
returned, it is flatten to an 1-dimensional array. For example,
|
||||
when 5 records that have 3 columns are returned, you can retrieve
|
||||
values using the following code.
|
||||
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
shift(@$res);
|
||||
for (my $row = 0; $row < 5; ++$row) {
|
||||
for (my $col = 0; $col < 3; ++$col) {
|
||||
my $value = $res->[$row * 5 + $col];
|
||||
# ...
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
To update or delete records, you need to specify more arguments
|
||||
for the execute_single method. Note that the Net::HandlerSocket
|
||||
object must be connected to a handlersocket worker for write
|
||||
operations, which is port 9999 by default.
|
||||
(For safety, the port 9998 only allows read operations, and the
|
||||
port 9999 allows write operations also. The port 9999 allows
|
||||
read operations too, but slower than 9998 because of record
|
||||
locking etc.. Port numbers can be changed using the
|
||||
'handlersocket_port' and the 'handlersocket_port_wr'
|
||||
configuration options of mysqld.)
|
||||
|
||||
my $args = { host => 'localhost', port => 9999 };
|
||||
my $hs = new Net::HandlerSocket($args);
|
||||
|
||||
my $res = $hs->execute_single(3, '=', [ 'bar' ], 1, 0, 'U',
|
||||
[ 'fubar', 'hoge' ]);
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
my $num_updated_rows = $res->[1];
|
||||
|
||||
my $res = $hs->execute_single(3, '=', [ 'baz' ], 1, 0, 'D');
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
my $num_deleted_rows = $res->[1];
|
||||
|
||||
The 6th argument for execute_single specifies the modification
|
||||
operation. The current version supports 'U' and 'D'. For the 'U'
|
||||
operation, the 7th argument specifies the new value for the row.
|
||||
The columns to be modified are specified by the 5th argument for
|
||||
the corresponding open_index call. For the 'D' operation, the
|
||||
7th argument can be omitted.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
The execute_single method can be used for inserting records also.
|
||||
|
||||
my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]);
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
my $num_inserted_rows = $res->[1];
|
||||
|
||||
The 3rd argument must be an arrayref whose elements correspond to
|
||||
the 5th argument for the corresponding open_index call. If there
|
||||
is a column which is not appeared in the 5th argument for the
|
||||
open_index, the default value for the column is set.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Multiple operations can be executed in a single call. Executing
|
||||
multiple operations in a single call is much faster than
|
||||
executing them separatedly.
|
||||
|
||||
my $rarr = $hs->execute_multi([
|
||||
[ 0, '>=', [ 'foo' ], 5, 0 ],
|
||||
[ 2, '=', [ 'bar' ], 1, 0 ],
|
||||
[ 4, '<', [ 'baz' ], 10, 5 ],
|
||||
]);
|
||||
for my $res (@$rarr) {
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
shift(@$res);
|
||||
# ...
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
When an error is occured, the first element of the returned
|
||||
arrayref becomes a non-zero value. A negative value indicates
|
||||
that an I/O error is occured and the Net::HandlerSocket object
|
||||
should be disposed. A positive value means that the connection is
|
||||
still active and the Net::HandlerSocket object can be reused
|
||||
later.
|
||||
|
148
plugin/handler_socket/docs-en/protocol.en.txt
Normal file
148
plugin/handler_socket/docs-en/protocol.en.txt
Normal file
@ -0,0 +1,148 @@
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
The HandlerSocket protocol
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Basic syntax
|
||||
|
||||
- The HandlerSocket protocol is line-based. Each line ends with LF(0x0a).
|
||||
- Each line consists a concatenation of tokens separated by HT(0x09).
|
||||
- A token is either NULL or an encoded string. Note that you need to
|
||||
distinguish NULL from an empty string, as most DBMs does so.
|
||||
- NULL is expressed as a single NUL(0x00).
|
||||
- An encoded string is a string with the following encoding rules.
|
||||
- Characters in the range [0x10 - 0xff] are not encoded.
|
||||
- A character in the range [0x00 - 0x0f] is prefixed by 0x01 and
|
||||
shifted by 0x40. For example, 0x03 is encoded as 0x01 0x43.
|
||||
- Note that a string can be empty. A continuation of 0x09 0x09 means that
|
||||
there is an empty string between them. A continuation of 0x09 0x0a means
|
||||
that there is an empty string at the end of the line.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Request and Response
|
||||
|
||||
- The HandlerSocket protocol is a simple request/response protocol. After a
|
||||
connection is established, the client side sends a request, and then the
|
||||
server side sends a response.
|
||||
- A request/response consists of a single line.
|
||||
- Requests can be pipelined; That is, you can send multiple requests (ie.
|
||||
lines) at one time, and receive responses for them at one time.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
'open_index' request
|
||||
|
||||
The 'open_index' request has the following syntax.
|
||||
|
||||
P <indexid> <dbname> <tablename> <indexname> <columns>
|
||||
|
||||
- <indexid> is a number in decimal.
|
||||
- <dbname>, <tablename>, and <indexname> are strings. To open the primary
|
||||
key, use PRIMARY as <indexname>.
|
||||
- <columns> is a comma-separated list of column names.
|
||||
|
||||
Once an 'open_index' request is issued, the HandlerSocket plugin opens the
|
||||
specified index and keep it open until the client connection is closed. Each
|
||||
open index is identified by <indexid>. If <indexid> is already open, the old
|
||||
open index is closed. You can open the same combination of <dbname>
|
||||
<tablename> <indexname> multple times, possibly with different <columns>.
|
||||
For efficiency, keep <indexid> small as far as possible.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Getting data
|
||||
|
||||
The 'find' request has the following syntax.
|
||||
|
||||
<indexid> <op> <vlen> <v1> ... <vn> <limit> <offset>
|
||||
|
||||
- <indexid> is a number. This number must be an <indexid> specified by a
|
||||
'open_index' request executed previously on the same connection.
|
||||
- <op> specifies the comparison operation to use. The current version of
|
||||
HandlerSocket supports '=', '>', '>=', '<', and '<='.
|
||||
- <vlen> indicates the length of the trailing parameters <v1> ... <vn>. This
|
||||
must be smaller than or equal to the number of index columns specified by
|
||||
specified by the corresponding 'open_index' request.
|
||||
- <v1> ... <vn> specify the index column values to fetch.
|
||||
- <limit> and <offset> are numbers. These parameters can be omitted. When
|
||||
omitted, it works as if 1 and 0 are specified.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Updating/Deleting data
|
||||
|
||||
The 'find_modify' request has the following syntax.
|
||||
|
||||
<indexid> <op> <vlen> <v1> ... <vn> <limit> <offset> <mop> <m1> ... <mk>
|
||||
|
||||
- <mop> is either 'U' (update) or 'D' (delete).
|
||||
- <m1> ... <mk> specifies the column values to set. The length of <m1> ...
|
||||
<mk> must be smaller than or equal to the length of <columns> specified by
|
||||
the corresponding 'open_index' request. If <mop> is 'D', these parameters
|
||||
are ignored.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Inserting data
|
||||
|
||||
The 'insert' request has the following syntax.
|
||||
|
||||
<indexid> '+' <vlen> <v1> ... <vn>
|
||||
|
||||
- <vlen> indicates the length of the trailing parameters <v1> ... <vn>. This
|
||||
must be smaller than or equal to the length of <columns> specified by the
|
||||
corresponding 'open_index' request.
|
||||
- <v1> ... <vn> specify the column values to set. For columns not in
|
||||
<columns>, the default values for each column are set.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Response syntax
|
||||
|
||||
HandlerSocket returns a response of the following syntax for each request.
|
||||
|
||||
<errorcode> <numcolumns> <r1> ... <rn>
|
||||
|
||||
- <errorcode> indicates whether the request has successfully executed or not.
|
||||
'0' means success. Non-zero means an error.
|
||||
- <numcolumns> indicates the number of columns of the result set.
|
||||
- <r1> ... <rn> is the result set. The length of <r1> ... <rn> is always a
|
||||
multiple of <numcolumns>. It is possible that <r1> ... <rn> is empty.
|
||||
|
||||
If <errorcode> is non-zero, <numcolumns> is always 1 and <r1> indicates a
|
||||
human-readable error message, though sometimes <r1> is not provided.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Response for 'open_index'
|
||||
|
||||
If 'open_index' is succeeded, HandlerSocket returns a line of the following
|
||||
syntax.
|
||||
|
||||
0 1
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Response for 'find'
|
||||
|
||||
If 'find' is succeeded, HandlerSocket returns a line of the following
|
||||
syntax.
|
||||
|
||||
0 <numcolumns> <r1> ... <rn>
|
||||
|
||||
- <numcolumns> always equals to the length of <columns> of the corresponding
|
||||
'open_index' request.
|
||||
- <r1> ... <rn> is the result set. If N rows are found, the length of <r1>
|
||||
... <rn> becomes ( <numcolumns> * N ).
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Response for 'find_modify'
|
||||
|
||||
If 'find_modify' is succeeded, HandlerSocket returns a line of the following
|
||||
syntax.
|
||||
|
||||
0 1 <nummod>
|
||||
|
||||
- <nummod> is the number of modified rows.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Response for 'insert'
|
||||
|
||||
If 'insert' is succeeded, HanderSocket returns a line of the following
|
||||
syntax.
|
||||
|
||||
0 1
|
||||
|
51
plugin/handler_socket/docs-ja/about-handlersocket.ja.txt
Normal file
51
plugin/handler_socket/docs-ja/about-handlersocket.ja.txt
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
ソースコードの利用にあたっての免責事項
|
||||
|
||||
本ソフトウェアの開発者および株式会社ディー・エヌ・エーは、本フト
|
||||
ウェアの不稼動、稼動不良を含む法律上の瑕疵担保責任、その他保証責
|
||||
任を負わないものとします。また、本ソフトウエアの開発者および株式
|
||||
会社ディー・エヌ・エーは、本ソフトウェアの商品性、またはお客様の
|
||||
特定の目的に対する適合性について、いかなる保証も負わないものとし
|
||||
ます。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocket pluginについて
|
||||
|
||||
mysqlサーバに常駐し、innodb等のストレージエンジンへの直接のアクセ
|
||||
スを提供するプラグインです。handlersocketプラグインは自前のリス
|
||||
ナーを持ち、専用のクライアントライブラリ(libhsclient)を使ってそれ
|
||||
にアクセスします。
|
||||
|
||||
mysqlの標準クライアントライブラリ(libmysql)を使ったアクセスと比べ
|
||||
て、以下のような利点があります。
|
||||
・接続あたりに消費するリソースが少ないため、同時接続数が事実上無
|
||||
制限。したがって接続数を気にせず持続接続を使えます。
|
||||
・高速(単純な参照クエリで3倍〜10倍程度)。
|
||||
・通信プロトコルがコンパクト。libmysqlを使うとデータ転送時にレ
|
||||
コード名などが付随するために通信内容が冗長ですが、libhsclientで
|
||||
はデータのみが転送されるため、帯域消費が少なくなります。場合に
|
||||
よっては10倍以上libmysqlのほうが冗長になります。
|
||||
|
||||
現在のバージョンでは以下のような処理をサポートしています。
|
||||
・指定された索引について、指定された値と完全一致するようなレコー
|
||||
ドを取得。(SELECT ??? FROM tbl WHERE k1 = v1 AND k2 = v2...)。
|
||||
索引を使わない検索はサポートしていません。
|
||||
・指定された索引について、指定された値の位置の前後のレコードを取
|
||||
得。(SELECT ??? FROM tbl WHERE k1 >= v1 LIMIT 100)
|
||||
・前述のような手段で取得したレコードに対するUPDATEとDELETE
|
||||
・レコードのINSERT
|
||||
|
||||
以下のような言語をサポートします。
|
||||
・C++。libhsclientをリンクします。
|
||||
・Perl。Net::HandlerSocketをuseします。
|
||||
|
||||
現在のバージョンではGNU/Linuxでのみ動作します。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
既知の問題
|
||||
|
||||
・killでhandlersocketスレッドを殺すと、スレッド数が減ったまま回復
|
||||
しません。
|
||||
|
87
plugin/handler_socket/docs-ja/installation.ja.txt
Normal file
87
plugin/handler_socket/docs-ja/installation.ja.txt
Normal file
@ -0,0 +1,87 @@
|
||||
|
||||
-----------------------------------------------------------------
|
||||
HandlerSocketプラグインのビルド方法(RPMを使わない方法)
|
||||
|
||||
以下のようにしてconfigureを実行します。
|
||||
|
||||
$ ./autogen.sh
|
||||
$ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin
|
||||
|
||||
ここで--with-mysql-sourceにはMySQLのソースコードのトップディレク
|
||||
トリを指定します。--with-mysql-bindirにはインストール済みのMySQL
|
||||
のmysql_configコマンドが有るディレクトリを指定します。
|
||||
その後以下のようにビルド・インストールします。
|
||||
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
-----------------------------------------------------------------
|
||||
クライアントライブラリのビルド方法(RPMを使わない方法)
|
||||
|
||||
クライアントライブラリをビルドする際には、MySQLのソースコードは
|
||||
必要ありません。またMySQLがインストールされている必要もありません。
|
||||
|
||||
$ ./autogen.sh
|
||||
$ ./configure --disable-handlersocket-server
|
||||
$ make
|
||||
$ sudo make install
|
||||
$ cd perl-Net-HandlerSocket
|
||||
$ perl Makefile.PL
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
-----------------------------------------------------------------
|
||||
ビルド方法(RPM)
|
||||
|
||||
以下のように実行すれば、rpmパッケージがビルド&インストールされま
|
||||
す。
|
||||
|
||||
(MySQLサーバ側、HandlerSocketプラグインをインストールする)
|
||||
$ ./autogen.sh
|
||||
$ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin
|
||||
$ make rpm_cli
|
||||
$ sudo rpm -U dist/RPMS/*/libhsclient*.rpm
|
||||
$ make rpm_c
|
||||
$ sudo rpm -U dist/RPMS/*/handlersocket*.rpm
|
||||
|
||||
(クライアント側、クライアントライブラリをインストールする)
|
||||
$ ./autogen.sh
|
||||
$ ./configure --disable-handlersocket-server
|
||||
$ make rpm_cli
|
||||
$ sudo rpm -U dist/RPMS/*/libhsclient*.rpm
|
||||
$ make rpm_perl
|
||||
$ sudo rpm -U dist/RPMS/*/perl-Net-HandlerSocket*.rpm
|
||||
|
||||
-----------------------------------------------------------------
|
||||
起動
|
||||
|
||||
mysqlを起動した状態で、mysqlの設定ファイル(my.cnf等)に以下の内容を
|
||||
追加します。
|
||||
|
||||
[mysqld]
|
||||
handlersocket_port = 9998
|
||||
# handlersocketが接続を受け付けるポート(参照系リクエスト用)
|
||||
handlersocket_port_wr = 9999
|
||||
# handlersocketが接続を受け付けるポート(更新系リクエスト用)
|
||||
handlersocket_address =
|
||||
# handlersocketがバインドするアドレス(空のままでOK)
|
||||
handlersocket_verbose = 0
|
||||
# デバッグ用
|
||||
handlersocket_timeout = 300
|
||||
# 通信タイムアウト(秒)
|
||||
handlersocket_threads = 16
|
||||
# handlersocketのワーカースレッド数
|
||||
thread_concurrency = 128
|
||||
# handlersocketが幾つかのスレッドを占有するため、大きめの
|
||||
# 値を指定してください
|
||||
open_files_limit = 65535
|
||||
# ソケットを大量に開けるようにするため、大きめの値を指定し
|
||||
# てください
|
||||
|
||||
以下のクエリを実行します。
|
||||
|
||||
mysql> install plugin handlersocket soname 'handlersocket.so';
|
||||
Query OK, 0 rows affected (0.06 sec)
|
||||
|
||||
以上でhandlersocketへクライアントからアクセスできるようになります。
|
||||
|
118
plugin/handler_socket/docs-ja/perl-client.ja.txt
Normal file
118
plugin/handler_socket/docs-ja/perl-client.ja.txt
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocketプラグインへの接続を開くには、Net::HandlerSocketオブ
|
||||
ジェクトを作成します。
|
||||
|
||||
use Net::HandlerSocket;
|
||||
my $args = { host => 'localhost', port => 9998 };
|
||||
my $hs = new Net::HandlerSocket($args);
|
||||
|
||||
-----------------------------------------------------------------
|
||||
検索などの命令を実行する前に、処理対象となる索引を開く必要があり
|
||||
ます。
|
||||
|
||||
my $err = $hs->open_index(3, 'database1', 'table1', 'PRIMARY',
|
||||
'f1,f2');
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
|
||||
最初の引数は開く索引に付ける番号です。付けた番号は同一の
|
||||
Net::HandlerSocketオブジェクトについてのみ有効です。第4引数は開く
|
||||
索引の名前で、「PRIMARY」が指定され場合はプライマリキーが開かれま
|
||||
す。第5引数は「,」で区切られた列名のリストです。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
テーブルから索引を使って行を取得するには、execute_singleメソッド
|
||||
を呼びます。
|
||||
|
||||
my $res = $hs->execute_single(3, '=', [ 'foo' ], 1, 0);
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
shift(@$res);
|
||||
|
||||
最初の引数は索引の番号で、同じNet::HandlerSocketオブジェクトへ
|
||||
open_indexで付けたものでなければなりません。第2引数には操作を指定
|
||||
します。現在のバージョンでは、「=」、「>=」、「<=」、「>」、「<」
|
||||
の操作が利用可能です。第3引数は配列への参照で、これは探すべき行の
|
||||
キー値を指定します。配列の長さは索引のキーの個数と同じか少ない数
|
||||
でなければなりません。第4引数と第5引数はそれぞれ、取得する最大行
|
||||
数、取得前に読み飛ばす行数を指定します。取得される列は対応する
|
||||
open_index呼び出しの第5引数で指定されたものになります。
|
||||
|
||||
execute_singleメソッドは常に配列への参照を返します。最初の要素は
|
||||
エラーコードで、これが0ならば成功を表します。残りの要素は列の値で
|
||||
す。もし取得されたデータが複数行の場合は、それが一つの配列へ連結
|
||||
された形で格納されています。例えば、5行3列のデータの場合、次のよ
|
||||
うなコードによってその内容を取得できます。
|
||||
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
shift(@$res);
|
||||
for (my $row = 0; $row < 5; ++$row) {
|
||||
for (my $col = 0; $col < 3; ++$col) {
|
||||
my $value = $res->[$row * 5 + $col];
|
||||
# ...
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
行を更新または削除するには、更に多くの引数を指定して
|
||||
execute_singleメソッドを呼び出します。書き込み処理をするには、
|
||||
対象のNet::HandlerSocketオブジェクトは更新用handlersocketワーカ(既
|
||||
定ではポート9999)へ接続されたものでなくてはなりません。
|
||||
(安全のため、ポート9998は参照処理だけを受け付け、ポート9999は更新
|
||||
処理も受け付けるようになっています。ポート9999は参照処理も受け付
|
||||
けますが、レコードロック等の影響で遅くなります。ポート番号は
|
||||
mysqldの「handlersocket_port」と「handlersocket_port_wr」の設定項
|
||||
目で変更できます。)
|
||||
|
||||
my $args = { host => 'localhost', port => 9999 };
|
||||
my $hs = new Net::HandlerSocket($args);
|
||||
|
||||
my $res = $hs->execute_single(3, '=', [ 'bar' ], 1, 0, 'U',
|
||||
[ 'fubar', 'hoge' ]);
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
my $num_updated_rows = $res->[1];
|
||||
|
||||
my $res = $hs->execute_single(3, '=', [ 'baz' ], 1, 0, 'D');
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
my $num_deleted_rows = $res->[1];
|
||||
|
||||
execute_singleの第6引数は変更処理の種類を指定します。現在のバー
|
||||
ジョンでは「U」と「D」が利用可能です。「U」については、第7引数で
|
||||
新しい値を指定します。更新される列は、対応するopen_index呼び出し
|
||||
の第5引数で指定されたものになります。「D」については第7引数は省
|
||||
略できます。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
execute_singleメソッドは列の挿入にも使用できます。
|
||||
|
||||
my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]);
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
my $num_inserted_rows = $res->[1];
|
||||
|
||||
第3引数は、対応するopen_index呼び出しの第5引数の列リストと同じだ
|
||||
けの長さの配列への参照でなければなりません。open_index呼び出しの
|
||||
第5引数に指定されていない列については、その列の既定値がセットされ
|
||||
ます。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
execute_multiメソッドを使えば、複数のリクエストを一つの呼び出しで
|
||||
実行することができます。これはリクエストを個別に実行するより高速
|
||||
です。
|
||||
|
||||
my $rarr = $hs->execute_multi([
|
||||
[ 0, '>=', [ 'foo' ], 5, 0 ],
|
||||
[ 2, '=', [ 'bar' ], 1, 0 ],
|
||||
[ 4, '<', [ 'baz' ], 10, 5 ],
|
||||
]);
|
||||
for my $res (@$rarr) {
|
||||
die $hs->get_error() if $res->[0] != 0;
|
||||
shift(@$res);
|
||||
# ...
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
エラーが起こると返値の配列参照の最初の要素が0以外になります。負の
|
||||
数の場合はI/Oエラーが起こったことを示し、その場合はその
|
||||
Net::HandlerSocketオブジェクトは破棄するべきです。正の値の場合は
|
||||
接続は維持されているため、そのオブジェクトはそれ以後も再利用でき
|
||||
ます。
|
||||
|
94
plugin/handler_socket/docs-ja/protocol.ja.txt
Normal file
94
plugin/handler_socket/docs-ja/protocol.ja.txt
Normal file
@ -0,0 +1,94 @@
|
||||
|
||||
-----------------------------------------------------------------
|
||||
handlersocketの通信プロトコル
|
||||
|
||||
-----------------------------------------------------------------
|
||||
構文
|
||||
|
||||
・コマンド行は改行(LF)で終わる。
|
||||
・コマンド行は複数のトークンからなり、トークン間はTABで区切られる。
|
||||
・トークンはNULLトークンか、文字列トークンのいずれか。
|
||||
・NULLトークンは単一のNUL文字であらわされる。
|
||||
・文字列トークンは、0バイト以上の文字列であらわされる。ただし0x10
|
||||
未満の文字については0x01を前置し、0x40を加えたコードであらわさ
|
||||
れる。それ以外の文字はその文字自身のコードであらわされる。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
リクエストとレスポンス
|
||||
|
||||
・接続が確立した直後の状態では、まずクライアントがコマンド行を送
|
||||
る。(リクエスト)
|
||||
・サーバはクライアントが送ったリクエストと丁度同じ数のコマンド行
|
||||
を返す。(レスポンス)
|
||||
・リクエストはパイプライン化してよい。つまりクライアントは前に
|
||||
送ったリクエストに対する返事を待たずに次のリクエストを送っても
|
||||
よい。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
リクエスト
|
||||
|
||||
・open_index命令は次のような構文を持つ。
|
||||
'P' indexid dbname tablename indexname fieldlist
|
||||
indexidは開いている索引に付けられる番号で、同一接続上で後に実行
|
||||
する命令の、対象索引を指定するために使われる。dbname、tablename、
|
||||
indexnameはそれぞれ開きたいDB、テーブル、索引の名前。索引の名前
|
||||
として"PRIMARY"を指定するとプライマリキーが開かれる。fieldlist
|
||||
はカンマ区切りの列名のリスト。
|
||||
・find命令は次のような構文を持つ。
|
||||
indexid op nflds v1 ... vn limit offset
|
||||
indexidは実行対象の索引を指定する。opは索引検索の演算子(後述)。
|
||||
v1からvnは可変長で、その個数はnflds。nfldsはindexidで指定された
|
||||
open_index命令のindexnameの索引のfieldlistのフィールド数に等し
|
||||
いか小さくなくてはならない。m2からmkは可変長で、その個数は
|
||||
indexidで指定されたopen_index命令が発行された際のfieldlistに一
|
||||
致しなければならない。コマンド行のlimit以降は省略できる。limit
|
||||
とoffsetは、検索条件に合致する列のうちレスポンスに返す列数の上
|
||||
限と、スキップする列数。limitとoffsetを省略した場合はそれぞれ1
|
||||
と0が指定されたときと同じ動作をする。find命令はレスポンスとして、
|
||||
条件に合致した列のリストを返す。opとして指定できる演算子は次の
|
||||
とおり。
|
||||
'=' - v1 ... vnと一致するものを取得
|
||||
'>' - v1 ... vnより大きいものを昇順に取得
|
||||
'>=' - v1 ... vnに一致するか大きいものを昇順に取得
|
||||
'<' - v1 ... vnより小さいものを降順に取得
|
||||
'<=' - v1 ... vnに一致するか等しいものを降順に取得
|
||||
nfldsが1より大きい(v1 ... vnが2個以上)ときは辞書式順序で比較さ
|
||||
れる。
|
||||
・find_modify命令は次のような構文を持つ。
|
||||
indexid op nflds v1 ... vn limit offset modop m1 ... mk
|
||||
modopより前の部分はfind命令と同等で、これによって操作対象の行を
|
||||
指定する。その操作対象の行に対しmodopで指定された変更処理を実行
|
||||
する。m1 ... mkは可変長で、省略できる。modopは次いずれか。
|
||||
'U' - indexidで指定されたopen_index命令のfieldlist列
|
||||
の内容を、m1 ... mkの値で更新する。
|
||||
'D' - 対象の行を削除する。m1 ... mkの値は無視される。
|
||||
・insert命令はのような構文を持つ。
|
||||
indexid '+' nflds v1 ... vn
|
||||
indexidで指定されたテーブルに、列を挿入する。v1 ... vnは可変長
|
||||
で、その個数はnflds。nfldsはindexidで指定されたopen_index命令の
|
||||
indexnameの索引のfieldlistのフィールド数に等しいか小さくなくて
|
||||
はならない。
|
||||
|
||||
-----------------------------------------------------------------
|
||||
レスポンス
|
||||
|
||||
・open_index命令が成功したとき、レスポンスは次の構文を持つ。
|
||||
'0' '1'
|
||||
・find命令が成功したとき、レスポンスは次の構文を持つ。
|
||||
'0' nflds v1 ... vn
|
||||
nfldsは結果セットの列の数をあらわす。v1 ... vnは可変長で、その
|
||||
長さはnfldsの整数倍。v1 ... vnは空のこともあり、それは条件に合
|
||||
致するレコードが存在しなかったことをあらわす。結果セットが複数
|
||||
行になったときはv1 ... vnの長さがnfldsの2倍以上となり、最初の
|
||||
行から順にv1 ... vnにセットされる。
|
||||
・modify命令が成功したとき、レスポンスは次の構文を持つ。
|
||||
'0' '1' nummod
|
||||
nummodは変更が施された行数。nummodが0のときは変更された行が無
|
||||
かったことをあらわす。
|
||||
・insert命令が成功したとき、レスポンスは次の構文を持つ。
|
||||
'0' '1'
|
||||
・命令が失敗したとき、レスポンスは命令に関わらず次の構文を持つ。
|
||||
err '1' message
|
||||
errは0以外の数値で、エラーコードをあらわす。messageは人間可読な
|
||||
エラーメッセージ。ただしmessageが無いこともある。
|
||||
|
27
plugin/handler_socket/handlersocket/COPYRIGHT.txt
Normal file
27
plugin/handler_socket/handlersocket/COPYRIGHT.txt
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
Copyright (c) 2010 DeNA Co.,Ltd.
|
||||
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 DeNA Co.,Ltd. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DeNA Co.,Ltd. "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 DeNA Co.,Ltd. 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.
|
||||
|
11
plugin/handler_socket/handlersocket/Makefile.am
Normal file
11
plugin/handler_socket/handlersocket/Makefile.am
Normal file
@ -0,0 +1,11 @@
|
||||
CXXFLAGS += -fimplicit-templates
|
||||
pkgplugindir = $(PLUGIN_DIR)
|
||||
noinst_HEADERS = database.hpp hstcpsvr.hpp hstcpsvr_worker.hpp mysql_incl.hpp
|
||||
pkgplugin_LTLIBRARIES = handlersocket.la
|
||||
handlersocket_la_LDFLAGS = -module ../libhsclient/libhsclient.la
|
||||
handlersocket_la_CFLAGS = $(MYSQL_INC) $(MYSQL_CFLAGS) $(AM_CFLAGS) \
|
||||
-I$(srcdir)/../libhsclient
|
||||
handlersocket_la_CXXFLAGS = $(MYSQL_INC) $(MYSQL_CFLAGS) $(AM_CFLAGS) \
|
||||
-I$(srcdir)/../libhsclient
|
||||
handlersocket_la_SOURCES = database.cpp handlersocket.cpp \
|
||||
hstcpsvr_worker.cpp hstcpsvr.cpp
|
31
plugin/handler_socket/handlersocket/Makefile.plain.template
Normal file
31
plugin/handler_socket/handlersocket/Makefile.plain.template
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
MYSQL_INC = HANDLERSOCKET_MYSQL_INC
|
||||
MYSQL_LIB = HANDLERSOCKET_MYSQL_LIB
|
||||
|
||||
CXX = g++ -Wall -g -fno-rtti -fno-exceptions -fPIC -DPIC
|
||||
LIBS = $(MYSQL_LIB) -lhsclient -lpthread -lz
|
||||
CXXFLAGS = -I/usr/include/handlersocket $(MYSQL_INC)
|
||||
LDFLAGS =
|
||||
|
||||
CXXFLAGS += -O3 -DNDEBUG
|
||||
|
||||
HANDLERSOCKET_OBJS = database.o hstcpsvr.o hstcpsvr_worker.o
|
||||
|
||||
all: handlersocket.so
|
||||
|
||||
handlersocket.so: $(HANDLERSOCKET_OBJS) handlersocket.cpp
|
||||
$(CXX) $(CXXFLAGS) -fno-strict-aliasing -shared $^ -o $@ $(LDFLAGS) \
|
||||
-Wl,-soname -Wl,$@ $(LIBS)
|
||||
clean:
|
||||
rm -f *.a *.so *.o
|
||||
|
||||
LIBDIR = $(shell \
|
||||
if [ -e /usr/lib64/mysql ]; then echo /usr/lib64; else echo /usr/lib; fi)
|
||||
|
||||
install: handlersocket.so
|
||||
sudo sh -c 'ulimit -c unlimited ; /etc/init.d/mysql stop ; \
|
||||
cp handlersocket.so handlersocket.so.cpy && \
|
||||
mv handlersocket.so.cpy \
|
||||
$(LIBDIR)/mysql/plugin/handlersocket.so && \
|
||||
/etc/init.d/mysql start'
|
||||
|
1143
plugin/handler_socket/handlersocket/database.cpp
Normal file
1143
plugin/handler_socket/handlersocket/database.cpp
Normal file
File diff suppressed because it is too large
Load Diff
130
plugin/handler_socket/handlersocket/database.hpp
Normal file
130
plugin/handler_socket/handlersocket/database.hpp
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_DATABASE_HPP
|
||||
#define DENA_DATABASE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "string_buffer.hpp"
|
||||
#include "string_ref.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct database_i;
|
||||
typedef std::auto_ptr<volatile database_i> database_ptr;
|
||||
|
||||
struct dbcontext_i;
|
||||
typedef std::auto_ptr<dbcontext_i> dbcontext_ptr;
|
||||
|
||||
struct database_i {
|
||||
virtual ~database_i() { }
|
||||
virtual dbcontext_ptr create_context(bool for_write) volatile = 0;
|
||||
virtual void stop() volatile = 0;
|
||||
virtual const config& get_conf() const volatile = 0;
|
||||
static database_ptr create(const config& conf);
|
||||
};
|
||||
|
||||
struct prep_stmt {
|
||||
typedef std::vector<uint32_t> fields_type;
|
||||
private:
|
||||
dbcontext_i *dbctx; /* must be valid while *this is alive */
|
||||
size_t table_id; /* a prep_stmt object holds a refcount of the table */
|
||||
size_t idxnum;
|
||||
fields_type ret_fields;
|
||||
fields_type filter_fields;
|
||||
public:
|
||||
prep_stmt();
|
||||
prep_stmt(dbcontext_i *c, size_t tbl, size_t idx, const fields_type& rf,
|
||||
const fields_type& ff);
|
||||
~prep_stmt();
|
||||
prep_stmt(const prep_stmt& x);
|
||||
prep_stmt& operator =(const prep_stmt& x);
|
||||
public:
|
||||
size_t get_table_id() const { return table_id; }
|
||||
size_t get_idxnum() const { return idxnum; }
|
||||
const fields_type& get_ret_fields() const { return ret_fields; }
|
||||
const fields_type& get_filter_fields() const { return filter_fields; }
|
||||
};
|
||||
|
||||
struct dbcallback_i {
|
||||
virtual ~dbcallback_i () { }
|
||||
virtual void dbcb_set_prep_stmt(size_t pst_id, const prep_stmt& v) = 0;
|
||||
virtual const prep_stmt *dbcb_get_prep_stmt(size_t pst_id) const = 0;
|
||||
virtual void dbcb_resp_short(uint32_t code, const char *msg) = 0;
|
||||
virtual void dbcb_resp_short_num(uint32_t code, uint32_t value) = 0;
|
||||
virtual void dbcb_resp_begin(size_t num_flds) = 0;
|
||||
virtual void dbcb_resp_entry(const char *fld, size_t fldlen) = 0;
|
||||
virtual void dbcb_resp_end() = 0;
|
||||
virtual void dbcb_resp_cancel() = 0;
|
||||
};
|
||||
|
||||
enum record_filter_type {
|
||||
record_filter_type_skip = 0,
|
||||
record_filter_type_break = 1,
|
||||
};
|
||||
|
||||
struct record_filter {
|
||||
record_filter_type filter_type;
|
||||
string_ref op;
|
||||
uint32_t ff_offset; /* offset in filter_fields */
|
||||
string_ref val;
|
||||
record_filter() : filter_type(record_filter_type_skip), ff_offset(0) { }
|
||||
};
|
||||
|
||||
struct cmd_exec_args {
|
||||
const prep_stmt *pst;
|
||||
string_ref op;
|
||||
const string_ref *kvals;
|
||||
size_t kvalslen;
|
||||
uint32_t limit;
|
||||
uint32_t skip;
|
||||
string_ref mod_op;
|
||||
const string_ref *uvals; /* size must be pst->retfieelds.size() */
|
||||
const record_filter *filters;
|
||||
cmd_exec_args() : pst(0), kvals(0), kvalslen(0), limit(0), skip(0),
|
||||
uvals(0), filters(0) { }
|
||||
};
|
||||
|
||||
struct dbcontext_i {
|
||||
virtual ~dbcontext_i() { }
|
||||
virtual void init_thread(const void *stack_bottom,
|
||||
volatile int& shutdown_flag) = 0;
|
||||
virtual void term_thread() = 0;
|
||||
virtual bool check_alive() = 0;
|
||||
virtual void lock_tables_if() = 0;
|
||||
virtual void unlock_tables_if() = 0;
|
||||
virtual bool get_commit_error() = 0;
|
||||
virtual void clear_error() = 0;
|
||||
virtual void close_tables_if() = 0;
|
||||
virtual void table_addref(size_t tbl_id) = 0; /* TODO: hide */
|
||||
virtual void table_release(size_t tbl_id) = 0; /* TODO: hide */
|
||||
virtual void cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn,
|
||||
const char *tbl, const char *idx, const char *retflds,
|
||||
const char *filflds) = 0;
|
||||
virtual void cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args)
|
||||
= 0;
|
||||
virtual void set_statistics(size_t num_conns, size_t num_active) = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
extern unsigned long long int open_tables_count;
|
||||
extern unsigned long long int close_tables_count;
|
||||
extern unsigned long long int lock_tables_count;
|
||||
extern unsigned long long int unlock_tables_count;
|
||||
#if 0
|
||||
extern unsigned long long int index_exec_count;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
216
plugin/handler_socket/handlersocket/handlersocket.cpp
Normal file
216
plugin/handler_socket/handlersocket/handlersocket.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "hstcpsvr.hpp"
|
||||
#include "string_util.hpp"
|
||||
#include "mysql_incl.hpp"
|
||||
|
||||
#define DBG_LOG \
|
||||
if (dena::verbose_level >= 100) { \
|
||||
fprintf(stderr, "%s %p\n", __PRETTY_FUNCTION__, this); \
|
||||
}
|
||||
#define DBG_DO(x) if (dena::verbose_level >= 100) { x; }
|
||||
|
||||
#define DBG_DIR(x)
|
||||
|
||||
using namespace dena;
|
||||
|
||||
static char *handlersocket_address = 0;
|
||||
static char *handlersocket_port = 0;
|
||||
static char *handlersocket_port_wr = 0;
|
||||
static unsigned int handlersocket_epoll = 1;
|
||||
static unsigned int handlersocket_threads = 32;
|
||||
static unsigned int handlersocket_threads_wr = 1;
|
||||
static unsigned int handlersocket_timeout = 30;
|
||||
static unsigned int handlersocket_backlog = 32768;
|
||||
static unsigned int handlersocket_sndbuf = 0;
|
||||
static unsigned int handlersocket_rcvbuf = 0;
|
||||
static unsigned int handlersocket_readsize = 0;
|
||||
static unsigned int handlersocket_accept_balance = 0;
|
||||
static unsigned int handlersocket_wrlock_timeout = 0;
|
||||
static char *handlersocket_plain_secret = 0;
|
||||
static char *handlersocket_plain_secret_wr = 0;
|
||||
|
||||
struct daemon_handlersocket_data {
|
||||
hstcpsvr_ptr hssvr_rd;
|
||||
hstcpsvr_ptr hssvr_wr;
|
||||
};
|
||||
|
||||
static int
|
||||
daemon_handlersocket_init(void *p)
|
||||
{
|
||||
DENA_VERBOSE(10, fprintf(stderr, "handlersocket: initialized\n"));
|
||||
config conf;
|
||||
conf["use_epoll"] = handlersocket_epoll ? "1" : "0";
|
||||
if (handlersocket_address) {
|
||||
conf["host"] = handlersocket_address;
|
||||
}
|
||||
if (handlersocket_port) {
|
||||
conf["port"] = handlersocket_port;
|
||||
}
|
||||
/*
|
||||
* unix domain socket
|
||||
* conf["host"] = "/";
|
||||
* conf["port"] = "/tmp/handlersocket";
|
||||
*/
|
||||
if (handlersocket_threads > 0) {
|
||||
conf["num_threads"] = to_stdstring(handlersocket_threads);
|
||||
} else {
|
||||
conf["num_threads"] = "1";
|
||||
}
|
||||
conf["timeout"] = to_stdstring(handlersocket_timeout);
|
||||
conf["listen_backlog"] = to_stdstring(handlersocket_backlog);
|
||||
conf["sndbuf"] = to_stdstring(handlersocket_sndbuf);
|
||||
conf["rcvbuf"] = to_stdstring(handlersocket_rcvbuf);
|
||||
conf["readsize"] = to_stdstring(handlersocket_readsize);
|
||||
conf["accept_balance"] = to_stdstring(handlersocket_accept_balance);
|
||||
conf["wrlock_timeout"] = to_stdstring(handlersocket_wrlock_timeout);
|
||||
std::auto_ptr<daemon_handlersocket_data> ap(new daemon_handlersocket_data);
|
||||
if (handlersocket_port != 0 && handlersocket_port_wr != handlersocket_port) {
|
||||
conf["port"] = handlersocket_port;
|
||||
if (handlersocket_plain_secret) {
|
||||
conf["plain_secret"] = handlersocket_plain_secret;
|
||||
}
|
||||
ap->hssvr_rd = hstcpsvr_i::create(conf);
|
||||
ap->hssvr_rd->start_listen();
|
||||
}
|
||||
if (handlersocket_port_wr != 0) {
|
||||
if (handlersocket_threads_wr > 0) {
|
||||
conf["num_threads"] = to_stdstring(handlersocket_threads_wr);
|
||||
}
|
||||
conf["port"] = handlersocket_port_wr;
|
||||
conf["for_write"] = "1";
|
||||
conf["plain_secret"] = "";
|
||||
if (handlersocket_plain_secret_wr) {
|
||||
conf["plain_secret"] = handlersocket_plain_secret_wr;
|
||||
}
|
||||
ap->hssvr_wr = hstcpsvr_i::create(conf);
|
||||
ap->hssvr_wr->start_listen();
|
||||
}
|
||||
st_plugin_int *const plugin = static_cast<st_plugin_int *>(p);
|
||||
plugin->data = ap.release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
daemon_handlersocket_deinit(void *p)
|
||||
{
|
||||
DENA_VERBOSE(10, fprintf(stderr, "handlersocket: terminated\n"));
|
||||
st_plugin_int *const plugin = static_cast<st_plugin_int *>(p);
|
||||
daemon_handlersocket_data *ptr =
|
||||
static_cast<daemon_handlersocket_data *>(plugin->data);
|
||||
delete ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct st_mysql_daemon daemon_handlersocket_plugin = {
|
||||
MYSQL_DAEMON_INTERFACE_VERSION
|
||||
};
|
||||
|
||||
static MYSQL_SYSVAR_UINT(verbose, dena::verbose_level, 0,
|
||||
"0..10000", 0, 0, 10 /* default */, 0, 10000, 0);
|
||||
static MYSQL_SYSVAR_UINT(epoll, handlersocket_epoll, PLUGIN_VAR_READONLY,
|
||||
"0..1", 0, 0, 1 /* default */, 0, 1, 0);
|
||||
static MYSQL_SYSVAR_STR(address, handlersocket_address,
|
||||
PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "", NULL, NULL, NULL);
|
||||
static MYSQL_SYSVAR_STR(port, handlersocket_port,
|
||||
PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "", NULL, NULL, NULL);
|
||||
static MYSQL_SYSVAR_STR(port_wr, handlersocket_port_wr,
|
||||
PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "", NULL, NULL, NULL);
|
||||
static MYSQL_SYSVAR_UINT(threads, handlersocket_threads, PLUGIN_VAR_READONLY,
|
||||
"1..3000", 0, 0, 16 /* default */, 1, 3000, 0);
|
||||
static MYSQL_SYSVAR_UINT(threads_wr, handlersocket_threads_wr,
|
||||
PLUGIN_VAR_READONLY, "1..3000", 0, 0, 1 /* default */, 1, 3000, 0);
|
||||
static MYSQL_SYSVAR_UINT(timeout, handlersocket_timeout, PLUGIN_VAR_READONLY,
|
||||
"30..3600", 0, 0, 300 /* default */, 30, 3600, 0);
|
||||
static MYSQL_SYSVAR_UINT(backlog, handlersocket_backlog, PLUGIN_VAR_READONLY,
|
||||
"5..1000000", 0, 0, 32768 /* default */, 5, 1000000, 0);
|
||||
static MYSQL_SYSVAR_UINT(sndbuf, handlersocket_sndbuf, PLUGIN_VAR_READONLY,
|
||||
"0..16777216", 0, 0, 0 /* default */, 0, 16777216, 0);
|
||||
static MYSQL_SYSVAR_UINT(rcvbuf, handlersocket_rcvbuf, PLUGIN_VAR_READONLY,
|
||||
"0..16777216", 0, 0, 0 /* default */, 0, 16777216, 0);
|
||||
static MYSQL_SYSVAR_UINT(readsize, handlersocket_readsize, PLUGIN_VAR_READONLY,
|
||||
"0..16777216", 0, 0, 0 /* default */, 0, 16777216, 0);
|
||||
static MYSQL_SYSVAR_UINT(accept_balance, handlersocket_accept_balance,
|
||||
PLUGIN_VAR_READONLY, "0..10000", 0, 0, 0 /* default */, 0, 10000, 0);
|
||||
static MYSQL_SYSVAR_UINT(wrlock_timeout, handlersocket_wrlock_timeout,
|
||||
PLUGIN_VAR_READONLY, "0..3600", 0, 0, 12 /* default */, 0, 3600, 0);
|
||||
static MYSQL_SYSVAR_STR(plain_secret, handlersocket_plain_secret,
|
||||
PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "", NULL, NULL, NULL);
|
||||
static MYSQL_SYSVAR_STR(plain_secret_wr, handlersocket_plain_secret_wr,
|
||||
PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "", NULL, NULL, NULL);
|
||||
|
||||
|
||||
/* warning: type-punning to incomplete type might break strict-aliasing
|
||||
* rules */
|
||||
static struct st_mysql_sys_var *daemon_handlersocket_system_variables[] = {
|
||||
MYSQL_SYSVAR(verbose),
|
||||
MYSQL_SYSVAR(address),
|
||||
MYSQL_SYSVAR(port),
|
||||
MYSQL_SYSVAR(port_wr),
|
||||
MYSQL_SYSVAR(epoll),
|
||||
MYSQL_SYSVAR(threads),
|
||||
MYSQL_SYSVAR(threads_wr),
|
||||
MYSQL_SYSVAR(timeout),
|
||||
MYSQL_SYSVAR(backlog),
|
||||
MYSQL_SYSVAR(sndbuf),
|
||||
MYSQL_SYSVAR(rcvbuf),
|
||||
MYSQL_SYSVAR(readsize),
|
||||
MYSQL_SYSVAR(accept_balance),
|
||||
MYSQL_SYSVAR(wrlock_timeout),
|
||||
MYSQL_SYSVAR(plain_secret),
|
||||
MYSQL_SYSVAR(plain_secret_wr),
|
||||
0
|
||||
};
|
||||
|
||||
static SHOW_VAR hs_status_variables[] = {
|
||||
{"table_open", (char*) &open_tables_count, SHOW_LONGLONG},
|
||||
{"table_close", (char*) &close_tables_count, SHOW_LONGLONG},
|
||||
{"table_lock", (char*) &lock_tables_count, SHOW_LONGLONG},
|
||||
{"table_unlock", (char*) &unlock_tables_count, SHOW_LONGLONG},
|
||||
#if 0
|
||||
{"index_exec", (char*) &index_exec_count, SHOW_LONGLONG},
|
||||
#endif
|
||||
{NullS, NullS, SHOW_LONG}
|
||||
};
|
||||
|
||||
static int show_hs_vars(THD *thd, SHOW_VAR *var, char *buff)
|
||||
{
|
||||
var->type= SHOW_ARRAY;
|
||||
var->value= (char *) &hs_status_variables;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SHOW_VAR daemon_handlersocket_status_variables[] = {
|
||||
{"Hs", (char*) show_hs_vars, SHOW_FUNC},
|
||||
{NullS, NullS, SHOW_LONG}
|
||||
};
|
||||
|
||||
|
||||
mysql_declare_plugin(handlersocket)
|
||||
{
|
||||
MYSQL_DAEMON_PLUGIN,
|
||||
&daemon_handlersocket_plugin,
|
||||
"handlersocket",
|
||||
"higuchi dot akira at dena dot jp",
|
||||
"",
|
||||
PLUGIN_LICENSE_BSD,
|
||||
daemon_handlersocket_init,
|
||||
daemon_handlersocket_deinit,
|
||||
0x0100 /* 1.0 */,
|
||||
daemon_handlersocket_status_variables,
|
||||
daemon_handlersocket_system_variables,
|
||||
0
|
||||
}
|
||||
mysql_declare_plugin_end;
|
||||
|
@ -0,0 +1,29 @@
|
||||
Summary: handlersocket plugin for mysql
|
||||
Name: handlersocket
|
||||
Version: HANDLERSOCKET_VERSION
|
||||
Release: 1%{?dist}
|
||||
Group: System Environment/Libraries
|
||||
License: BSD
|
||||
Source: handlersocket.tar.gz
|
||||
Packager: Akira Higuchi <higuchi dot akira at dena dot jp>
|
||||
BuildRoot: /var/tmp/%{name}-%{version}-root
|
||||
|
||||
%description
|
||||
|
||||
%prep
|
||||
%setup -n %{name}
|
||||
|
||||
%define _use_internal_dependency_generator 0
|
||||
|
||||
%build
|
||||
make -f Makefile.plain
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_libdir}/mysql/plugin
|
||||
install -m 755 handlersocket.so $RPM_BUILD_ROOT/%{_libdir}/mysql/plugin/
|
||||
|
||||
%files
|
||||
%defattr(-, root, root)
|
||||
%{_libdir}/mysql/plugin/*.so
|
||||
|
149
plugin/handler_socket/handlersocket/hstcpsvr.cpp
Normal file
149
plugin/handler_socket/handlersocket/hstcpsvr.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "hstcpsvr.hpp"
|
||||
#include "hstcpsvr_worker.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "fatal.hpp"
|
||||
#include "auto_ptrcontainer.hpp"
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct worker_throbj {
|
||||
worker_throbj(const hstcpsvr_worker_arg& arg)
|
||||
: worker(hstcpsvr_worker_i::create(arg)) { }
|
||||
void operator ()() {
|
||||
worker->run();
|
||||
}
|
||||
hstcpsvr_worker_ptr worker;
|
||||
};
|
||||
|
||||
struct hstcpsvr : public hstcpsvr_i, private noncopyable {
|
||||
hstcpsvr(const config& c);
|
||||
~hstcpsvr();
|
||||
virtual std::string start_listen();
|
||||
private:
|
||||
hstcpsvr_shared_c cshared;
|
||||
volatile hstcpsvr_shared_v vshared;
|
||||
typedef thread<worker_throbj> worker_thread_type;
|
||||
typedef auto_ptrcontainer< std::vector<worker_thread_type *> > threads_type;
|
||||
threads_type threads;
|
||||
std::vector<unsigned int> thread_num_conns_vec;
|
||||
private:
|
||||
void stop_workers();
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
check_nfile(size_t nfile)
|
||||
{
|
||||
struct rlimit rl;
|
||||
const int r = getrlimit(RLIMIT_NOFILE, &rl);
|
||||
if (r != 0) {
|
||||
fatal_abort("check_nfile: getrlimit failed");
|
||||
}
|
||||
if (rl.rlim_cur < static_cast<rlim_t>(nfile + 1000)) {
|
||||
fprintf(stderr,
|
||||
"[Warning] handlersocket: open_files_limit is too small.\n");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
hstcpsvr::hstcpsvr(const config& c)
|
||||
: cshared(), vshared()
|
||||
{
|
||||
vshared.shutdown = 0;
|
||||
cshared.conf = c; /* copy */
|
||||
if (cshared.conf["port"] == "") {
|
||||
cshared.conf["port"] = "9999";
|
||||
}
|
||||
cshared.num_threads = cshared.conf.get_int("num_threads", 32);
|
||||
cshared.sockargs.nonblocking = cshared.conf.get_int("nonblocking", 1);
|
||||
cshared.sockargs.use_epoll = cshared.conf.get_int("use_epoll", 1);
|
||||
if (cshared.sockargs.use_epoll) {
|
||||
cshared.sockargs.nonblocking = 1;
|
||||
}
|
||||
cshared.readsize = cshared.conf.get_int("readsize", 1);
|
||||
cshared.nb_conn_per_thread = cshared.conf.get_int("conn_per_thread", 1024);
|
||||
cshared.for_write_flag = cshared.conf.get_int("for_write", 0);
|
||||
cshared.plain_secret = cshared.conf.get_str("plain_secret", "");
|
||||
cshared.require_auth = !cshared.plain_secret.empty();
|
||||
cshared.sockargs.set(cshared.conf);
|
||||
cshared.dbptr = database_i::create(c);
|
||||
check_nfile(cshared.num_threads * cshared.nb_conn_per_thread);
|
||||
thread_num_conns_vec.resize(cshared.num_threads);
|
||||
cshared.thread_num_conns = thread_num_conns_vec.empty()
|
||||
? 0 : &thread_num_conns_vec[0];
|
||||
}
|
||||
|
||||
hstcpsvr::~hstcpsvr()
|
||||
{
|
||||
stop_workers();
|
||||
}
|
||||
|
||||
std::string
|
||||
hstcpsvr::start_listen()
|
||||
{
|
||||
std::string err;
|
||||
if (threads.size() != 0) {
|
||||
return "start_listen: already running";
|
||||
}
|
||||
if (socket_bind(cshared.listen_fd, cshared.sockargs, err) != 0) {
|
||||
return "bind: " + err;
|
||||
}
|
||||
DENA_VERBOSE(20, fprintf(stderr, "bind done\n"));
|
||||
const size_t stack_size = std::max(
|
||||
cshared.conf.get_int("stack_size", 1 * 1024LL * 1024), 8 * 1024LL * 1024);
|
||||
for (long i = 0; i < cshared.num_threads; ++i) {
|
||||
hstcpsvr_worker_arg arg;
|
||||
arg.cshared = &cshared;
|
||||
arg.vshared = &vshared;
|
||||
arg.worker_id = i;
|
||||
std::auto_ptr< thread<worker_throbj> > thr(
|
||||
new thread<worker_throbj>(arg, stack_size));
|
||||
threads.push_back_ptr(thr);
|
||||
}
|
||||
DENA_VERBOSE(20, fprintf(stderr, "threads created\n"));
|
||||
for (size_t i = 0; i < threads.size(); ++i) {
|
||||
threads[i]->start();
|
||||
}
|
||||
DENA_VERBOSE(20, fprintf(stderr, "threads started\n"));
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr::stop_workers()
|
||||
{
|
||||
vshared.shutdown = 1;
|
||||
for (size_t i = 0; i < threads.size(); ++i) {
|
||||
threads[i]->join();
|
||||
}
|
||||
threads.clear();
|
||||
}
|
||||
|
||||
hstcpsvr_ptr
|
||||
hstcpsvr_i::create(const config& conf)
|
||||
{
|
||||
return hstcpsvr_ptr(new hstcpsvr(conf));
|
||||
}
|
||||
|
||||
};
|
||||
|
58
plugin/handler_socket/handlersocket/hstcpsvr.hpp
Normal file
58
plugin/handler_socket/handlersocket/hstcpsvr.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_HSTCPSVR_HPP
|
||||
#define DENA_HSTCPSVR_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "mutex.hpp"
|
||||
#include "auto_file.hpp"
|
||||
#include "database.hpp"
|
||||
#include "config.hpp"
|
||||
#include "socket.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct hstcpsvr_shared_c {
|
||||
config conf;
|
||||
long num_threads;
|
||||
long nb_conn_per_thread;
|
||||
bool for_write_flag;
|
||||
bool require_auth;
|
||||
std::string plain_secret;
|
||||
int readsize;
|
||||
socket_args sockargs;
|
||||
auto_file listen_fd;
|
||||
database_ptr dbptr;
|
||||
volatile unsigned int *thread_num_conns; /* 0 .. num_threads-1 */
|
||||
hstcpsvr_shared_c() : num_threads(0), nb_conn_per_thread(100),
|
||||
for_write_flag(false), require_auth(false), readsize(0),
|
||||
thread_num_conns(0) { }
|
||||
};
|
||||
|
||||
struct hstcpsvr_shared_v : public mutex {
|
||||
int shutdown;
|
||||
hstcpsvr_shared_v() : shutdown(0) { }
|
||||
};
|
||||
|
||||
struct hstcpsvr_i;
|
||||
typedef std::auto_ptr<hstcpsvr_i> hstcpsvr_ptr;
|
||||
|
||||
struct hstcpsvr_i {
|
||||
virtual ~hstcpsvr_i() { }
|
||||
virtual std::string start_listen() = 0;
|
||||
static hstcpsvr_ptr create(const config& conf);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
896
plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp
Normal file
896
plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp
Normal file
@ -0,0 +1,896 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdexcept>
|
||||
#include <signal.h>
|
||||
#include <list>
|
||||
#if __linux__
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
#include "hstcpsvr_worker.hpp"
|
||||
#include "string_buffer.hpp"
|
||||
#include "auto_ptrcontainer.hpp"
|
||||
#include "string_util.hpp"
|
||||
#include "escape.hpp"
|
||||
|
||||
#define DBG_FD(x)
|
||||
#define DBG_TR(x)
|
||||
#define DBG_EP(x)
|
||||
|
||||
/* TODO */
|
||||
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct dbconnstate {
|
||||
string_buffer readbuf;
|
||||
string_buffer writebuf;
|
||||
std::vector<prep_stmt> prep_stmts;
|
||||
size_t resp_begin_pos;
|
||||
void reset() {
|
||||
readbuf.clear();
|
||||
writebuf.clear();
|
||||
prep_stmts.clear();
|
||||
resp_begin_pos = 0;
|
||||
}
|
||||
dbconnstate() : resp_begin_pos(0) { }
|
||||
};
|
||||
|
||||
struct hstcpsvr_conn;
|
||||
typedef auto_ptrcontainer< std::list<hstcpsvr_conn *> > hstcpsvr_conns_type;
|
||||
|
||||
struct hstcpsvr_conn : public dbcallback_i {
|
||||
public:
|
||||
auto_file fd;
|
||||
sockaddr_storage addr;
|
||||
socklen_t addr_len;
|
||||
dbconnstate cstate;
|
||||
std::string err;
|
||||
size_t readsize;
|
||||
bool nonblocking;
|
||||
bool read_finished;
|
||||
bool write_finished;
|
||||
time_t nb_last_io;
|
||||
hstcpsvr_conns_type::iterator conns_iter;
|
||||
bool authorized;
|
||||
public:
|
||||
bool closed() const;
|
||||
bool ok_to_close() const;
|
||||
void reset();
|
||||
int accept(const hstcpsvr_shared_c& cshared);
|
||||
bool write_more(bool *more_r = 0);
|
||||
bool read_more(bool *more_r = 0);
|
||||
public:
|
||||
virtual void dbcb_set_prep_stmt(size_t pst_id, const prep_stmt& v);
|
||||
virtual const prep_stmt *dbcb_get_prep_stmt(size_t pst_id) const;
|
||||
virtual void dbcb_resp_short(uint32_t code, const char *msg);
|
||||
virtual void dbcb_resp_short_num(uint32_t code, uint32_t value);
|
||||
virtual void dbcb_resp_begin(size_t num_flds);
|
||||
virtual void dbcb_resp_entry(const char *fld, size_t fldlen);
|
||||
virtual void dbcb_resp_end();
|
||||
virtual void dbcb_resp_cancel();
|
||||
public:
|
||||
hstcpsvr_conn() : addr_len(sizeof(addr)), readsize(4096),
|
||||
nonblocking(false), read_finished(false), write_finished(false),
|
||||
nb_last_io(0), authorized(false) { }
|
||||
};
|
||||
|
||||
bool
|
||||
hstcpsvr_conn::closed() const
|
||||
{
|
||||
return fd.get() < 0;
|
||||
}
|
||||
|
||||
bool
|
||||
hstcpsvr_conn::ok_to_close() const
|
||||
{
|
||||
return write_finished || (read_finished && cstate.writebuf.size() == 0);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::reset()
|
||||
{
|
||||
addr = sockaddr_storage();
|
||||
addr_len = sizeof(addr);
|
||||
cstate.reset();
|
||||
fd.reset();
|
||||
read_finished = false;
|
||||
write_finished = false;
|
||||
}
|
||||
|
||||
int
|
||||
hstcpsvr_conn::accept(const hstcpsvr_shared_c& cshared)
|
||||
{
|
||||
reset();
|
||||
return socket_accept(cshared.listen_fd.get(), fd, cshared.sockargs, addr,
|
||||
addr_len, err);
|
||||
}
|
||||
|
||||
bool
|
||||
hstcpsvr_conn::write_more(bool *more_r)
|
||||
{
|
||||
if (write_finished || cstate.writebuf.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
const size_t wlen = cstate.writebuf.size();
|
||||
ssize_t len = send(fd.get(), cstate.writebuf.begin(), wlen, MSG_NOSIGNAL);
|
||||
if (len <= 0) {
|
||||
if (len == 0 || !nonblocking || errno != EWOULDBLOCK) {
|
||||
cstate.writebuf.clear();
|
||||
write_finished = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
cstate.writebuf.erase_front(len);
|
||||
/* FIXME: reallocate memory if too large */
|
||||
if (more_r) {
|
||||
*more_r = (static_cast<size_t>(len) == wlen);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
hstcpsvr_conn::read_more(bool *more_r)
|
||||
{
|
||||
if (read_finished) {
|
||||
return false;
|
||||
}
|
||||
const size_t block_size = readsize > 4096 ? readsize : 4096;
|
||||
char *wp = cstate.readbuf.make_space(block_size);
|
||||
const ssize_t len = read(fd.get(), wp, block_size);
|
||||
if (len <= 0) {
|
||||
if (len == 0 || !nonblocking || errno != EWOULDBLOCK) {
|
||||
read_finished = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
cstate.readbuf.space_wrote(len);
|
||||
if (more_r) {
|
||||
*more_r = (static_cast<size_t>(len) == block_size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_set_prep_stmt(size_t pst_id, const prep_stmt& v)
|
||||
{
|
||||
if (cstate.prep_stmts.size() <= pst_id) {
|
||||
cstate.prep_stmts.resize(pst_id + 1);
|
||||
}
|
||||
cstate.prep_stmts[pst_id] = v;
|
||||
}
|
||||
|
||||
const prep_stmt *
|
||||
hstcpsvr_conn::dbcb_get_prep_stmt(size_t pst_id) const
|
||||
{
|
||||
if (cstate.prep_stmts.size() <= pst_id) {
|
||||
return 0;
|
||||
}
|
||||
return &cstate.prep_stmts[pst_id];
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_resp_short(uint32_t code, const char *msg)
|
||||
{
|
||||
write_ui32(cstate.writebuf, code);
|
||||
const size_t msglen = strlen(msg);
|
||||
if (msglen != 0) {
|
||||
cstate.writebuf.append_literal("\t1\t");
|
||||
cstate.writebuf.append(msg, msg + msglen);
|
||||
} else {
|
||||
cstate.writebuf.append_literal("\t1");
|
||||
}
|
||||
cstate.writebuf.append_literal("\n");
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_resp_short_num(uint32_t code, uint32_t value)
|
||||
{
|
||||
write_ui32(cstate.writebuf, code);
|
||||
cstate.writebuf.append_literal("\t1\t");
|
||||
write_ui32(cstate.writebuf, value);
|
||||
cstate.writebuf.append_literal("\n");
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_resp_begin(size_t num_flds)
|
||||
{
|
||||
cstate.resp_begin_pos = cstate.writebuf.size();
|
||||
cstate.writebuf.append_literal("0\t");
|
||||
write_ui32(cstate.writebuf, num_flds);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_resp_entry(const char *fld, size_t fldlen)
|
||||
{
|
||||
if (fld != 0) {
|
||||
cstate.writebuf.append_literal("\t");
|
||||
escape_string(cstate.writebuf, fld, fld + fldlen);
|
||||
} else {
|
||||
static const char t[] = "\t\0";
|
||||
cstate.writebuf.append(t, t + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_resp_end()
|
||||
{
|
||||
cstate.writebuf.append_literal("\n");
|
||||
cstate.resp_begin_pos = 0;
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_conn::dbcb_resp_cancel()
|
||||
{
|
||||
cstate.writebuf.resize(cstate.resp_begin_pos);
|
||||
cstate.resp_begin_pos = 0;
|
||||
}
|
||||
|
||||
struct hstcpsvr_worker : public hstcpsvr_worker_i, private noncopyable {
|
||||
hstcpsvr_worker(const hstcpsvr_worker_arg& arg);
|
||||
virtual void run();
|
||||
private:
|
||||
const hstcpsvr_shared_c& cshared;
|
||||
volatile hstcpsvr_shared_v& vshared;
|
||||
long worker_id;
|
||||
dbcontext_ptr dbctx;
|
||||
hstcpsvr_conns_type conns; /* conns refs dbctx */
|
||||
time_t last_check_time;
|
||||
std::vector<pollfd> pfds;
|
||||
#ifdef __linux__
|
||||
std::vector<epoll_event> events_vec;
|
||||
auto_file epoll_fd;
|
||||
#endif
|
||||
bool accept_enabled;
|
||||
int accept_balance;
|
||||
std::vector<record_filter> filters_work;
|
||||
private:
|
||||
int run_one_nb();
|
||||
int run_one_ep();
|
||||
void execute_lines(hstcpsvr_conn& conn);
|
||||
void execute_line(char *start, char *finish, hstcpsvr_conn& conn);
|
||||
void do_open_index(char *start, char *finish, hstcpsvr_conn& conn);
|
||||
void do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
|
||||
char *finish, hstcpsvr_conn& conn);
|
||||
void do_authorization(char *start, char *finish, hstcpsvr_conn& conn);
|
||||
};
|
||||
|
||||
hstcpsvr_worker::hstcpsvr_worker(const hstcpsvr_worker_arg& arg)
|
||||
: cshared(*arg.cshared), vshared(*arg.vshared), worker_id(arg.worker_id),
|
||||
dbctx(cshared.dbptr->create_context(cshared.for_write_flag)),
|
||||
last_check_time(time(0)), accept_enabled(true), accept_balance(0)
|
||||
{
|
||||
#ifdef __linux__
|
||||
if (cshared.sockargs.use_epoll) {
|
||||
epoll_fd.reset(epoll_create(10));
|
||||
if (epoll_fd.get() < 0) {
|
||||
fatal_abort("epoll_create");
|
||||
}
|
||||
epoll_event ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.ptr = 0;
|
||||
if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, cshared.listen_fd.get(), &ev)
|
||||
!= 0) {
|
||||
fatal_abort("epoll_ctl EPOLL_CTL_ADD");
|
||||
}
|
||||
events_vec.resize(10240);
|
||||
}
|
||||
#endif
|
||||
accept_balance = cshared.conf.get_int("accept_balance", 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct thr_init {
|
||||
thr_init(const dbcontext_ptr& dc, volatile int& shutdown_flag) : dbctx(dc) {
|
||||
dbctx->init_thread(this, shutdown_flag);
|
||||
}
|
||||
~thr_init() {
|
||||
dbctx->term_thread();
|
||||
}
|
||||
const dbcontext_ptr& dbctx;
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
void
|
||||
hstcpsvr_worker::run()
|
||||
{
|
||||
thr_init initobj(dbctx, vshared.shutdown);
|
||||
|
||||
#ifdef __linux__
|
||||
if (cshared.sockargs.use_epoll) {
|
||||
while (!vshared.shutdown && dbctx->check_alive()) {
|
||||
run_one_ep();
|
||||
}
|
||||
} else if (cshared.sockargs.nonblocking) {
|
||||
while (!vshared.shutdown && dbctx->check_alive()) {
|
||||
run_one_nb();
|
||||
}
|
||||
} else {
|
||||
/* UNUSED */
|
||||
fatal_abort("run_one");
|
||||
}
|
||||
#else
|
||||
while (!vshared.shutdown && dbctx->check_alive()) {
|
||||
run_one_nb();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
hstcpsvr_worker::run_one_nb()
|
||||
{
|
||||
size_t nfds = 0;
|
||||
/* CLIENT SOCKETS */
|
||||
for (hstcpsvr_conns_type::const_iterator i = conns.begin();
|
||||
i != conns.end(); ++i) {
|
||||
if (pfds.size() <= nfds) {
|
||||
pfds.resize(nfds + 1);
|
||||
}
|
||||
pollfd& pfd = pfds[nfds++];
|
||||
pfd.fd = (*i)->fd.get();
|
||||
short ev = 0;
|
||||
if ((*i)->cstate.writebuf.size() != 0) {
|
||||
ev = POLLOUT;
|
||||
} else {
|
||||
ev = POLLIN;
|
||||
}
|
||||
pfd.events = pfd.revents = ev;
|
||||
}
|
||||
/* LISTENER */
|
||||
{
|
||||
const size_t cpt = cshared.nb_conn_per_thread;
|
||||
const short ev = (cpt > nfds) ? POLLIN : 0;
|
||||
if (pfds.size() <= nfds) {
|
||||
pfds.resize(nfds + 1);
|
||||
}
|
||||
pollfd& pfd = pfds[nfds++];
|
||||
pfd.fd = cshared.listen_fd.get();
|
||||
pfd.events = pfd.revents = ev;
|
||||
}
|
||||
/* POLL */
|
||||
const int npollev = poll(&pfds[0], nfds, 1 * 1000);
|
||||
dbctx->set_statistics(conns.size(), npollev);
|
||||
const time_t now = time(0);
|
||||
size_t j = 0;
|
||||
const short mask_in = ~POLLOUT;
|
||||
const short mask_out = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
|
||||
/* READ */
|
||||
for (hstcpsvr_conns_type::iterator i = conns.begin(); i != conns.end();
|
||||
++i, ++j) {
|
||||
pollfd& pfd = pfds[j];
|
||||
if ((pfd.revents & mask_in) == 0) {
|
||||
continue;
|
||||
}
|
||||
hstcpsvr_conn& conn = **i;
|
||||
if (conn.read_more()) {
|
||||
if (conn.cstate.readbuf.size() > 0) {
|
||||
const char ch = conn.cstate.readbuf.begin()[0];
|
||||
if (ch == 'Q') {
|
||||
vshared.shutdown = 1;
|
||||
} else if (ch == '/') {
|
||||
conn.cstate.readbuf.clear();
|
||||
conn.cstate.writebuf.clear();
|
||||
conn.read_finished = true;
|
||||
conn.write_finished = true;
|
||||
}
|
||||
}
|
||||
conn.nb_last_io = now;
|
||||
}
|
||||
}
|
||||
/* EXECUTE */
|
||||
j = 0;
|
||||
for (hstcpsvr_conns_type::iterator i = conns.begin(); i != conns.end();
|
||||
++i, ++j) {
|
||||
pollfd& pfd = pfds[j];
|
||||
if ((pfd.revents & mask_in) == 0 || (*i)->cstate.readbuf.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
execute_lines(**i);
|
||||
}
|
||||
/* COMMIT */
|
||||
dbctx->unlock_tables_if();
|
||||
const bool commit_error = dbctx->get_commit_error();
|
||||
dbctx->clear_error();
|
||||
/* WRITE/CLOSE */
|
||||
j = 0;
|
||||
for (hstcpsvr_conns_type::iterator i = conns.begin(); i != conns.end();
|
||||
++j) {
|
||||
pollfd& pfd = pfds[j];
|
||||
hstcpsvr_conn& conn = **i;
|
||||
hstcpsvr_conns_type::iterator icur = i;
|
||||
++i;
|
||||
if (commit_error) {
|
||||
conn.reset();
|
||||
continue;
|
||||
}
|
||||
if ((pfd.revents & (mask_out | mask_in)) != 0) {
|
||||
if (conn.write_more()) {
|
||||
conn.nb_last_io = now;
|
||||
}
|
||||
}
|
||||
if (cshared.sockargs.timeout != 0 &&
|
||||
conn.nb_last_io + cshared.sockargs.timeout < now) {
|
||||
conn.reset();
|
||||
}
|
||||
if (conn.closed() || conn.ok_to_close()) {
|
||||
conns.erase_ptr(icur);
|
||||
}
|
||||
}
|
||||
/* ACCEPT */
|
||||
{
|
||||
pollfd& pfd = pfds[nfds - 1];
|
||||
if ((pfd.revents & mask_in) != 0) {
|
||||
std::auto_ptr<hstcpsvr_conn> c(new hstcpsvr_conn());
|
||||
c->nonblocking = true;
|
||||
c->readsize = cshared.readsize;
|
||||
c->accept(cshared);
|
||||
if (c->fd.get() >= 0) {
|
||||
if (fcntl(c->fd.get(), F_SETFL, O_NONBLOCK) != 0) {
|
||||
fatal_abort("F_SETFL O_NONBLOCK");
|
||||
}
|
||||
c->nb_last_io = now;
|
||||
conns.push_back_ptr(c);
|
||||
} else {
|
||||
/* errno == 11 (EAGAIN) is not a fatal error. */
|
||||
DENA_VERBOSE(100, fprintf(stderr,
|
||||
"accept failed: errno=%d (not fatal)\n", errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
DENA_VERBOSE(30, fprintf(stderr, "nb: %p nfds=%zu cns=%zu\n", this, nfds,
|
||||
conns.size()));
|
||||
if (conns.empty()) {
|
||||
dbctx->close_tables_if();
|
||||
}
|
||||
dbctx->set_statistics(conns.size(), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
int
|
||||
hstcpsvr_worker::run_one_ep()
|
||||
{
|
||||
epoll_event *const events = &events_vec[0];
|
||||
const size_t num_events = events_vec.size();
|
||||
const time_t now = time(0);
|
||||
size_t in_count = 0, out_count = 0, accept_count = 0;
|
||||
int nfds = epoll_wait(epoll_fd.get(), events, num_events, 1000);
|
||||
/* READ/ACCEPT */
|
||||
dbctx->set_statistics(conns.size(), nfds);
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
epoll_event& ev = events[i];
|
||||
if ((ev.events & EPOLLIN) == 0) {
|
||||
continue;
|
||||
}
|
||||
hstcpsvr_conn *const conn = static_cast<hstcpsvr_conn *>(ev.data.ptr);
|
||||
if (conn == 0) {
|
||||
/* listener */
|
||||
++accept_count;
|
||||
DBG_EP(fprintf(stderr, "IN listener\n"));
|
||||
std::auto_ptr<hstcpsvr_conn> c(new hstcpsvr_conn());
|
||||
c->nonblocking = true;
|
||||
c->readsize = cshared.readsize;
|
||||
c->accept(cshared);
|
||||
if (c->fd.get() >= 0) {
|
||||
if (fcntl(c->fd.get(), F_SETFL, O_NONBLOCK) != 0) {
|
||||
fatal_abort("F_SETFL O_NONBLOCK");
|
||||
}
|
||||
epoll_event cev;
|
||||
memset(&cev, 0, sizeof(cev));
|
||||
cev.events = EPOLLIN | EPOLLOUT | EPOLLET;
|
||||
cev.data.ptr = c.get();
|
||||
c->nb_last_io = now;
|
||||
const int fd = c->fd.get();
|
||||
conns.push_back_ptr(c);
|
||||
conns.back()->conns_iter = --conns.end();
|
||||
if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, fd, &cev) != 0) {
|
||||
fatal_abort("epoll_ctl EPOLL_CTL_ADD");
|
||||
}
|
||||
} else {
|
||||
DENA_VERBOSE(100, fprintf(stderr,
|
||||
"accept failed: errno=%d (not fatal)\n", errno));
|
||||
}
|
||||
} else {
|
||||
/* client connection */
|
||||
++in_count;
|
||||
DBG_EP(fprintf(stderr, "IN client\n"));
|
||||
bool more_data = false;
|
||||
while (conn->read_more(&more_data)) {
|
||||
DBG_EP(fprintf(stderr, "IN client read_more\n"));
|
||||
conn->nb_last_io = now;
|
||||
if (!more_data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* EXECUTE */
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
epoll_event& ev = events[i];
|
||||
hstcpsvr_conn *const conn = static_cast<hstcpsvr_conn *>(ev.data.ptr);
|
||||
if ((ev.events & EPOLLIN) == 0 || conn == 0 ||
|
||||
conn->cstate.readbuf.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
const char ch = conn->cstate.readbuf.begin()[0];
|
||||
if (ch == 'Q') {
|
||||
vshared.shutdown = 1;
|
||||
} else if (ch == '/') {
|
||||
conn->cstate.readbuf.clear();
|
||||
conn->cstate.writebuf.clear();
|
||||
conn->read_finished = true;
|
||||
conn->write_finished = true;
|
||||
} else {
|
||||
execute_lines(*conn);
|
||||
}
|
||||
}
|
||||
/* COMMIT */
|
||||
dbctx->unlock_tables_if();
|
||||
const bool commit_error = dbctx->get_commit_error();
|
||||
dbctx->clear_error();
|
||||
/* WRITE */
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
epoll_event& ev = events[i];
|
||||
hstcpsvr_conn *const conn = static_cast<hstcpsvr_conn *>(ev.data.ptr);
|
||||
if (commit_error && conn != 0) {
|
||||
conn->reset();
|
||||
continue;
|
||||
}
|
||||
if ((ev.events & EPOLLOUT) == 0) {
|
||||
continue;
|
||||
}
|
||||
++out_count;
|
||||
if (conn == 0) {
|
||||
/* listener */
|
||||
DBG_EP(fprintf(stderr, "OUT listener\n"));
|
||||
} else {
|
||||
/* client connection */
|
||||
DBG_EP(fprintf(stderr, "OUT client\n"));
|
||||
bool more_data = false;
|
||||
while (conn->write_more(&more_data)) {
|
||||
DBG_EP(fprintf(stderr, "OUT client write_more\n"));
|
||||
conn->nb_last_io = now;
|
||||
if (!more_data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* CLOSE */
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
epoll_event& ev = events[i];
|
||||
hstcpsvr_conn *const conn = static_cast<hstcpsvr_conn *>(ev.data.ptr);
|
||||
if (conn != 0 && conn->ok_to_close()) {
|
||||
DBG_EP(fprintf(stderr, "CLOSE close\n"));
|
||||
conns.erase_ptr(conn->conns_iter);
|
||||
}
|
||||
}
|
||||
/* TIMEOUT & cleanup */
|
||||
if (last_check_time + 10 < now) {
|
||||
for (hstcpsvr_conns_type::iterator i = conns.begin();
|
||||
i != conns.end(); ) {
|
||||
hstcpsvr_conns_type::iterator icur = i;
|
||||
++i;
|
||||
if (cshared.sockargs.timeout != 0 &&
|
||||
(*icur)->nb_last_io + cshared.sockargs.timeout < now) {
|
||||
conns.erase_ptr((*icur)->conns_iter);
|
||||
}
|
||||
}
|
||||
last_check_time = now;
|
||||
DENA_VERBOSE(20, fprintf(stderr, "ep: %p nfds=%d cns=%zu\n", this, nfds,
|
||||
conns.size()));
|
||||
}
|
||||
DENA_VERBOSE(30, fprintf(stderr, "%p in=%zu out=%zu ac=%zu, cns=%zu\n",
|
||||
this, in_count, out_count, accept_count, conns.size()));
|
||||
if (conns.empty()) {
|
||||
dbctx->close_tables_if();
|
||||
}
|
||||
/* STATISTICS */
|
||||
const size_t num_conns = conns.size();
|
||||
dbctx->set_statistics(num_conns, 0);
|
||||
/* ENABLE/DISABLE ACCEPT */
|
||||
if (accept_balance != 0) {
|
||||
cshared.thread_num_conns[worker_id] = num_conns;
|
||||
size_t total_num_conns = 0;
|
||||
for (long i = 0; i < cshared.num_threads; ++i) {
|
||||
total_num_conns += cshared.thread_num_conns[i];
|
||||
}
|
||||
bool e_acc = false;
|
||||
if (num_conns < 10 ||
|
||||
total_num_conns * 2 > num_conns * cshared.num_threads) {
|
||||
e_acc = true;
|
||||
}
|
||||
epoll_event ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.ptr = 0;
|
||||
if (e_acc == accept_enabled) {
|
||||
} else if (e_acc) {
|
||||
if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, cshared.listen_fd.get(), &ev)
|
||||
!= 0) {
|
||||
fatal_abort("epoll_ctl EPOLL_CTL_ADD");
|
||||
}
|
||||
} else {
|
||||
if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_DEL, cshared.listen_fd.get(), &ev)
|
||||
!= 0) {
|
||||
fatal_abort("epoll_ctl EPOLL_CTL_ADD");
|
||||
}
|
||||
}
|
||||
accept_enabled = e_acc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
hstcpsvr_worker::execute_lines(hstcpsvr_conn& conn)
|
||||
{
|
||||
dbconnstate& cstate = conn.cstate;
|
||||
char *buf_end = cstate.readbuf.end();
|
||||
char *line_begin = cstate.readbuf.begin();
|
||||
while (true) {
|
||||
char *const nl = memchr_char(line_begin, '\n', buf_end - line_begin);
|
||||
if (nl == 0) {
|
||||
break;
|
||||
}
|
||||
char *const lf = (line_begin != nl && nl[-1] == '\r') ? nl - 1 : nl;
|
||||
execute_line(line_begin, lf, conn);
|
||||
line_begin = nl + 1;
|
||||
}
|
||||
cstate.readbuf.erase_front(line_begin - cstate.readbuf.begin());
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_worker::execute_line(char *start, char *finish, hstcpsvr_conn& conn)
|
||||
{
|
||||
/* safe to modify, safe to dereference 'finish' */
|
||||
char *const cmd_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const cmd_end = start;
|
||||
skip_one(start, finish);
|
||||
if (cmd_begin == cmd_end) {
|
||||
return conn.dbcb_resp_short(2, "cmd");
|
||||
}
|
||||
if (cmd_begin + 1 == cmd_end) {
|
||||
if (cmd_begin[0] == 'P') {
|
||||
if (cshared.require_auth && !conn.authorized) {
|
||||
return conn.dbcb_resp_short(3, "unauth");
|
||||
}
|
||||
return do_open_index(start, finish, conn);
|
||||
}
|
||||
if (cmd_begin[0] == 'A') {
|
||||
return do_authorization(start, finish, conn);
|
||||
}
|
||||
}
|
||||
if (cmd_begin[0] >= '0' && cmd_begin[0] <= '9') {
|
||||
if (cshared.require_auth && !conn.authorized) {
|
||||
return conn.dbcb_resp_short(3, "unauth");
|
||||
}
|
||||
return do_exec_on_index(cmd_begin, cmd_end, start, finish, conn);
|
||||
}
|
||||
return conn.dbcb_resp_short(2, "cmd");
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_worker::do_open_index(char *start, char *finish, hstcpsvr_conn& conn)
|
||||
{
|
||||
const size_t pst_id = read_ui32(start, finish);
|
||||
skip_one(start, finish);
|
||||
/* dbname */
|
||||
char *const dbname_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const dbname_end = start;
|
||||
skip_one(start, finish);
|
||||
/* tblname */
|
||||
char *const tblname_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const tblname_end = start;
|
||||
skip_one(start, finish);
|
||||
/* idxname */
|
||||
char *const idxname_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const idxname_end = start;
|
||||
skip_one(start, finish);
|
||||
/* retfields */
|
||||
char *const retflds_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const retflds_end = start;
|
||||
skip_one(start, finish);
|
||||
/* filfields */
|
||||
char *const filflds_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const filflds_end = start;
|
||||
dbname_end[0] = 0;
|
||||
tblname_end[0] = 0;
|
||||
idxname_end[0] = 0;
|
||||
retflds_end[0] = 0;
|
||||
filflds_end[0] = 0;
|
||||
return dbctx->cmd_open_index(conn, pst_id, dbname_begin, tblname_begin,
|
||||
idxname_begin, retflds_begin, filflds_begin);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
|
||||
char *finish, hstcpsvr_conn& conn)
|
||||
{
|
||||
cmd_exec_args args;
|
||||
const size_t pst_id = read_ui32(cmd_begin, cmd_end);
|
||||
if (pst_id >= conn.cstate.prep_stmts.size()) {
|
||||
return conn.dbcb_resp_short(2, "stmtnum");
|
||||
}
|
||||
args.pst = &conn.cstate.prep_stmts[pst_id];
|
||||
char *const op_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const op_end = start;
|
||||
args.op = string_ref(op_begin, op_end);
|
||||
skip_one(start, finish);
|
||||
const uint32_t fldnum = read_ui32(start, finish);
|
||||
string_ref flds[fldnum]; /* GNU */
|
||||
args.kvals = flds;
|
||||
args.kvalslen = fldnum;
|
||||
for (size_t i = 0; i < fldnum; ++i) {
|
||||
skip_one(start, finish);
|
||||
char *const f_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const f_end = start;
|
||||
if (is_null_expression(f_begin, f_end)) {
|
||||
/* null */
|
||||
flds[i] = string_ref();
|
||||
} else {
|
||||
/* non-null */
|
||||
char *wp = f_begin;
|
||||
unescape_string(wp, f_begin, f_end);
|
||||
flds[i] = string_ref(f_begin, wp - f_begin);
|
||||
}
|
||||
}
|
||||
skip_one(start, finish);
|
||||
args.limit = read_ui32(start, finish);
|
||||
skip_one(start, finish);
|
||||
args.skip = read_ui32(start, finish);
|
||||
if (start == finish) {
|
||||
/* simple query */
|
||||
return dbctx->cmd_exec_on_index(conn, args);
|
||||
}
|
||||
/* has filters or modops */
|
||||
skip_one(start, finish);
|
||||
/* filters */
|
||||
size_t filters_count = 0;
|
||||
while (start != finish && (start[0] == 'W' || start[0] == 'F')) {
|
||||
char *const filter_type_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const filter_type_end = start;
|
||||
skip_one(start, finish);
|
||||
char *const filter_op_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const filter_op_end = start;
|
||||
skip_one(start, finish);
|
||||
const uint32_t ff_offset = read_ui32(start, finish);
|
||||
skip_one(start, finish);
|
||||
char *const filter_val_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const filter_val_end = start;
|
||||
skip_one(start, finish);
|
||||
if (filters_work.size() <= filters_count) {
|
||||
filters_work.resize(filters_count + 1);
|
||||
}
|
||||
record_filter& fi = filters_work[filters_count];
|
||||
if (filter_type_end != filter_type_begin + 1) {
|
||||
return conn.dbcb_resp_short(2, "filtertype");
|
||||
}
|
||||
fi.filter_type = (filter_type_begin[0] == 'W')
|
||||
? record_filter_type_break : record_filter_type_skip;
|
||||
const uint32_t num_filflds = args.pst->get_filter_fields().size();
|
||||
if (ff_offset >= num_filflds) {
|
||||
return conn.dbcb_resp_short(2, "filterfld");
|
||||
}
|
||||
fi.op = string_ref(filter_op_begin, filter_op_end);
|
||||
fi.ff_offset = ff_offset;
|
||||
if (is_null_expression(filter_val_begin, filter_val_end)) {
|
||||
/* null */
|
||||
fi.val = string_ref();
|
||||
} else {
|
||||
/* non-null */
|
||||
char *wp = filter_val_begin;
|
||||
unescape_string(wp, filter_val_begin, filter_val_end);
|
||||
fi.val = string_ref(filter_val_begin, wp - filter_val_begin);
|
||||
}
|
||||
++filters_count;
|
||||
}
|
||||
if (filters_count > 0) {
|
||||
if (filters_work.size() <= filters_count) {
|
||||
filters_work.resize(filters_count + 1);
|
||||
}
|
||||
filters_work[filters_count].op = string_ref(); /* sentinel */
|
||||
args.filters = &filters_work[0];
|
||||
} else {
|
||||
args.filters = 0;
|
||||
}
|
||||
if (start == finish) {
|
||||
/* no modops */
|
||||
return dbctx->cmd_exec_on_index(conn, args);
|
||||
}
|
||||
/* has modops */
|
||||
char *const mod_op_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const mod_op_end = start;
|
||||
args.mod_op = string_ref(mod_op_begin, mod_op_end);
|
||||
const size_t num_uvals = args.pst->get_ret_fields().size();
|
||||
string_ref uflds[num_uvals]; /* GNU */
|
||||
for (size_t i = 0; i < num_uvals; ++i) {
|
||||
skip_one(start, finish);
|
||||
char *const f_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const f_end = start;
|
||||
if (is_null_expression(f_begin, f_end)) {
|
||||
/* null */
|
||||
uflds[i] = string_ref();
|
||||
} else {
|
||||
/* non-null */
|
||||
char *wp = f_begin;
|
||||
unescape_string(wp, f_begin, f_end);
|
||||
uflds[i] = string_ref(f_begin, wp - f_begin);
|
||||
}
|
||||
}
|
||||
args.uvals = uflds;
|
||||
return dbctx->cmd_exec_on_index(conn, args);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpsvr_worker::do_authorization(char *start, char *finish,
|
||||
hstcpsvr_conn& conn)
|
||||
{
|
||||
/* auth type */
|
||||
char *const authtype_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const authtype_end = start;
|
||||
const size_t authtype_len = authtype_end - authtype_begin;
|
||||
skip_one(start, finish);
|
||||
/* key */
|
||||
char *const key_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const key_end = start;
|
||||
const size_t key_len = key_end - key_begin;
|
||||
authtype_end[0] = 0;
|
||||
key_end[0] = 0;
|
||||
char *wp = key_begin;
|
||||
unescape_string(wp, key_begin, key_end);
|
||||
if (authtype_len != 1 || authtype_begin[0] != '1') {
|
||||
return conn.dbcb_resp_short(2, "authtype");
|
||||
}
|
||||
if (cshared.plain_secret.size() == key_len &&
|
||||
memcmp(cshared.plain_secret.data(), key_begin, key_len) == 0) {
|
||||
conn.authorized = true;
|
||||
} else {
|
||||
conn.authorized = false;
|
||||
}
|
||||
if (!conn.authorized) {
|
||||
return conn.dbcb_resp_short(3, "unauth");
|
||||
} else {
|
||||
return conn.dbcb_resp_short(0, "");
|
||||
}
|
||||
}
|
||||
|
||||
hstcpsvr_worker_ptr
|
||||
hstcpsvr_worker_i::create(const hstcpsvr_worker_arg& arg)
|
||||
{
|
||||
return hstcpsvr_worker_ptr(new hstcpsvr_worker(arg));
|
||||
}
|
||||
|
||||
};
|
||||
|
35
plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp
Normal file
35
plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_HSTCPSVR_WORKER_HPP
|
||||
#define DENA_HSTCPSVR_WORKER_HPP
|
||||
|
||||
#include "hstcpsvr.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct hstcpsvr_worker_i;
|
||||
typedef std::auto_ptr<hstcpsvr_worker_i> hstcpsvr_worker_ptr;
|
||||
|
||||
struct hstcpsvr_worker_arg {
|
||||
const hstcpsvr_shared_c *cshared;
|
||||
volatile hstcpsvr_shared_v *vshared;
|
||||
long worker_id;
|
||||
hstcpsvr_worker_arg() : cshared(0), vshared(0), worker_id(0) { }
|
||||
};
|
||||
|
||||
struct hstcpsvr_worker_i {
|
||||
virtual ~hstcpsvr_worker_i() { }
|
||||
virtual void run() = 0;
|
||||
static hstcpsvr_worker_ptr create(const hstcpsvr_worker_arg& arg);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
49
plugin/handler_socket/handlersocket/mysql_incl.hpp
Normal file
49
plugin/handler_socket/handlersocket/mysql_incl.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_MYSQL_INCL_HPP
|
||||
#define DENA_MYSQL_INCL_HPP
|
||||
|
||||
#ifndef HAVE_CONFIG_H
|
||||
#define HAVE_CONFIG_H
|
||||
#endif
|
||||
|
||||
#define MYSQL_DYNAMIC_PLUGIN
|
||||
#define MYSQL_SERVER 1
|
||||
|
||||
#include <my_config.h>
|
||||
#include <mysql_version.h>
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50505
|
||||
#include <my_pthread.h>
|
||||
#include <sql_priv.h>
|
||||
#include "sql_class.h"
|
||||
#include "unireg.h"
|
||||
#include "lock.h"
|
||||
#include "key.h" // key_copy()
|
||||
#include <my_global.h>
|
||||
#include <mysql/plugin.h>
|
||||
#include <transaction.h>
|
||||
#include <sql_base.h>
|
||||
// FIXME FIXME FIXME
|
||||
#define safeFree(X) my_free(X)
|
||||
#define pthread_cond_timedwait mysql_cond_timedwait
|
||||
#define pthread_mutex_lock mysql_mutex_lock
|
||||
#define pthread_mutex_unlock mysql_mutex_unlock
|
||||
#define current_stmt_binlog_row_based is_current_stmt_binlog_format_row
|
||||
#define clear_current_stmt_binlog_row_based clear_current_stmt_binlog_format_row
|
||||
|
||||
#else
|
||||
#include "mysql_priv.h"
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#endif
|
||||
|
27
plugin/handler_socket/libhsclient/COPYRIGHT.txt
Normal file
27
plugin/handler_socket/libhsclient/COPYRIGHT.txt
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
Copyright (c) 2010 DeNA Co.,Ltd.
|
||||
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 DeNA Co.,Ltd. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DeNA Co.,Ltd. "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 DeNA Co.,Ltd. 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.
|
||||
|
13
plugin/handler_socket/libhsclient/Makefile.am
Normal file
13
plugin/handler_socket/libhsclient/Makefile.am
Normal file
@ -0,0 +1,13 @@
|
||||
CXXFLAGS += -fimplicit-templates
|
||||
instdir = $(includedir)/handlersocket
|
||||
# TODO: these headers should be in dena/
|
||||
inst_HEADERS = allocator.hpp config.hpp mutex.hpp string_util.hpp \
|
||||
auto_addrinfo.hpp escape.hpp socket.hpp thread.hpp auto_file.hpp \
|
||||
fatal.hpp string_buffer.hpp util.hpp auto_ptrcontainer.hpp \
|
||||
hstcpcli.hpp string_ref.hpp
|
||||
lib_LTLIBRARIES = libhsclient.la
|
||||
libhsclient_la_SOURCES = config.cpp escape.cpp fatal.cpp hstcpcli.cpp \
|
||||
socket.cpp string_util.cpp
|
||||
#libhsclient_la_LDFLAGS = -static
|
||||
libhsclient_la_CFLAGS = $(AM_CFLAGS)
|
||||
libhsclient_la_CXXFLAGS = $(AM_CFLAGS)
|
27
plugin/handler_socket/libhsclient/Makefile.plain
Normal file
27
plugin/handler_socket/libhsclient/Makefile.plain
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
CXX = g++ -Wall -g -fno-rtti -fno-exceptions -fPIC -DPIC
|
||||
LDFLAGS =
|
||||
|
||||
CXXFLAGS += -O3 -DNDEBUG
|
||||
|
||||
COMMON_OBJS = config.o fatal.o socket.o string_util.o escape.o
|
||||
HSCLIENT_OBJS = $(COMMON_OBJS) hstcpcli.o
|
||||
|
||||
all: libhsclient.a
|
||||
|
||||
libhsclient.a: $(HSCLIENT_OBJS)
|
||||
$(AR) rc $@ $^
|
||||
$(AR) s $@
|
||||
|
||||
clean:
|
||||
rm -f *.a *.so *.o
|
||||
|
||||
LIBDIR = $(shell \
|
||||
if [ -e /usr/lib64/mysql ]; then echo /usr/lib64; else echo /usr/lib; fi)
|
||||
|
||||
install: libhsclient.a
|
||||
sudo sh -c 'cp libhsclient.a libhsclient.a.cpy && \
|
||||
mv libhsclient.a.cpy $(LIBDIR)/libhsclient.a && \
|
||||
mkdir -p /usr/include/handlersocket && \
|
||||
cp -a *.hpp /usr/include/handlersocket/'
|
||||
|
37
plugin/handler_socket/libhsclient/allocator.hpp
Normal file
37
plugin/handler_socket/libhsclient/allocator.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_ALLOCATOR_HPP
|
||||
#define DENA_ALLOCATOR_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
extern "C" {
|
||||
#include <tlsf.h>
|
||||
};
|
||||
#define DENA_MALLOC(x) tlsf_malloc(x)
|
||||
#define DENA_REALLOC(x, y) tlsf_realloc(x, y)
|
||||
#define DENA_FREE(x) tlsf_free(x)
|
||||
#define DENA_NEWCHAR(x) static_cast<char *>(tlsf_malloc(x))
|
||||
#define DENA_DELETE(x) tlsf_free(x)
|
||||
typedef std::allocator<int> allocator_type;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define DENA_MALLOC(x) malloc(x)
|
||||
#define DENA_REALLOC(x, y) realloc(x, y)
|
||||
#define DENA_FREE(x) free(x)
|
||||
#define DENA_NEWCHAR(x) (new char[x])
|
||||
#define DENA_DELETE(x) (delete [] x)
|
||||
typedef std::allocator<int> allocator_type;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
50
plugin/handler_socket/libhsclient/auto_addrinfo.hpp
Normal file
50
plugin/handler_socket/libhsclient/auto_addrinfo.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_AUTO_ADDRINFO_HPP
|
||||
#define DENA_AUTO_ADDRINFO_HPP
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include "util.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct auto_addrinfo : private noncopyable {
|
||||
auto_addrinfo() : addr(0) { }
|
||||
~auto_addrinfo() {
|
||||
reset();
|
||||
}
|
||||
void reset(addrinfo *a = 0) {
|
||||
if (addr != 0) {
|
||||
freeaddrinfo(addr);
|
||||
}
|
||||
addr = a;
|
||||
}
|
||||
const addrinfo *get() const { return addr; }
|
||||
int resolve(const char *node, const char *service, int flags = 0,
|
||||
int family = AF_UNSPEC, int socktype = SOCK_STREAM, int protocol = 0) {
|
||||
reset();
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = flags;
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = socktype;
|
||||
hints.ai_protocol = protocol;
|
||||
return getaddrinfo(node, service, &hints, &addr);
|
||||
}
|
||||
private:
|
||||
addrinfo *addr;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
64
plugin/handler_socket/libhsclient/auto_file.hpp
Normal file
64
plugin/handler_socket/libhsclient/auto_file.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_AUTO_FILE_HPP
|
||||
#define DENA_AUTO_FILE_HPP
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct auto_file : private noncopyable {
|
||||
auto_file() : fd(-1) { }
|
||||
~auto_file() {
|
||||
reset();
|
||||
}
|
||||
int get() const { return fd; }
|
||||
int close() {
|
||||
if (fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
const int r = ::close(fd);
|
||||
fd = -1;
|
||||
return r;
|
||||
}
|
||||
void reset(int x = -1) {
|
||||
if (fd >= 0) {
|
||||
this->close();
|
||||
}
|
||||
fd = x;
|
||||
}
|
||||
private:
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct auto_dir : private noncopyable {
|
||||
auto_dir() : dp(0) { }
|
||||
~auto_dir() {
|
||||
reset();
|
||||
}
|
||||
DIR *get() const { return dp; }
|
||||
void reset(DIR *d = 0) {
|
||||
if (dp != 0) {
|
||||
closedir(dp);
|
||||
}
|
||||
dp = d;
|
||||
}
|
||||
private:
|
||||
DIR *dp;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
67
plugin/handler_socket/libhsclient/auto_ptrcontainer.hpp
Normal file
67
plugin/handler_socket/libhsclient/auto_ptrcontainer.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_AUTO_PTRCONTAINER_HPP
|
||||
#define DENA_AUTO_PTRCONTAINER_HPP
|
||||
|
||||
namespace dena {
|
||||
|
||||
template <typename Tcnt>
|
||||
struct auto_ptrcontainer {
|
||||
typedef Tcnt container_type;
|
||||
typedef typename container_type::value_type value_type;
|
||||
typedef typename container_type::pointer pointer;
|
||||
typedef typename container_type::reference reference;
|
||||
typedef typename container_type::const_reference const_reference;
|
||||
typedef typename container_type::size_type size_type;
|
||||
typedef typename container_type::difference_type difference_type;
|
||||
typedef typename container_type::iterator iterator;
|
||||
typedef typename container_type::const_iterator const_iterator;
|
||||
typedef typename container_type::reverse_iterator reverse_iterator;
|
||||
typedef typename container_type::const_reverse_iterator
|
||||
const_reverse_iterator;
|
||||
iterator begin() { return cnt.begin(); }
|
||||
const_iterator begin() const { return cnt.begin(); }
|
||||
iterator end() { return cnt.end(); }
|
||||
const_iterator end() const { return cnt.end(); }
|
||||
reverse_iterator rbegin() { return cnt.rbegin(); }
|
||||
reverse_iterator rend() { return cnt.rend(); }
|
||||
const_reverse_iterator rbegin() const { return cnt.rbegin(); }
|
||||
const_reverse_iterator rend() const { return cnt.rend(); }
|
||||
size_type size() const { return cnt.size(); }
|
||||
size_type max_size() const { return cnt.max_size(); }
|
||||
bool empty() const { return cnt.empty(); }
|
||||
reference front() { return cnt.front(); }
|
||||
const_reference front() const { cnt.front(); }
|
||||
reference back() { return cnt.back(); }
|
||||
const_reference back() const { cnt.back(); }
|
||||
void swap(auto_ptrcontainer& x) { cnt.swap(x.cnt); }
|
||||
~auto_ptrcontainer() {
|
||||
for (iterator i = begin(); i != end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
template <typename Tap> void push_back_ptr(Tap& ap) {
|
||||
cnt.push_back(ap.get());
|
||||
ap.release();
|
||||
}
|
||||
void erase_ptr(iterator i) {
|
||||
delete *i;
|
||||
cnt.erase(i);
|
||||
}
|
||||
reference operator [](size_type n) { return cnt[n]; }
|
||||
const_reference operator [](size_type n) const { return cnt[n]; }
|
||||
void clear() { cnt.clear(); }
|
||||
private:
|
||||
Tcnt cnt;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
67
plugin/handler_socket/libhsclient/config.cpp
Normal file
67
plugin/handler_socket/libhsclient/config.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
unsigned int verbose_level = 0;
|
||||
|
||||
std::string
|
||||
config::get_str(const std::string& key, const std::string& def) const
|
||||
{
|
||||
const_iterator iter = this->find(key);
|
||||
if (iter == this->end()) {
|
||||
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s(default)\n", key.c_str(),
|
||||
def.c_str()));
|
||||
return def;
|
||||
}
|
||||
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s\n", key.c_str(),
|
||||
iter->second.c_str()));
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
long long
|
||||
config::get_int(const std::string& key, long long def) const
|
||||
{
|
||||
const_iterator iter = this->find(key);
|
||||
if (iter == this->end()) {
|
||||
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld(default)\n", key.c_str(),
|
||||
def));
|
||||
return def;
|
||||
}
|
||||
const long long r = atoll(iter->second.c_str());
|
||||
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld\n", key.c_str(), r));
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
parse_args(int argc, char **argv, config& conf)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
const char *const arg = argv[i];
|
||||
const char *const eq = strchr(arg, '=');
|
||||
if (eq == 0) {
|
||||
continue;
|
||||
}
|
||||
const std::string key(arg, eq - arg);
|
||||
const std::string val(eq + 1);
|
||||
conf[key] = val;
|
||||
}
|
||||
config::const_iterator iter = conf.find("verbose");
|
||||
if (iter != conf.end()) {
|
||||
verbose_level = atoi(iter->second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
32
plugin/handler_socket/libhsclient/config.hpp
Normal file
32
plugin/handler_socket/libhsclient/config.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_CONFIG_HPP
|
||||
#define DENA_CONFIG_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#define DENA_VERBOSE(lv, x) if (dena::verbose_level >= (lv)) { (x); }
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct config : public std::map<std::string, std::string> {
|
||||
std::string get_str(const std::string& key, const std::string& def = "")
|
||||
const;
|
||||
long long get_int(const std::string& key, long long def = 0) const;
|
||||
};
|
||||
|
||||
void parse_args(int argc, char **argv, config& conf);
|
||||
|
||||
extern unsigned int verbose_level;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
117
plugin/handler_socket/libhsclient/escape.cpp
Normal file
117
plugin/handler_socket/libhsclient/escape.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "escape.hpp"
|
||||
#include "string_buffer.hpp"
|
||||
#include "fatal.hpp"
|
||||
#include "string_util.hpp"
|
||||
|
||||
#define DBG_OP(x)
|
||||
#define DBG_BUF(x)
|
||||
|
||||
namespace dena {
|
||||
|
||||
enum special_char_t {
|
||||
special_char_escape_prefix = 0x01, /* SOH */
|
||||
special_char_noescape_min = 0x10, /* DLE */
|
||||
special_char_escape_shift = 0x40, /* '@' */
|
||||
};
|
||||
|
||||
void
|
||||
escape_string(char *& wp, const char *start, const char *finish)
|
||||
{
|
||||
while (start != finish) {
|
||||
const unsigned char c = *start;
|
||||
if (c >= special_char_noescape_min) {
|
||||
wp[0] = c; /* no need to escape */
|
||||
} else {
|
||||
wp[0] = special_char_escape_prefix;
|
||||
++wp;
|
||||
wp[0] = c + special_char_escape_shift;
|
||||
}
|
||||
++start;
|
||||
++wp;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
escape_string(string_buffer& ar, const char *start, const char *finish)
|
||||
{
|
||||
const size_t buflen = (finish - start) * 2;
|
||||
char *const wp_begin = ar.make_space(buflen);
|
||||
char *wp = wp_begin;
|
||||
escape_string(wp, start, finish);
|
||||
ar.space_wrote(wp - wp_begin);
|
||||
}
|
||||
|
||||
bool
|
||||
unescape_string(char *& wp, const char *start, const char *finish)
|
||||
{
|
||||
/* works even if wp == start */
|
||||
while (start != finish) {
|
||||
const unsigned char c = *start;
|
||||
if (c != special_char_escape_prefix) {
|
||||
wp[0] = c;
|
||||
} else if (start + 1 != finish) {
|
||||
++start;
|
||||
const unsigned char cn = *start;
|
||||
if (cn < special_char_escape_shift) {
|
||||
return false;
|
||||
}
|
||||
wp[0] = cn - special_char_escape_shift;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
++start;
|
||||
++wp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
unescape_string(string_buffer& ar, const char *start, const char *finish)
|
||||
{
|
||||
const size_t buflen = finish - start;
|
||||
char *const wp_begin = ar.make_space(buflen);
|
||||
char *wp = wp_begin;
|
||||
const bool r = unescape_string(wp, start, finish);
|
||||
ar.space_wrote(wp - wp_begin);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
read_ui32(char *& start, char *finish)
|
||||
{
|
||||
char *const n_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const n_end = start;
|
||||
uint32_t v = 0;
|
||||
for (char *p = n_begin; p != n_end; ++p) {
|
||||
const char ch = p[0];
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
v *= 10;
|
||||
v += (ch - '0');
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
write_ui32(string_buffer& buf, uint32_t v)
|
||||
{
|
||||
char *wp = buf.make_space(32);
|
||||
int len = snprintf(wp, 32, "%u", v);
|
||||
if (len > 0) {
|
||||
buf.space_wrote(len);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
65
plugin/handler_socket/libhsclient/escape.hpp
Normal file
65
plugin/handler_socket/libhsclient/escape.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "string_buffer.hpp"
|
||||
#include "string_ref.hpp"
|
||||
#include "string_util.hpp"
|
||||
|
||||
#ifndef DENA_ESCAPE_HPP
|
||||
#define DENA_ESCAPE_HPP
|
||||
|
||||
namespace dena {
|
||||
|
||||
void escape_string(char *& wp, const char *start, const char *finish);
|
||||
void escape_string(string_buffer& ar, const char *start, const char *finish);
|
||||
bool unescape_string(char *& wp, const char *start, const char *finish);
|
||||
/* unescaped_string() works even if wp == start */
|
||||
bool unescape_string(string_buffer& ar, const char *start, const char *finish);
|
||||
|
||||
uint32_t read_ui32(char *& start, char *finish);
|
||||
void write_ui32(string_buffer& buf, uint32_t v);
|
||||
|
||||
inline bool
|
||||
is_null_expression(const char *start, const char *finish)
|
||||
{
|
||||
return (finish == start + 1 && start[0] == 0);
|
||||
}
|
||||
|
||||
inline void
|
||||
read_token(char *& start, char *finish)
|
||||
{
|
||||
char *const p = memchr_char(start, '\t', finish - start);
|
||||
if (p == 0) {
|
||||
start = finish;
|
||||
} else {
|
||||
start = p;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
skip_token_delim_fold(char *& start, char *finish)
|
||||
{
|
||||
while (start != finish && start[0] == '\t') {
|
||||
++start;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
skip_one(char *& start, char *finish)
|
||||
{
|
||||
if (start != finish) {
|
||||
++start;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
36
plugin/handler_socket/libhsclient/fatal.cpp
Normal file
36
plugin/handler_socket/libhsclient/fatal.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "fatal.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS;
|
||||
|
||||
void
|
||||
fatal_exit(const std::string& message)
|
||||
{
|
||||
fprintf(stderr, "FATAL_EXIT: %s\n", message.c_str());
|
||||
syslog(opt_syslog, "FATAL_EXIT: %s", message.c_str());
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
fatal_abort(const std::string& message)
|
||||
{
|
||||
fprintf(stderr, "FATAL_COREDUMP: %s\n", message.c_str());
|
||||
syslog(opt_syslog, "FATAL_COREDUMP: %s", message.c_str());
|
||||
abort();
|
||||
}
|
||||
|
||||
};
|
||||
|
22
plugin/handler_socket/libhsclient/fatal.hpp
Normal file
22
plugin/handler_socket/libhsclient/fatal.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_FATAL_HPP
|
||||
#define DENA_FATAL_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace dena {
|
||||
|
||||
void fatal_exit(const std::string& message);
|
||||
void fatal_abort(const std::string& message);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
453
plugin/handler_socket/libhsclient/hstcpcli.cpp
Normal file
453
plugin/handler_socket/libhsclient/hstcpcli.cpp
Normal file
@ -0,0 +1,453 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "hstcpcli.hpp"
|
||||
#include "auto_file.hpp"
|
||||
#include "string_util.hpp"
|
||||
#include "auto_addrinfo.hpp"
|
||||
#include "escape.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
/* TODO */
|
||||
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct hstcpcli : public hstcpcli_i, private noncopyable {
|
||||
hstcpcli(const socket_args& args);
|
||||
virtual void close();
|
||||
virtual int reconnect();
|
||||
virtual bool stable_point();
|
||||
virtual void request_buf_open_index(size_t pst_id, const char *dbn,
|
||||
const char *tbl, const char *idx, const char *retflds, const char *filflds);
|
||||
#if 0
|
||||
virtual void request_buf_find(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip);
|
||||
virtual void request_buf_insert(size_t pst_id, const string_ref *fvs,
|
||||
size_t fvslen);
|
||||
virtual void request_buf_update(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
|
||||
const string_ref *mvs, size_t mvslen);
|
||||
virtual void request_buf_delete(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip);
|
||||
#endif
|
||||
virtual void request_buf_exec_generic(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
|
||||
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
|
||||
const hstcpcli_filter *fils, size_t filslen);
|
||||
virtual int request_send();
|
||||
virtual int response_recv(size_t& num_flds_r);
|
||||
virtual const string_ref *get_next_row();
|
||||
virtual void response_buf_remove();
|
||||
virtual int get_error_code();
|
||||
virtual std::string get_error();
|
||||
private:
|
||||
int read_more();
|
||||
void clear_error();
|
||||
int set_error(int code, const std::string& str);
|
||||
private:
|
||||
auto_file fd;
|
||||
socket_args sargs;
|
||||
string_buffer readbuf;
|
||||
string_buffer writebuf;
|
||||
size_t response_end_offset; /* incl newline */
|
||||
size_t cur_row_offset;
|
||||
size_t num_flds;
|
||||
size_t num_req_bufd; /* buffered but not yet sent */
|
||||
size_t num_req_sent; /* sent but not yet received */
|
||||
size_t num_req_rcvd; /* received but not yet removed */
|
||||
int error_code;
|
||||
std::string error_str;
|
||||
std::vector<string_ref> flds;
|
||||
};
|
||||
|
||||
hstcpcli::hstcpcli(const socket_args& args)
|
||||
: sargs(args), response_end_offset(0), cur_row_offset(0), num_flds(0),
|
||||
num_req_bufd(0), num_req_sent(0), num_req_rcvd(0), error_code(0)
|
||||
{
|
||||
std::string err;
|
||||
if (socket_connect(fd, sargs, err) != 0) {
|
||||
set_error(-1, err);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::close()
|
||||
{
|
||||
fd.close();
|
||||
readbuf.clear();
|
||||
writebuf.clear();
|
||||
flds.clear();
|
||||
response_end_offset = 0;
|
||||
cur_row_offset = 0;
|
||||
num_flds = 0;
|
||||
num_req_bufd = 0;
|
||||
num_req_sent = 0;
|
||||
num_req_rcvd = 0;
|
||||
}
|
||||
|
||||
int
|
||||
hstcpcli::reconnect()
|
||||
{
|
||||
clear_error();
|
||||
close();
|
||||
std::string err;
|
||||
if (socket_connect(fd, sargs, err) != 0) {
|
||||
set_error(-1, err);
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
bool
|
||||
hstcpcli::stable_point()
|
||||
{
|
||||
/* returns true if cli can send a new request */
|
||||
return fd.get() >= 0 && num_req_bufd == 0 && num_req_sent == 0 &&
|
||||
num_req_rcvd == 0 && response_end_offset == 0;
|
||||
}
|
||||
|
||||
int
|
||||
hstcpcli::get_error_code()
|
||||
{
|
||||
return error_code;
|
||||
}
|
||||
|
||||
std::string
|
||||
hstcpcli::get_error()
|
||||
{
|
||||
return error_str;
|
||||
}
|
||||
|
||||
int
|
||||
hstcpcli::read_more()
|
||||
{
|
||||
const size_t block_size = 4096; // FIXME
|
||||
char *const wp = readbuf.make_space(block_size);
|
||||
const ssize_t rlen = read(fd.get(), wp, block_size);
|
||||
if (rlen <= 0) {
|
||||
if (rlen < 0) {
|
||||
error_str = "read: failed";
|
||||
} else {
|
||||
error_str = "read: eof";
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
readbuf.space_wrote(rlen);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::clear_error()
|
||||
{
|
||||
DBG(fprintf(stderr, "CLEAR_ERROR: %d\n", error_code));
|
||||
error_code = 0;
|
||||
error_str.clear();
|
||||
}
|
||||
|
||||
int
|
||||
hstcpcli::set_error(int code, const std::string& str)
|
||||
{
|
||||
DBG(fprintf(stderr, "SET_ERROR: %d\n", code));
|
||||
error_code = code;
|
||||
error_str = str;
|
||||
return error_code;
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::request_buf_open_index(size_t pst_id, const char *dbn,
|
||||
const char *tbl, const char *idx, const char *retflds, const char *filflds)
|
||||
{
|
||||
if (num_req_sent > 0 || num_req_rcvd > 0) {
|
||||
close();
|
||||
set_error(-1, "request_buf_open_index: protocol out of sync");
|
||||
return;
|
||||
}
|
||||
const string_ref dbn_ref(dbn, strlen(dbn));
|
||||
const string_ref tbl_ref(tbl, strlen(tbl));
|
||||
const string_ref idx_ref(idx, strlen(idx));
|
||||
const string_ref rfs_ref(retflds, strlen(retflds));
|
||||
writebuf.append_literal("P\t");
|
||||
append_uint32(writebuf, pst_id); // FIXME size_t ?
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(dbn_ref.begin(), dbn_ref.end());
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(tbl_ref.begin(), tbl_ref.end());
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(idx_ref.begin(), idx_ref.end());
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(rfs_ref.begin(), rfs_ref.end());
|
||||
if (filflds != 0) {
|
||||
const string_ref fls_ref(filflds, strlen(filflds));
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(fls_ref.begin(), fls_ref.end());
|
||||
}
|
||||
writebuf.append_literal("\n");
|
||||
++num_req_bufd;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
append_delim_value(string_buffer& buf, const char *start, const char *finish)
|
||||
{
|
||||
if (start == 0) {
|
||||
/* null */
|
||||
const char t[] = "\t\0";
|
||||
buf.append(t, t + 2);
|
||||
} else {
|
||||
/* non-null */
|
||||
buf.append_literal("\t");
|
||||
escape_string(buf, start, finish);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void
|
||||
hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
|
||||
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
|
||||
const hstcpcli_filter *fils, size_t filslen)
|
||||
{
|
||||
if (num_req_sent > 0 || num_req_rcvd > 0) {
|
||||
close();
|
||||
set_error(-1, "request_buf_exec_generic: protocol out of sync");
|
||||
return;
|
||||
}
|
||||
append_uint32(writebuf, pst_id); // FIXME size_t ?
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(op.begin(), op.end());
|
||||
writebuf.append_literal("\t");
|
||||
append_uint32(writebuf, kvslen); // FIXME size_t ?
|
||||
for (size_t i = 0; i < kvslen; ++i) {
|
||||
const string_ref& kv = kvs[i];
|
||||
append_delim_value(writebuf, kv.begin(), kv.end());
|
||||
}
|
||||
if (limit != 0 || skip != 0 || mod_op.size() != 0 || filslen != 0) {
|
||||
writebuf.append_literal("\t");
|
||||
append_uint32(writebuf, limit); // FIXME size_t ?
|
||||
if (skip != 0 || mod_op.size() != 0 || filslen != 0) {
|
||||
writebuf.append_literal("\t");
|
||||
append_uint32(writebuf, skip); // FIXME size_t ?
|
||||
}
|
||||
for (size_t i = 0; i < filslen; ++i) {
|
||||
const hstcpcli_filter& f = fils[i];
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(f.filter_type.begin(), f.filter_type.end());
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(f.op.begin(), f.op.end());
|
||||
writebuf.append_literal("\t");
|
||||
append_uint32(writebuf, f.ff_offset);
|
||||
append_delim_value(writebuf, f.val.begin(), f.val.end());
|
||||
}
|
||||
if (mod_op.size() != 0) {
|
||||
writebuf.append_literal("\t");
|
||||
writebuf.append(mod_op.begin(), mod_op.end());
|
||||
for (size_t i = 0; i < mvslen; ++i) {
|
||||
const string_ref& mv = mvs[i];
|
||||
append_delim_value(writebuf, mv.begin(), mv.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
writebuf.append_literal("\n");
|
||||
++num_req_bufd;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
hstcpcli::request_buf_find(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip)
|
||||
{
|
||||
return request_buf_exec_generic(pst_id, op, kvs, kvslen, limit, skip,
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::request_buf_insert(size_t pst_id, const string_ref *fvs,
|
||||
size_t fvslen)
|
||||
{
|
||||
const string_ref insert_op("+", 1);
|
||||
return request_buf_exec_generic(pst_id, insert_op, fvs, fvslen,
|
||||
0, 0, string_ref(), 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::request_buf_update(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
|
||||
const string_ref *mvs, size_t mvslen)
|
||||
{
|
||||
const string_ref modop_update("U", 1);
|
||||
return request_buf_exec_generic(pst_id, op, kvs, kvslen, limit, skip,
|
||||
modop_update, mvs, mvslen);
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::request_buf_delete(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip)
|
||||
{
|
||||
const string_ref modop_delete("D", 1);
|
||||
return request_buf_exec_generic(pst_id, op, kvs, kvslen, limit, skip,
|
||||
modop_delete, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
hstcpcli::request_send()
|
||||
{
|
||||
if (error_code < 0) {
|
||||
return error_code;
|
||||
}
|
||||
clear_error();
|
||||
if (fd.get() < 0) {
|
||||
close();
|
||||
return set_error(-1, "write: closed");
|
||||
}
|
||||
if (num_req_bufd == 0 || num_req_sent > 0 || num_req_rcvd > 0) {
|
||||
close();
|
||||
return set_error(-1, "request_send: protocol out of sync");
|
||||
}
|
||||
const size_t wrlen = writebuf.size();
|
||||
const ssize_t r = send(fd.get(), writebuf.begin(), wrlen, MSG_NOSIGNAL);
|
||||
if (r <= 0) {
|
||||
close();
|
||||
return set_error(-1, r < 0 ? "write: failed" : "write: eof");
|
||||
}
|
||||
writebuf.erase_front(r);
|
||||
if (static_cast<size_t>(r) != wrlen) {
|
||||
close();
|
||||
return set_error(-1, "write: incomplete");
|
||||
}
|
||||
num_req_sent = num_req_bufd;
|
||||
num_req_bufd = 0;
|
||||
DBG(fprintf(stderr, "REQSEND 0\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hstcpcli::response_recv(size_t& num_flds_r)
|
||||
{
|
||||
if (error_code < 0) {
|
||||
return error_code;
|
||||
}
|
||||
clear_error();
|
||||
if (num_req_bufd > 0 || num_req_sent == 0 || num_req_rcvd > 0 ||
|
||||
response_end_offset != 0) {
|
||||
close();
|
||||
return set_error(-1, "response_recv: protocol out of sync");
|
||||
}
|
||||
cur_row_offset = 0;
|
||||
num_flds_r = num_flds = 0;
|
||||
if (fd.get() < 0) {
|
||||
return set_error(-1, "read: closed");
|
||||
}
|
||||
size_t offset = 0;
|
||||
while (true) {
|
||||
const char *const lbegin = readbuf.begin() + offset;
|
||||
const char *const lend = readbuf.end();
|
||||
const char *const nl = memchr_char(lbegin, '\n', lend - lbegin);
|
||||
if (nl != 0) {
|
||||
offset = (nl + 1) - readbuf.begin();
|
||||
break;
|
||||
}
|
||||
if (read_more() <= 0) {
|
||||
close();
|
||||
return set_error(-1, "read: eof");
|
||||
}
|
||||
}
|
||||
response_end_offset = offset;
|
||||
--num_req_sent;
|
||||
++num_req_rcvd;
|
||||
char *start = readbuf.begin();
|
||||
char *const finish = start + response_end_offset - 1;
|
||||
const size_t resp_code = read_ui32(start, finish);
|
||||
skip_one(start, finish);
|
||||
num_flds_r = num_flds = read_ui32(start, finish);
|
||||
if (resp_code != 0) {
|
||||
skip_one(start, finish);
|
||||
char *const err_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const err_end = start;
|
||||
std::string e = std::string(err_begin, err_end - err_begin);
|
||||
if (e.empty()) {
|
||||
e = "unknown_error";
|
||||
}
|
||||
return set_error(resp_code, e);
|
||||
}
|
||||
cur_row_offset = start - readbuf.begin();
|
||||
DBG(fprintf(stderr, "[%s] ro=%zu eol=%zu\n",
|
||||
std::string(readbuf.begin(), readbuf.begin() + response_end_offset)
|
||||
.c_str(),
|
||||
cur_row_offset, response_end_offset));
|
||||
DBG(fprintf(stderr, "RES 0\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const string_ref *
|
||||
hstcpcli::get_next_row()
|
||||
{
|
||||
if (num_flds == 0) {
|
||||
DBG(fprintf(stderr, "GNR NF 0\n"));
|
||||
return 0;
|
||||
}
|
||||
if (flds.size() < num_flds) {
|
||||
flds.resize(num_flds);
|
||||
}
|
||||
char *start = readbuf.begin() + cur_row_offset;
|
||||
char *const finish = readbuf.begin() + response_end_offset - 1;
|
||||
if (start >= finish) { /* start[0] == nl */
|
||||
DBG(fprintf(stderr, "GNR FIN 0 %p %p\n", start, finish));
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < num_flds; ++i) {
|
||||
skip_one(start, finish);
|
||||
char *const fld_begin = start;
|
||||
read_token(start, finish);
|
||||
char *const fld_end = start;
|
||||
char *wp = fld_begin;
|
||||
if (is_null_expression(fld_begin, fld_end)) {
|
||||
/* null */
|
||||
flds[i] = string_ref();
|
||||
} else {
|
||||
unescape_string(wp, fld_begin, fld_end); /* in-place */
|
||||
flds[i] = string_ref(fld_begin, wp);
|
||||
}
|
||||
}
|
||||
cur_row_offset = start - readbuf.begin();
|
||||
return &flds[0];
|
||||
}
|
||||
|
||||
void
|
||||
hstcpcli::response_buf_remove()
|
||||
{
|
||||
if (response_end_offset == 0) {
|
||||
close();
|
||||
set_error(-1, "response_buf_remove: protocol out of sync");
|
||||
return;
|
||||
}
|
||||
readbuf.erase_front(response_end_offset);
|
||||
response_end_offset = 0;
|
||||
--num_req_rcvd;
|
||||
cur_row_offset = 0;
|
||||
num_flds = 0;
|
||||
flds.clear();
|
||||
}
|
||||
|
||||
hstcpcli_ptr
|
||||
hstcpcli_i::create(const socket_args& args)
|
||||
{
|
||||
return hstcpcli_ptr(new hstcpcli(args));
|
||||
}
|
||||
|
||||
};
|
||||
|
59
plugin/handler_socket/libhsclient/hstcpcli.hpp
Normal file
59
plugin/handler_socket/libhsclient/hstcpcli.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_HSTCPCLI_HPP
|
||||
#define DENA_HSTCPCLI_HPP
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "socket.hpp"
|
||||
#include "string_ref.hpp"
|
||||
#include "string_buffer.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct hstcpcli_filter {
|
||||
string_ref filter_type;
|
||||
string_ref op;
|
||||
size_t ff_offset;
|
||||
string_ref val;
|
||||
hstcpcli_filter() : ff_offset(0) { }
|
||||
};
|
||||
|
||||
struct hstcpcli_i;
|
||||
typedef std::auto_ptr<hstcpcli_i> hstcpcli_ptr;
|
||||
|
||||
struct hstcpcli_i {
|
||||
virtual ~hstcpcli_i() { }
|
||||
virtual void close() = 0;
|
||||
virtual int reconnect() = 0;
|
||||
virtual bool stable_point() = 0;
|
||||
virtual void request_buf_open_index(size_t pst_id, const char *dbn,
|
||||
const char *tbl, const char *idx, const char *retflds,
|
||||
const char *filflds = 0) = 0;
|
||||
virtual void request_buf_exec_generic(size_t pst_id, const string_ref& op,
|
||||
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
|
||||
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
|
||||
const hstcpcli_filter *fils = 0, size_t filslen = 0) = 0;
|
||||
virtual int request_send() = 0;
|
||||
virtual int response_recv(size_t& num_flds_r) = 0;
|
||||
virtual const string_ref *get_next_row() = 0;
|
||||
virtual void response_buf_remove() = 0;
|
||||
virtual int get_error_code() = 0;
|
||||
virtual std::string get_error() = 0;
|
||||
static hstcpcli_ptr create(const socket_args& args);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
39
plugin/handler_socket/libhsclient/libhsclient.spec.template
Normal file
39
plugin/handler_socket/libhsclient/libhsclient.spec.template
Normal file
@ -0,0 +1,39 @@
|
||||
Summary: handlersocket client library
|
||||
Name: libhsclient
|
||||
Version: HANDLERSOCKET_VERSION
|
||||
Release: 1%{?dist}
|
||||
Group: System Environment/Libraries
|
||||
License: BSD
|
||||
Source: libhsclient.tar.gz
|
||||
Packager: Akira Higuchi <higuchi dot akira at dena dot jp>
|
||||
BuildRoot: /var/tmp/%{name}-%{version}-root
|
||||
|
||||
%description
|
||||
|
||||
%prep
|
||||
%setup -n %{name}
|
||||
|
||||
%define _use_internal_dependency_generator 0
|
||||
|
||||
%build
|
||||
make -f Makefile.plain
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/include/handlersocket
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_bindir}
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_libdir}
|
||||
install -m 755 libhsclient.a $RPM_BUILD_ROOT/%{_libdir}
|
||||
install -m 644 *.hpp $RPM_BUILD_ROOT/usr/include/handlersocket/
|
||||
|
||||
%post
|
||||
/sbin/ldconfig
|
||||
|
||||
%postun
|
||||
/sbin/ldconfig
|
||||
|
||||
%files
|
||||
%defattr(-, root, root)
|
||||
/usr/include/*
|
||||
%{_libdir}/*.a
|
||||
|
51
plugin/handler_socket/libhsclient/mutex.hpp
Normal file
51
plugin/handler_socket/libhsclient/mutex.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_MUTEX_HPP
|
||||
#define DENA_MUTEX_HPP
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fatal.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct condition;
|
||||
|
||||
struct mutex : private noncopyable {
|
||||
friend struct condition;
|
||||
mutex() {
|
||||
if (pthread_mutex_init(&mtx, 0) != 0) {
|
||||
fatal_abort("pthread_mutex_init");
|
||||
}
|
||||
}
|
||||
~mutex() {
|
||||
if (pthread_mutex_destroy(&mtx) != 0) {
|
||||
fatal_abort("pthread_mutex_destroy");
|
||||
}
|
||||
}
|
||||
void lock() const {
|
||||
if (pthread_mutex_lock(&mtx) != 0) {
|
||||
fatal_abort("pthread_mutex_lock");
|
||||
}
|
||||
}
|
||||
void unlock() const {
|
||||
if (pthread_mutex_unlock(&mtx) != 0) {
|
||||
fatal_abort("pthread_mutex_unlock");
|
||||
}
|
||||
}
|
||||
private:
|
||||
mutable pthread_mutex_t mtx;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
186
plugin/handler_socket/libhsclient/socket.cpp
Normal file
186
plugin/handler_socket/libhsclient/socket.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "socket.hpp"
|
||||
#include "string_util.hpp"
|
||||
#include "fatal.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
void
|
||||
ignore_sigpipe()
|
||||
{
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
fatal_abort("SIGPIPE SIG_IGN");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
socket_args::set(const config& conf)
|
||||
{
|
||||
timeout = conf.get_int("timeout", 600);
|
||||
listen_backlog = conf.get_int("listen_backlog", 256);
|
||||
std::string node = conf.get_str("host", "");
|
||||
std::string port = conf.get_str("port", "");
|
||||
if (!node.empty() || !port.empty()) {
|
||||
if (family == AF_UNIX || node == "/") {
|
||||
set_unix_domain(port.c_str());
|
||||
} else {
|
||||
const char *nd = node.empty() ? 0 : node.c_str();
|
||||
if (resolve(nd, port.c_str()) != 0) {
|
||||
fatal_exit("getaddrinfo failed: " + node + ":" + port);
|
||||
}
|
||||
}
|
||||
}
|
||||
sndbuf = conf.get_int("sndbuf", 0);
|
||||
rcvbuf = conf.get_int("rcvbuf", 0);
|
||||
}
|
||||
|
||||
void
|
||||
socket_args::set_unix_domain(const char *path)
|
||||
{
|
||||
family = AF_UNIX;
|
||||
addr = sockaddr_storage();
|
||||
addrlen = sizeof(sockaddr_un);
|
||||
sockaddr_un *const ap = reinterpret_cast<sockaddr_un *>(&addr);
|
||||
ap->sun_family = AF_UNIX;
|
||||
strncpy(ap->sun_path, path, sizeof(ap->sun_path) - 1);
|
||||
}
|
||||
|
||||
int
|
||||
socket_args::resolve(const char *node, const char *service)
|
||||
{
|
||||
const int flags = (node == 0) ? AI_PASSIVE : 0;
|
||||
auto_addrinfo ai;
|
||||
addr = sockaddr_storage();
|
||||
addrlen = 0;
|
||||
const int r = ai.resolve(node, service, flags, family, socktype, protocol);
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
memcpy(&addr, ai.get()->ai_addr, ai.get()->ai_addrlen);
|
||||
addrlen = ai.get()->ai_addrlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
socket_set_options(auto_file& fd, const socket_args& args, std::string& err_r)
|
||||
{
|
||||
if (args.timeout != 0 && !args.nonblocking) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = args.timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (setsockopt(fd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
|
||||
return errno_string("setsockopt SO_RCVTIMEO", errno, err_r);
|
||||
}
|
||||
tv.tv_sec = args.timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (setsockopt(fd.get(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
|
||||
return errno_string("setsockopt SO_RCVTIMEO", errno, err_r);
|
||||
}
|
||||
}
|
||||
if (args.nonblocking && fcntl(fd.get(), F_SETFL, O_NONBLOCK) != 0) {
|
||||
return errno_string("fcntl O_NONBLOCK", errno, err_r);
|
||||
}
|
||||
if (args.sndbuf != 0) {
|
||||
const int v = args.sndbuf;
|
||||
if (setsockopt(fd.get(), SOL_SOCKET, SO_SNDBUF, &v, sizeof(v)) != 0) {
|
||||
return errno_string("setsockopt SO_SNDBUF", errno, err_r);
|
||||
}
|
||||
}
|
||||
if (args.rcvbuf != 0) {
|
||||
const int v = args.rcvbuf;
|
||||
if (setsockopt(fd.get(), SOL_SOCKET, SO_RCVBUF, &v, sizeof(v)) != 0) {
|
||||
return errno_string("setsockopt SO_RCVBUF", errno, err_r);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
socket_open(auto_file& fd, const socket_args& args, std::string& err_r)
|
||||
{
|
||||
fd.reset(socket(args.family, args.socktype, args.protocol));
|
||||
if (fd.get() < 0) {
|
||||
return errno_string("socket", errno, err_r);
|
||||
}
|
||||
return socket_set_options(fd, args, err_r);
|
||||
}
|
||||
|
||||
int
|
||||
socket_connect(auto_file& fd, const socket_args& args, std::string& err_r)
|
||||
{
|
||||
int r = 0;
|
||||
if ((r = socket_open(fd, args, err_r)) != 0) {
|
||||
return r;
|
||||
}
|
||||
if (connect(fd.get(), reinterpret_cast<const sockaddr *>(&args.addr),
|
||||
args.addrlen) != 0) {
|
||||
if (!args.nonblocking || errno != EINPROGRESS) {
|
||||
return errno_string("connect", errno, err_r);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
socket_bind(auto_file& fd, const socket_args& args, std::string& err_r)
|
||||
{
|
||||
fd.reset(socket(args.family, args.socktype, args.protocol));
|
||||
if (fd.get() < 0) {
|
||||
return errno_string("socket", errno, err_r);
|
||||
}
|
||||
if (args.reuseaddr) {
|
||||
if (args.family == AF_UNIX) {
|
||||
const sockaddr_un *const ap =
|
||||
reinterpret_cast<const sockaddr_un *>(&args.addr);
|
||||
if (unlink(ap->sun_path) != 0 && errno != ENOENT) {
|
||||
return errno_string("unlink uds", errno, err_r);
|
||||
}
|
||||
} else {
|
||||
int v = 1;
|
||||
if (setsockopt(fd.get(), SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) != 0) {
|
||||
return errno_string("setsockopt SO_REUSEADDR", errno, err_r);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bind(fd.get(), reinterpret_cast<const sockaddr *>(&args.addr),
|
||||
args.addrlen) != 0) {
|
||||
return errno_string("bind", errno, err_r);
|
||||
}
|
||||
if (listen(fd.get(), args.listen_backlog) != 0) {
|
||||
return errno_string("listen", errno, err_r);
|
||||
}
|
||||
if (args.nonblocking && fcntl(fd.get(), F_SETFL, O_NONBLOCK) != 0) {
|
||||
return errno_string("fcntl O_NONBLOCK", errno, err_r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
socket_accept(int listen_fd, auto_file& fd, const socket_args& args,
|
||||
sockaddr_storage& addr_r, socklen_t& addrlen_r, std::string& err_r)
|
||||
{
|
||||
fd.reset(accept(listen_fd, reinterpret_cast<sockaddr *>(&addr_r),
|
||||
&addrlen_r));
|
||||
if (fd.get() < 0) {
|
||||
return errno_string("accept", errno, err_r);
|
||||
}
|
||||
return socket_set_options(fd, args, err_r);
|
||||
}
|
||||
|
||||
};
|
||||
|
51
plugin/handler_socket/libhsclient/socket.hpp
Normal file
51
plugin/handler_socket/libhsclient/socket.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_SOCKET_HPP
|
||||
#define DENA_SOCKET_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "auto_addrinfo.hpp"
|
||||
#include "auto_file.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct socket_args {
|
||||
sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int family;
|
||||
int socktype;
|
||||
int protocol;
|
||||
int timeout;
|
||||
int listen_backlog;
|
||||
bool reuseaddr;
|
||||
bool nonblocking;
|
||||
bool use_epoll;
|
||||
int sndbuf;
|
||||
int rcvbuf;
|
||||
socket_args() : addr(), addrlen(0), family(AF_INET), socktype(SOCK_STREAM),
|
||||
protocol(0), timeout(600), listen_backlog(256),
|
||||
reuseaddr(true), nonblocking(false), use_epoll(false),
|
||||
sndbuf(0), rcvbuf(0) { }
|
||||
void set(const config& conf);
|
||||
void set_unix_domain(const char *path);
|
||||
int resolve(const char *node, const char *service);
|
||||
};
|
||||
|
||||
void ignore_sigpipe();
|
||||
int socket_bind(auto_file& fd, const socket_args& args, std::string& err_r);
|
||||
int socket_connect(auto_file& fd, const socket_args& args, std::string& err_r);
|
||||
int socket_accept(int listen_fd, auto_file& fd, const socket_args& args,
|
||||
sockaddr_storage& addr_r, socklen_t& addrlen_r, std::string& err_r);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
118
plugin/handler_socket/libhsclient/string_buffer.hpp
Normal file
118
plugin/handler_socket/libhsclient/string_buffer.hpp
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_STRING_BUFFER_HPP
|
||||
#define DENA_STRING_BUFFER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.hpp"
|
||||
#include "allocator.hpp"
|
||||
#include "fatal.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct string_buffer : private noncopyable {
|
||||
string_buffer() : buffer(0), begin_offset(0), end_offset(0), alloc_size(0) { }
|
||||
~string_buffer() {
|
||||
DENA_FREE(buffer);
|
||||
}
|
||||
const char *begin() const {
|
||||
return buffer + begin_offset;
|
||||
}
|
||||
const char *end() const {
|
||||
return buffer + end_offset;
|
||||
}
|
||||
char *begin() {
|
||||
return buffer + begin_offset;
|
||||
}
|
||||
char *end() {
|
||||
return buffer + end_offset;
|
||||
}
|
||||
size_t size() const {
|
||||
return end_offset - begin_offset;
|
||||
}
|
||||
void clear() {
|
||||
begin_offset = end_offset = 0;
|
||||
}
|
||||
void resize(size_t len) {
|
||||
if (size() < len) {
|
||||
reserve(len);
|
||||
memset(buffer + end_offset, 0, len - size());
|
||||
}
|
||||
end_offset = begin_offset + len;
|
||||
}
|
||||
void reserve(size_t len) {
|
||||
if (alloc_size >= begin_offset + len) {
|
||||
return;
|
||||
}
|
||||
size_t asz = alloc_size;
|
||||
while (asz < begin_offset + len) {
|
||||
if (asz == 0) {
|
||||
asz = 16;
|
||||
}
|
||||
const size_t asz_n = asz << 1;
|
||||
if (asz_n < asz) {
|
||||
fatal_abort("string_buffer::resize() overflow");
|
||||
}
|
||||
asz = asz_n;
|
||||
}
|
||||
void *const p = DENA_REALLOC(buffer, asz);
|
||||
if (p == 0) {
|
||||
fatal_abort("string_buffer::resize() realloc");
|
||||
}
|
||||
buffer = static_cast<char *>(p);
|
||||
alloc_size = asz;
|
||||
}
|
||||
void erase_front(size_t len) {
|
||||
if (len >= size()) {
|
||||
clear();
|
||||
} else {
|
||||
begin_offset += len;
|
||||
}
|
||||
}
|
||||
char *make_space(size_t len) {
|
||||
reserve(size() + len);
|
||||
return buffer + end_offset;
|
||||
}
|
||||
void space_wrote(size_t len) {
|
||||
len = std::min(len, alloc_size - end_offset);
|
||||
end_offset = std::min(end_offset + len, alloc_size);
|
||||
}
|
||||
template <size_t N>
|
||||
void append_literal(const char (& str)[N]) {
|
||||
append(str, str + N - 1);
|
||||
}
|
||||
void append(const char *start, const char *finish) {
|
||||
const size_t len = finish - start;
|
||||
reserve(size() + len);
|
||||
memcpy(buffer + end_offset, start, len);
|
||||
end_offset += len;
|
||||
}
|
||||
void append_2(const char *s1, const char *f1, const char *s2,
|
||||
const char *f2) {
|
||||
const size_t l1 = f1 - s1;
|
||||
const size_t l2 = f2 - s2;
|
||||
reserve(end_offset + l1 + l2);
|
||||
memcpy(buffer + end_offset, s1, l1);
|
||||
memcpy(buffer + end_offset + l1, s2, l2);
|
||||
end_offset += l1 + l2;
|
||||
}
|
||||
private:
|
||||
char *buffer;
|
||||
size_t begin_offset;
|
||||
size_t end_offset;
|
||||
size_t alloc_size;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
63
plugin/handler_socket/libhsclient/string_ref.hpp
Normal file
63
plugin/handler_socket/libhsclient/string_ref.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_STRING_REF_HPP
|
||||
#define DENA_STRING_REF_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
namespace dena {
|
||||
|
||||
struct string_wref {
|
||||
typedef char value_type;
|
||||
char *begin() const { return start; }
|
||||
char *end() const { return start + length; }
|
||||
size_t size() const { return length; }
|
||||
private:
|
||||
char *start;
|
||||
size_t length;
|
||||
public:
|
||||
string_wref(char *s = 0, size_t len = 0) : start(s), length(len) { }
|
||||
};
|
||||
|
||||
struct string_ref {
|
||||
typedef const char value_type;
|
||||
const char *begin() const { return start; }
|
||||
const char *end() const { return start + length; }
|
||||
size_t size() const { return length; }
|
||||
private:
|
||||
const char *start;
|
||||
size_t length;
|
||||
public:
|
||||
string_ref(const char *s = 0, size_t len = 0) : start(s), length(len) { }
|
||||
string_ref(const char *s, const char *f) : start(s), length(f - s) { }
|
||||
string_ref(const string_wref& w) : start(w.begin()), length(w.size()) { }
|
||||
};
|
||||
|
||||
template <size_t N> inline bool
|
||||
operator ==(const string_ref& x, const char (& y)[N]) {
|
||||
return (x.size() == N - 1) && (::memcmp(x.begin(), y, N - 1) == 0);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator ==(const string_ref& x, const string_ref& y) {
|
||||
return (x.size() == y.size()) &&
|
||||
(::memcmp(x.begin(), y.begin(), x.size()) == 0);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator !=(const string_ref& x, const string_ref& y) {
|
||||
return (x.size() != y.size()) ||
|
||||
(::memcmp(x.begin(), y.begin(), x.size()) != 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
182
plugin/handler_socket/libhsclient/string_util.cpp
Normal file
182
plugin/handler_socket/libhsclient/string_util.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "string_util.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
string_wref
|
||||
get_token(char *& wp, char *wp_end, char delim)
|
||||
{
|
||||
char *const wp_begin = wp;
|
||||
char *const p = memchr_char(wp_begin, delim, wp_end - wp_begin);
|
||||
if (p == 0) {
|
||||
wp = wp_end;
|
||||
return string_wref(wp_begin, wp_end - wp_begin);
|
||||
}
|
||||
wp = p + 1;
|
||||
return string_wref(wp_begin, p - wp_begin);
|
||||
}
|
||||
|
||||
template <typename T> T
|
||||
atoi_tmpl_nocheck(const char *start, const char *finish)
|
||||
{
|
||||
T v = 0;
|
||||
for (; start != finish; ++start) {
|
||||
const char c = *start;
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
v *= 10;
|
||||
v += static_cast<T>(c - '0');
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename T> T
|
||||
atoi_signed_tmpl_nocheck(const char *start, const char *finish)
|
||||
{
|
||||
T v = 0;
|
||||
bool negative = false;
|
||||
if (start != finish) {
|
||||
if (start[0] == '-') {
|
||||
++start;
|
||||
negative = true;
|
||||
} else if (start[0] == '+') {
|
||||
++start;
|
||||
}
|
||||
}
|
||||
for (; start != finish; ++start) {
|
||||
const char c = *start;
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
v *= 10;
|
||||
if (negative) {
|
||||
v -= static_cast<T>(c - '0');
|
||||
} else {
|
||||
v += static_cast<T>(c - '0');
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
atoi_uint32_nocheck(const char *start, const char *finish)
|
||||
{
|
||||
return atoi_tmpl_nocheck<uint32_t>(start, finish);
|
||||
}
|
||||
|
||||
long long
|
||||
atoll_nocheck(const char *start, const char *finish)
|
||||
{
|
||||
return atoi_signed_tmpl_nocheck<long long>(start, finish);
|
||||
}
|
||||
|
||||
void
|
||||
append_uint32(string_buffer& buf, uint32_t v)
|
||||
{
|
||||
char *const wp = buf.make_space(64);
|
||||
const int len = snprintf(wp, 64, "%lu", static_cast<unsigned long>(v));
|
||||
if (len > 0) {
|
||||
buf.space_wrote(len);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
to_stdstring(uint32_t v)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%lu", static_cast<unsigned long>(v));
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
int
|
||||
errno_string(const char *s, int en, std::string& err_r)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%s: %d", s, en);
|
||||
err_r = std::string(buf);
|
||||
return en;
|
||||
}
|
||||
|
||||
template <typename T> size_t
|
||||
split_tmpl_arr(char delim, const T& buf, T *parts, size_t parts_len)
|
||||
{
|
||||
typedef typename T::value_type value_type;
|
||||
size_t i = 0;
|
||||
value_type *start = buf.begin();
|
||||
value_type *const finish = buf.end();
|
||||
for (i = 0; i < parts_len; ++i) {
|
||||
value_type *const p = memchr_char(start, delim, finish - start);
|
||||
if (p == 0) {
|
||||
parts[i] = T(start, finish - start);
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
parts[i] = T(start, p - start);
|
||||
start = p + 1;
|
||||
}
|
||||
const size_t r = i;
|
||||
for (; i < parts_len; ++i) {
|
||||
parts[i] = T();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
split(char delim, const string_ref& buf, string_ref *parts,
|
||||
size_t parts_len)
|
||||
{
|
||||
return split_tmpl_arr(delim, buf, parts, parts_len);
|
||||
}
|
||||
|
||||
size_t
|
||||
split(char delim, const string_wref& buf, string_wref *parts,
|
||||
size_t parts_len)
|
||||
{
|
||||
return split_tmpl_arr(delim, buf, parts, parts_len);
|
||||
}
|
||||
|
||||
template <typename T, typename V> size_t
|
||||
split_tmpl_vec(char delim, const T& buf, V& parts)
|
||||
{
|
||||
typedef typename T::value_type value_type;
|
||||
size_t i = 0;
|
||||
value_type *start = buf.begin();
|
||||
value_type *const finish = buf.end();
|
||||
while (true) {
|
||||
value_type *const p = memchr_char(start, delim, finish - start);
|
||||
if (p == 0) {
|
||||
parts.push_back(T(start, finish - start));
|
||||
break;
|
||||
}
|
||||
parts.push_back(T(start, p - start));
|
||||
start = p + 1;
|
||||
}
|
||||
const size_t r = i;
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
split(char delim, const string_ref& buf, std::vector<string_ref>& parts_r)
|
||||
{
|
||||
return split_tmpl_vec(delim, buf, parts_r);
|
||||
}
|
||||
|
||||
size_t
|
||||
split(char delim, const string_wref& buf, std::vector<string_wref>& parts_r)
|
||||
{
|
||||
return split_tmpl_vec(delim, buf, parts_r);
|
||||
}
|
||||
|
||||
};
|
||||
|
53
plugin/handler_socket/libhsclient/string_util.hpp
Normal file
53
plugin/handler_socket/libhsclient/string_util.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_STRING_UTIL_HPP
|
||||
#define DENA_STRING_UTIL_HPP
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "string_buffer.hpp"
|
||||
#include "string_ref.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
inline const char *
|
||||
memchr_char(const char *s, int c, size_t n)
|
||||
{
|
||||
return static_cast<const char *>(memchr(s, c, n));
|
||||
}
|
||||
|
||||
inline char *
|
||||
memchr_char(char *s, int c, size_t n)
|
||||
{
|
||||
return static_cast<char *>(memchr(s, c, n));
|
||||
}
|
||||
|
||||
string_wref get_token(char *& wp, char *wp_end, char delim);
|
||||
uint32_t atoi_uint32_nocheck(const char *start, const char *finish);
|
||||
std::string to_stdstring(uint32_t v);
|
||||
void append_uint32(string_buffer& buf, uint32_t v);
|
||||
long long atoll_nocheck(const char *start, const char *finish);
|
||||
|
||||
int errno_string(const char *s, int en, std::string& err_r);
|
||||
|
||||
size_t split(char delim, const string_ref& buf, string_ref *parts,
|
||||
size_t parts_len);
|
||||
size_t split(char delim, const string_wref& buf, string_wref *parts,
|
||||
size_t parts_len);
|
||||
size_t split(char delim, const string_ref& buf,
|
||||
std::vector<string_ref>& parts_r);
|
||||
size_t split(char delim, const string_wref& buf,
|
||||
std::vector<string_wref>& parts_r);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
84
plugin/handler_socket/libhsclient/thread.hpp
Normal file
84
plugin/handler_socket/libhsclient/thread.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_THREAD_HPP
|
||||
#define DENA_THREAD_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "fatal.hpp"
|
||||
|
||||
namespace dena {
|
||||
|
||||
template <typename T>
|
||||
struct thread : private noncopyable {
|
||||
template <typename Ta> thread(const Ta& arg, size_t stack_sz = 256 * 1024)
|
||||
: obj(arg), thr(0), need_join(false), stack_size(stack_sz) { }
|
||||
template <typename Ta0, typename Ta1> thread(const Ta0& a0,
|
||||
volatile Ta1& a1, size_t stack_sz = 256 * 1024)
|
||||
: obj(a0, a1), thr(0), need_join(false), stack_size(stack_sz) { }
|
||||
~thread() {
|
||||
join();
|
||||
}
|
||||
void start() {
|
||||
if (!start_nothrow()) {
|
||||
fatal_abort("thread::start");
|
||||
}
|
||||
}
|
||||
bool start_nothrow() {
|
||||
if (need_join) {
|
||||
return need_join; /* true */
|
||||
}
|
||||
void *const arg = this;
|
||||
pthread_attr_t attr;
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
fatal_abort("pthread_attr_init");
|
||||
}
|
||||
if (pthread_attr_setstacksize(&attr, stack_size) != 0) {
|
||||
fatal_abort("pthread_attr_setstacksize");
|
||||
}
|
||||
const int r = pthread_create(&thr, &attr, thread_main, arg);
|
||||
if (pthread_attr_destroy(&attr) != 0) {
|
||||
fatal_abort("pthread_attr_destroy");
|
||||
}
|
||||
if (r != 0) {
|
||||
return need_join; /* false */
|
||||
}
|
||||
need_join = true;
|
||||
return need_join; /* true */
|
||||
}
|
||||
void join() {
|
||||
if (!need_join) {
|
||||
return;
|
||||
}
|
||||
int e = 0;
|
||||
if ((e = pthread_join(thr, 0)) != 0) {
|
||||
fatal_abort("pthread_join");
|
||||
}
|
||||
need_join = false;
|
||||
}
|
||||
T& operator *() { return obj; }
|
||||
T *operator ->() { return &obj; }
|
||||
private:
|
||||
static void *thread_main(void *arg) {
|
||||
thread *p = static_cast<thread *>(arg);
|
||||
p->obj();
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
T obj;
|
||||
pthread_t thr;
|
||||
bool need_join;
|
||||
size_t stack_size;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
25
plugin/handler_socket/libhsclient/util.hpp
Normal file
25
plugin/handler_socket/libhsclient/util.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// vim:sw=2:ai
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#ifndef DENA_UTIL_HPP
|
||||
#define DENA_UTIL_HPP
|
||||
|
||||
namespace dena {
|
||||
|
||||
/* boost::noncopyable */
|
||||
struct noncopyable {
|
||||
noncopyable() { }
|
||||
private:
|
||||
noncopyable(const noncopyable&);
|
||||
noncopyable& operator =(const noncopyable&);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
130
plugin/handler_socket/misc/microbench-hs.log
Normal file
130
plugin/handler_socket/misc/microbench-hs.log
Normal file
@ -0,0 +1,130 @@
|
||||
[a@c54hdd libhsclient]$ ./hstest_hs.sh host=192.168.100.104 key_mask=1000000 num_threads=100 num=10000000 timelimit=10 dbname=hstest
|
||||
now: 1274127653 cntdiff: 265538 tdiff: 1.000996 rps: 265273.757409
|
||||
now: 1274127654 cntdiff: 265762 tdiff: 1.000995 rps: 265497.850684
|
||||
now: 1274127655 cntdiff: 265435 tdiff: 1.001010 rps: 265167.196749
|
||||
now: 1274127656 cntdiff: 265144 tdiff: 1.000994 rps: 264880.654203
|
||||
now: 1274127657 cntdiff: 265593 tdiff: 1.000995 rps: 265329.018659
|
||||
now: 1274127658 cntdiff: 264863 tdiff: 1.000996 rps: 264599.492138
|
||||
now: 1274127659 cntdiff: 265688 tdiff: 1.001008 rps: 265420.447231
|
||||
now: 1274127660 cntdiff: 265727 tdiff: 1.000999 rps: 265461.810594
|
||||
now: 1274127661 cntdiff: 265848 tdiff: 1.001010 rps: 265579.716809
|
||||
now: 1274127662 cntdiff: 265430 tdiff: 1.000992 rps: 265167.001723
|
||||
now: 1274127663 cntdiff: 266379 tdiff: 1.001008 rps: 266110.751381
|
||||
now: 1274127664 cntdiff: 266244 tdiff: 1.001003 rps: 265977.217679
|
||||
now: 1274127665 cntdiff: 265737 tdiff: 1.000996 rps: 265472.559379
|
||||
now: 1274127666 cntdiff: 265878 tdiff: 1.001003 rps: 265611.647683
|
||||
(1274127656.104648: 1328292, 1274127666.114649: 3985679), 265473.20173 qps
|
||||
|
||||
|
||||
*************************** 1. row ***************************
|
||||
Type: InnoDB
|
||||
Name:
|
||||
Status:
|
||||
=====================================
|
||||
100518 5:18:13 INNODB MONITOR OUTPUT
|
||||
=====================================
|
||||
Per second averages calculated from the last 5 seconds
|
||||
----------
|
||||
BACKGROUND THREAD
|
||||
----------
|
||||
srv_master_thread loops: 191 1_second, 190 sleeps, 18 10_second, 5 background, 5 flush
|
||||
srv_master_thread log flush and writes: 190
|
||||
----------
|
||||
SEMAPHORES
|
||||
----------
|
||||
OS WAIT ARRAY INFO: reservation count 53519, signal count 29547
|
||||
Mutex spin waits 3083488, rounds 5159906, OS waits 50700
|
||||
RW-shared spins 21, OS waits 16; RW-excl spins 1, OS waits 4
|
||||
Spin rounds per wait: 1.67 mutex, 30.00 RW-shared, 151.00 RW-excl
|
||||
------------
|
||||
TRANSACTIONS
|
||||
------------
|
||||
Trx id counter EDA36085
|
||||
Purge done for trx's n:o < EC1F94A7 undo n:o < 0
|
||||
History list length 20
|
||||
LIST OF TRANSACTIONS FOR EACH SESSION:
|
||||
---TRANSACTION 0, not started, process no 4533, OS thread id 1079281984
|
||||
MySQL thread id 11, query id 16 localhost root
|
||||
show engine innodb status
|
||||
---TRANSACTION ED9D5959, not started, process no 4533, OS thread id 1089849664
|
||||
MySQL thread id 7, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION ED9D5956, not started, process no 4533, OS thread id 1238796608
|
||||
MySQL thread id 1, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION EDA36084, not started, process no 4533, OS thread id 1255582016
|
||||
mysql tables in use 1, locked 1
|
||||
MySQL thread id 3, query id 0 handlersocket: mode=rd, 12 conns, 7 active
|
||||
---TRANSACTION EDA36080, not started, process no 4533, OS thread id 1247189312
|
||||
mysql tables in use 1, locked 1
|
||||
MySQL thread id 2, query id 0 handlersocket: mode=rd, 36 conns, 18 active
|
||||
---TRANSACTION EDA36082, ACTIVE 0 sec, process no 4533, OS thread id 1263974720 committing
|
||||
MySQL thread id 4, query id 0 handlersocket: mode=rd, 37 conns, 20 active
|
||||
Trx read view will not see trx with id >= EDA36083, sees < EDA3607D
|
||||
---TRANSACTION EDA3607D, ACTIVE 0 sec, process no 4533, OS thread id 1272367424, thread declared inside InnoDB 500
|
||||
mysql tables in use 1, locked 1
|
||||
MySQL thread id 5, query id 0 handlersocket: mode=rd, 15 conns, 9 active
|
||||
Trx read view will not see trx with id >= EDA3607E, sees < EDA36079
|
||||
--------
|
||||
FILE I/O
|
||||
--------
|
||||
I/O thread 0 state: waiting for i/o request (insert buffer thread)
|
||||
I/O thread 1 state: waiting for i/o request (log thread)
|
||||
I/O thread 2 state: waiting for i/o request (read thread)
|
||||
I/O thread 3 state: waiting for i/o request (read thread)
|
||||
I/O thread 4 state: waiting for i/o request (read thread)
|
||||
I/O thread 5 state: waiting for i/o request (read thread)
|
||||
I/O thread 6 state: waiting for i/o request (write thread)
|
||||
I/O thread 7 state: waiting for i/o request (write thread)
|
||||
I/O thread 8 state: waiting for i/o request (write thread)
|
||||
I/O thread 9 state: waiting for i/o request (write thread)
|
||||
Pending normal aio reads: 0, aio writes: 0,
|
||||
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
|
||||
Pending flushes (fsync) log: 0; buffer pool: 0
|
||||
71 OS file reads, 235 OS file writes, 235 OS fsyncs
|
||||
0.00 reads/s, 0 avg bytes/read, 1.00 writes/s, 1.00 fsyncs/s
|
||||
-------------------------------------
|
||||
INSERT BUFFER AND ADAPTIVE HASH INDEX
|
||||
-------------------------------------
|
||||
Ibuf: size 1, free list len 0, seg size 2,
|
||||
0 inserts, 0 merged recs, 0 merges
|
||||
Hash table size 12750011, node heap has 2 buffer(s)
|
||||
267203.76 hash searches/s, 0.00 non-hash searches/s
|
||||
---
|
||||
LOG
|
||||
---
|
||||
Log sequence number 147179727377
|
||||
Log flushed up to 147179726685
|
||||
Last checkpoint at 147179716475
|
||||
0 pending log writes, 0 pending chkp writes
|
||||
194 log i/o's done, 1.00 log i/o's/second
|
||||
----------------------
|
||||
BUFFER POOL AND MEMORY
|
||||
----------------------
|
||||
Total memory allocated 6587154432; in additional pool allocated 0
|
||||
Dictionary memory allocated 33640
|
||||
Buffer pool size 393216
|
||||
Free buffers 393154
|
||||
Database pages 60
|
||||
Old database pages 0
|
||||
Modified db pages 1
|
||||
Pending reads 0
|
||||
Pending writes: LRU 0, flush list 0, single page 0
|
||||
Pages made young 0, not young 0
|
||||
0.00 youngs/s, 0.00 non-youngs/s
|
||||
Pages read 60, created 0, written 23
|
||||
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
|
||||
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
|
||||
Pages read ahead 0.00/s, evicted without access 0.00/s
|
||||
LRU len: 60, unzip_LRU len: 0
|
||||
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
|
||||
--------------
|
||||
ROW OPERATIONS
|
||||
--------------
|
||||
2 queries inside InnoDB, 0 queries in queue
|
||||
3 read views open inside InnoDB
|
||||
Main thread process no. 4533, id 1230403904, state: sleeping
|
||||
Number of rows inserted 0, updated 0, deleted 0, read 37653556
|
||||
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 266608.28 reads/s
|
||||
----------------------------
|
||||
END OF INNODB MONITOR OUTPUT
|
||||
============================
|
||||
|
125
plugin/handler_socket/misc/microbench-my.log
Normal file
125
plugin/handler_socket/misc/microbench-my.log
Normal file
@ -0,0 +1,125 @@
|
||||
|
||||
[a@c54hdd libhsclient]$ ./hstest_my.sh host=192.168.100.104 key_mask=1000000 num_threads=100 num=10000000 timelimit=10 dbname=hstest
|
||||
now: 1274128046 cntdiff: 63061 tdiff: 1.000999 rps: 62998.066579
|
||||
now: 1274128047 cntdiff: 61227 tdiff: 1.001013 rps: 61165.037337
|
||||
now: 1274128048 cntdiff: 61367 tdiff: 1.001029 rps: 61303.917375
|
||||
now: 1274128049 cntdiff: 61959 tdiff: 1.000962 rps: 61899.451554
|
||||
now: 1274128050 cntdiff: 62176 tdiff: 1.001006 rps: 62113.520756
|
||||
now: 1274128051 cntdiff: 61367 tdiff: 1.000998 rps: 61305.815559
|
||||
now: 1274128052 cntdiff: 61644 tdiff: 1.001015 rps: 61581.497988
|
||||
now: 1274128053 cntdiff: 60659 tdiff: 1.000984 rps: 60599.373036
|
||||
now: 1274128054 cntdiff: 59459 tdiff: 1.000996 rps: 59399.831067
|
||||
now: 1274128055 cntdiff: 62310 tdiff: 1.001011 rps: 62247.074757
|
||||
now: 1274128056 cntdiff: 61947 tdiff: 1.000991 rps: 61885.664744
|
||||
now: 1274128057 cntdiff: 60675 tdiff: 1.001006 rps: 60614.029076
|
||||
now: 1274128058 cntdiff: 60312 tdiff: 1.001001 rps: 60251.680861
|
||||
now: 1274128059 cntdiff: 60290 tdiff: 1.001004 rps: 60229.530717
|
||||
(1274128049.309634: 309654, 1274128059.319648: 920493), 61022.79143 qps
|
||||
|
||||
*************************** 1. row ***************************
|
||||
Type: InnoDB
|
||||
Name:
|
||||
Status:
|
||||
=====================================
|
||||
100518 5:24:51 INNODB MONITOR OUTPUT
|
||||
=====================================
|
||||
Per second averages calculated from the last 5 seconds
|
||||
----------
|
||||
BACKGROUND THREAD
|
||||
----------
|
||||
srv_master_thread loops: 220 1_second, 219 sleeps, 21 10_second, 6 background, 6 flush
|
||||
srv_master_thread log flush and writes: 219
|
||||
----------
|
||||
SEMAPHORES
|
||||
----------
|
||||
OS WAIT ARRAY INFO: reservation count 56193, signal count 30826
|
||||
Mutex spin waits 3415153, rounds 5618661, OS waits 53251
|
||||
RW-shared spins 24, OS waits 17; RW-excl spins 1, OS waits 5
|
||||
Spin rounds per wait: 1.65 mutex, 30.00 RW-shared, 181.00 RW-excl
|
||||
------------
|
||||
TRANSACTIONS
|
||||
------------
|
||||
Trx id counter EDB514D6
|
||||
Purge done for trx's n:o < EC1F94A7 undo n:o < 0
|
||||
History list length 20
|
||||
LIST OF TRANSACTIONS FOR EACH SESSION:
|
||||
---TRANSACTION 0, not started, process no 4533, OS thread id 1306585408
|
||||
MySQL thread id 113, query id 920620 localhost root
|
||||
show engine innodb status
|
||||
---TRANSACTION EDA708BB, not started, process no 4533, OS thread id 1272367424
|
||||
MySQL thread id 5, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION ED9D5959, not started, process no 4533, OS thread id 1089849664
|
||||
MySQL thread id 7, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION ED9D5956, not started, process no 4533, OS thread id 1238796608
|
||||
MySQL thread id 1, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION EDA708BD, not started, process no 4533, OS thread id 1255582016
|
||||
MySQL thread id 3, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION EDA708BF, not started, process no 4533, OS thread id 1247189312
|
||||
MySQL thread id 2, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
---TRANSACTION EDA708BE, not started, process no 4533, OS thread id 1263974720
|
||||
MySQL thread id 4, query id 0 handlersocket: mode=rd, 0 conns, 0 active
|
||||
--------
|
||||
FILE I/O
|
||||
--------
|
||||
I/O thread 0 state: waiting for i/o request (insert buffer thread)
|
||||
I/O thread 1 state: waiting for i/o request (log thread)
|
||||
I/O thread 2 state: waiting for i/o request (read thread)
|
||||
I/O thread 3 state: waiting for i/o request (read thread)
|
||||
I/O thread 4 state: waiting for i/o request (read thread)
|
||||
I/O thread 5 state: waiting for i/o request (read thread)
|
||||
I/O thread 6 state: waiting for i/o request (write thread)
|
||||
I/O thread 7 state: waiting for i/o request (write thread)
|
||||
I/O thread 8 state: waiting for i/o request (write thread)
|
||||
I/O thread 9 state: waiting for i/o request (write thread)
|
||||
Pending normal aio reads: 0, aio writes: 0,
|
||||
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
|
||||
Pending flushes (fsync) log: 0; buffer pool: 0
|
||||
71 OS file reads, 269 OS file writes, 269 OS fsyncs
|
||||
0.00 reads/s, 0 avg bytes/read, 2.40 writes/s, 2.40 fsyncs/s
|
||||
-------------------------------------
|
||||
INSERT BUFFER AND ADAPTIVE HASH INDEX
|
||||
-------------------------------------
|
||||
Ibuf: size 1, free list len 0, seg size 2,
|
||||
0 inserts, 0 merged recs, 0 merges
|
||||
Hash table size 12750011, node heap has 2 buffer(s)
|
||||
65739.45 hash searches/s, 0.00 non-hash searches/s
|
||||
---
|
||||
LOG
|
||||
---
|
||||
Log sequence number 147179774153
|
||||
Log flushed up to 147179771813
|
||||
Last checkpoint at 147179761899
|
||||
0 pending log writes, 0 pending chkp writes
|
||||
220 log i/o's done, 1.60 log i/o's/second
|
||||
----------------------
|
||||
BUFFER POOL AND MEMORY
|
||||
----------------------
|
||||
Total memory allocated 6587154432; in additional pool allocated 0
|
||||
Dictionary memory allocated 33640
|
||||
Buffer pool size 393216
|
||||
Free buffers 393154
|
||||
Database pages 60
|
||||
Old database pages 0
|
||||
Modified db pages 1
|
||||
Pending reads 0
|
||||
Pending writes: LRU 0, flush list 0, single page 0
|
||||
Pages made young 0, not young 0
|
||||
0.00 youngs/s, 0.00 non-youngs/s
|
||||
Pages read 60, created 0, written 27
|
||||
0.00 reads/s, 0.00 creates/s, 0.40 writes/s
|
||||
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
|
||||
Pages read ahead 0.00/s, evicted without access 0.00/s
|
||||
LRU len: 60, unzip_LRU len: 0
|
||||
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
|
||||
--------------
|
||||
ROW OPERATIONS
|
||||
--------------
|
||||
0 queries inside InnoDB, 0 queries in queue
|
||||
1 read views open inside InnoDB
|
||||
Main thread process no. 4533, id 1230403904, state: sleeping
|
||||
Number of rows inserted 0, updated 0, deleted 0, read 40071920
|
||||
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 66321.54 reads/s
|
||||
----------------------------
|
||||
END OF INNODB MONITOR OUTPUT
|
||||
============================
|
||||
|
27
plugin/handler_socket/perl-Net-HandlerSocket/COPYRIGHT.txt
Normal file
27
plugin/handler_socket/perl-Net-HandlerSocket/COPYRIGHT.txt
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
Copyright (c) 2010 DeNA Co.,Ltd.
|
||||
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 DeNA Co.,Ltd. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DeNA Co.,Ltd. "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 DeNA Co.,Ltd. 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.
|
||||
|
6
plugin/handler_socket/perl-Net-HandlerSocket/Changes
Normal file
6
plugin/handler_socket/perl-Net-HandlerSocket/Changes
Normal file
@ -0,0 +1,6 @@
|
||||
Revision history for Perl extension HandlerSocket.
|
||||
|
||||
0.01 Wed Mar 31 11:50:23 2010
|
||||
- original version; created by h2xs 1.23 with options
|
||||
-A -n HandlerSocket
|
||||
|
577
plugin/handler_socket/perl-Net-HandlerSocket/HandlerSocket.xs
Normal file
577
plugin/handler_socket/perl-Net-HandlerSocket/HandlerSocket.xs
Normal file
@ -0,0 +1,577 @@
|
||||
|
||||
// vim:ai:sw=2:ts=8
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
* See COPYRIGHT.txt for details.
|
||||
*/
|
||||
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
|
||||
#include "ppport.h"
|
||||
|
||||
#include "hstcpcli.hpp"
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
static SV *
|
||||
arr_get_entry(AV *av, I32 avmax, I32 idx)
|
||||
{
|
||||
if (idx > avmax) {
|
||||
DBG(fprintf(stderr, "arr_get_entry1 %d %d\n", avmax, idx));
|
||||
return 0;
|
||||
}
|
||||
SV **const ev = av_fetch(av, idx, 0);
|
||||
if (ev == 0) {
|
||||
DBG(fprintf(stderr, "arr_get_entry2 %d %d\n", avmax, idx));
|
||||
return 0;
|
||||
}
|
||||
return *ev;
|
||||
}
|
||||
|
||||
static int
|
||||
arr_get_intval(AV *av, I32 avmax, I32 idx, int default_val = 0)
|
||||
{
|
||||
SV *const e = arr_get_entry(av, avmax, idx);
|
||||
if (e == 0) {
|
||||
return default_val;
|
||||
}
|
||||
return SvIV(e);
|
||||
}
|
||||
|
||||
static const char *
|
||||
sv_get_strval(SV *sv)
|
||||
{
|
||||
if (sv == 0 || !SvPOK(sv)) {
|
||||
DBG(fprintf(stderr, "sv_get_strval\n"));
|
||||
return 0;
|
||||
}
|
||||
return SvPV_nolen(sv);
|
||||
}
|
||||
|
||||
static const char *
|
||||
arr_get_strval(AV *av, I32 avmax, I32 idx)
|
||||
{
|
||||
SV *const e = arr_get_entry(av, avmax, idx);
|
||||
return sv_get_strval(e);
|
||||
}
|
||||
|
||||
static AV *
|
||||
sv_get_arrval(SV *sv)
|
||||
{
|
||||
if (sv == 0 || !SvROK(sv)) {
|
||||
DBG(fprintf(stderr, "sv_get_arrval1\n"));
|
||||
return 0;
|
||||
}
|
||||
SV *const svtarget = SvRV(sv);
|
||||
if (svtarget == 0 || SvTYPE(svtarget) != SVt_PVAV) {
|
||||
DBG(fprintf(stderr, "sv_get_arrval2\n"));
|
||||
return 0;
|
||||
}
|
||||
return (AV *)svtarget;
|
||||
}
|
||||
|
||||
static AV *
|
||||
arr_get_arrval(AV *av, I32 avmax, I32 idx)
|
||||
{
|
||||
SV *const e = arr_get_entry(av, avmax, idx);
|
||||
if (e == 0) {
|
||||
DBG(fprintf(stderr, "arr_get_arrval1\n"));
|
||||
return 0;
|
||||
}
|
||||
return sv_get_arrval(e);
|
||||
}
|
||||
|
||||
static void
|
||||
hv_to_strmap(HV *hv, std::map<std::string, std::string>& m_r)
|
||||
{
|
||||
if (hv == 0) {
|
||||
return;
|
||||
}
|
||||
hv_iterinit(hv);
|
||||
HE *hent = 0;
|
||||
while ((hent = hv_iternext(hv)) != 0) {
|
||||
I32 klen = 0;
|
||||
char *const k = hv_iterkey(hent, &klen);
|
||||
DBG(fprintf(stderr, "k=%s\n", k));
|
||||
const std::string key(k, klen);
|
||||
SV *const vsv = hv_iterval(hv, hent);
|
||||
STRLEN vlen = 0;
|
||||
char *const v = SvPV(vsv, vlen);
|
||||
DBG(fprintf(stderr, "v=%s\n", v));
|
||||
const std::string val(v, vlen);
|
||||
m_r[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
strrefarr_push_back(std::vector<dena::string_ref>& a_r, SV *sv)
|
||||
{
|
||||
if (sv == 0 || SvTYPE(sv) == SVt_NULL) {
|
||||
DBG(fprintf(stderr, "strrefarr_push_back: null\n"));
|
||||
return a_r.push_back(dena::string_ref());
|
||||
}
|
||||
STRLEN vlen = 0;
|
||||
char *const v = SvPV(sv, vlen);
|
||||
DBG(fprintf(stderr, "strrefarr_push_back: %s\n", v));
|
||||
a_r.push_back(dena::string_ref(v, vlen));
|
||||
}
|
||||
|
||||
static void
|
||||
av_to_strrefarr(AV *av, std::vector<dena::string_ref>& a_r)
|
||||
{
|
||||
if (av == 0) {
|
||||
return;
|
||||
}
|
||||
const I32 len = av_len(av) + 1;
|
||||
for (I32 i = 0; i < len; ++i) {
|
||||
SV **const ev = av_fetch(av, i, 0);
|
||||
strrefarr_push_back(a_r, ev ? *ev : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static dena::string_ref
|
||||
sv_get_string_ref(SV *sv)
|
||||
{
|
||||
if (sv == 0) {
|
||||
return dena::string_ref();
|
||||
}
|
||||
STRLEN vlen = 0;
|
||||
char *const v = SvPV(sv, vlen);
|
||||
return dena::string_ref(v, vlen);
|
||||
}
|
||||
|
||||
static IV
|
||||
sv_get_iv(SV *sv)
|
||||
{
|
||||
if (sv == 0 || !SvIOK(sv)) {
|
||||
return 0;
|
||||
}
|
||||
return SvIV(sv);
|
||||
}
|
||||
|
||||
static void
|
||||
av_to_filters(AV *av, std::vector<dena::hstcpcli_filter>& f_r)
|
||||
{
|
||||
DBG(fprintf(stderr, "av_to_filters: %p\n", av));
|
||||
if (av == 0) {
|
||||
return;
|
||||
}
|
||||
const I32 len = av_len(av) + 1;
|
||||
DBG(fprintf(stderr, "av_to_filters: len=%d\n", (int)len));
|
||||
for (I32 i = 0; i < len; ++i) {
|
||||
AV *const earr = arr_get_arrval(av, len, i);
|
||||
if (earr == 0) {
|
||||
continue;
|
||||
}
|
||||
const I32 earrlen = av_len(earr) + 1;
|
||||
dena::hstcpcli_filter fe;
|
||||
fe.filter_type = sv_get_string_ref(arr_get_entry(earr, earrlen, 0));
|
||||
fe.op = sv_get_string_ref(arr_get_entry(earr, earrlen, 1));
|
||||
fe.ff_offset = sv_get_iv(arr_get_entry(earr, earrlen, 2));
|
||||
fe.val = sv_get_string_ref(arr_get_entry(earr, earrlen, 3));
|
||||
f_r.push_back(fe);
|
||||
DBG(fprintf(stderr, "av_to_filters: %s %s %d %s\n",
|
||||
fe.filter_action.begin(), fe.filter_op.begin(), (int)fe.ff_offset,
|
||||
fe.value.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_process_verbose_level(const std::map<std::string, std::string>& m)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator iter = m.find("verbose");
|
||||
if (iter != m.end()) {
|
||||
dena::verbose_level = atoi(iter->second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static AV *
|
||||
execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
|
||||
int skip, const char *modop, AV *modvals, AV *filters)
|
||||
{
|
||||
AV *retval = (AV *)&PL_sv_undef;
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
do {
|
||||
std::vector<dena::string_ref> keyarr, mvarr;
|
||||
std::vector<dena::hstcpcli_filter> farr;
|
||||
av_to_strrefarr(keys, keyarr);
|
||||
dena::string_ref modop_ref;
|
||||
if (modop != 0) {
|
||||
modop_ref = dena::string_ref(modop, strlen(modop));
|
||||
av_to_strrefarr(modvals, mvarr);
|
||||
}
|
||||
if (filters != 0) {
|
||||
av_to_filters(filters, farr);
|
||||
}
|
||||
ptr->request_buf_exec_generic(id, dena::string_ref(op, strlen(op)),
|
||||
&keyarr[0], keyarr.size(), limit, skip, modop_ref, &mvarr[0],
|
||||
mvarr.size(), &farr[0], farr.size());
|
||||
AV *const av = newAV();
|
||||
retval = av;
|
||||
if (ptr->request_send() != 0) {
|
||||
break;
|
||||
}
|
||||
size_t nflds = 0;
|
||||
ptr->response_recv(nflds);
|
||||
const int e = ptr->get_error_code();
|
||||
DBG(fprintf(stderr, "e=%d nflds=%zu\n", e, nflds));
|
||||
av_push(av, newSViv(e));
|
||||
if (e != 0) {
|
||||
const std::string s = ptr->get_error();
|
||||
av_push(av, newSVpvn(s.data(), s.size()));
|
||||
} else {
|
||||
const dena::string_ref *row = 0;
|
||||
while ((row = ptr->get_next_row()) != 0) {
|
||||
DBG(fprintf(stderr, "row=%p\n", row));
|
||||
for (size_t i = 0; i < nflds; ++i) {
|
||||
const dena::string_ref& v = row[i];
|
||||
DBG(fprintf(stderr, "FLD %zu v=%s vbegin=%p\n", i,
|
||||
std::string(v.begin(), v.size())
|
||||
.c_str(), v.begin()));
|
||||
if (v.begin() != 0) {
|
||||
SV *const e = newSVpvn(
|
||||
v.begin(), v.size());
|
||||
av_push(av, e);
|
||||
} else {
|
||||
av_push(av, &PL_sv_undef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e >= 0) {
|
||||
ptr->response_buf_remove();
|
||||
}
|
||||
} while (0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
struct execute_arg {
|
||||
int id;
|
||||
const char *op;
|
||||
AV *keys;
|
||||
int limit;
|
||||
int skip;
|
||||
const char *modop;
|
||||
AV *modvals;
|
||||
AV *filters;
|
||||
execute_arg() : id(0), op(0), keys(0), limit(0), skip(0), modop(0),
|
||||
modvals(0), filters(0) { }
|
||||
};
|
||||
|
||||
static AV *
|
||||
execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args)
|
||||
{
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
/* appends multiple requests to the send buffer */
|
||||
for (size_t i = 0; i < num_args; ++i) {
|
||||
std::vector<dena::string_ref> keyarr, mvarr;
|
||||
std::vector<dena::hstcpcli_filter> farr;
|
||||
const execute_arg& arg = args[i];
|
||||
av_to_strrefarr(arg.keys, keyarr);
|
||||
dena::string_ref modop_ref;
|
||||
if (arg.modop != 0) {
|
||||
modop_ref = dena::string_ref(arg.modop, strlen(arg.modop));
|
||||
av_to_strrefarr(arg.modvals, mvarr);
|
||||
}
|
||||
if (arg.filters != 0) {
|
||||
av_to_filters(arg.filters, farr);
|
||||
}
|
||||
ptr->request_buf_exec_generic(arg.id,
|
||||
dena::string_ref(arg.op, strlen(arg.op)), &keyarr[0], keyarr.size(),
|
||||
arg.limit, arg.skip, modop_ref, &mvarr[0], mvarr.size(), &farr[0],
|
||||
farr.size());
|
||||
}
|
||||
AV *const retval = newAV();
|
||||
/* sends the requests */
|
||||
if (ptr->request_send() < 0) {
|
||||
/* IO error */
|
||||
AV *const av_respent = newAV();
|
||||
av_push(retval, newRV_noinc((SV *)av_respent));
|
||||
av_push(av_respent, newSViv(ptr->get_error_code()));
|
||||
const std::string& s = ptr->get_error();
|
||||
av_push(av_respent, newSVpvn(s.data(), s.size()));
|
||||
return retval; /* retval : [ [ err_code, err_message ] ] */
|
||||
}
|
||||
/* receives responses */
|
||||
for (size_t i = 0; i < num_args; ++i) {
|
||||
AV *const av_respent = newAV();
|
||||
av_push(retval, newRV_noinc((SV *)av_respent));
|
||||
size_t nflds = 0;
|
||||
const int e = ptr->response_recv(nflds);
|
||||
av_push(av_respent, newSViv(e));
|
||||
if (e != 0) {
|
||||
const std::string& s = ptr->get_error();
|
||||
av_push(av_respent, newSVpvn(s.data(), s.size()));
|
||||
} else {
|
||||
const dena::string_ref *row = 0;
|
||||
while ((row = ptr->get_next_row()) != 0) {
|
||||
for (size_t i = 0; i < nflds; ++i) {
|
||||
const dena::string_ref& v = row[i];
|
||||
DBG(fprintf(stderr, "%zu %s\n", i,
|
||||
std::string(v.begin(), v.size()).c_str()));
|
||||
if (v.begin() != 0) {
|
||||
av_push(av_respent, newSVpvn(v.begin(), v.size()));
|
||||
} else {
|
||||
/* null */
|
||||
av_push(av_respent, &PL_sv_undef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e >= 0) {
|
||||
ptr->response_buf_remove();
|
||||
}
|
||||
if (e < 0) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
MODULE = Net::HandlerSocket PACKAGE = Net::HandlerSocket
|
||||
|
||||
SV *
|
||||
new(klass, args)
|
||||
char *klass
|
||||
HV *args
|
||||
CODE:
|
||||
RETVAL = &PL_sv_undef;
|
||||
dena::config conf;
|
||||
hv_to_strmap(args, conf);
|
||||
set_process_verbose_level(conf);
|
||||
dena::socket_args sargs;
|
||||
sargs.set(conf);
|
||||
dena::hstcpcli_ptr p = dena::hstcpcli_i::create(sargs);
|
||||
SV *const objref = newSViv(0);
|
||||
SV *const obj = newSVrv(objref, klass);
|
||||
dena::hstcpcli_i *const ptr = p.get();
|
||||
sv_setiv(obj, reinterpret_cast<IV>(ptr));
|
||||
p.release();
|
||||
SvREADONLY_on(obj);
|
||||
RETVAL = objref;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
DESTROY(obj)
|
||||
SV *obj
|
||||
CODE:
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
delete ptr;
|
||||
|
||||
void
|
||||
close(obj)
|
||||
SV *obj
|
||||
CODE:
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
ptr->close();
|
||||
|
||||
int
|
||||
reconnect(obj)
|
||||
SV *obj
|
||||
CODE:
|
||||
RETVAL = 0;
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
RETVAL = ptr->reconnect();
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
stable_point(obj)
|
||||
SV *obj
|
||||
CODE:
|
||||
RETVAL = 0;
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
const bool rv = ptr->stable_point();
|
||||
RETVAL = static_cast<int>(rv);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
get_error_code(obj)
|
||||
SV *obj
|
||||
CODE:
|
||||
RETVAL = 0;
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
RETVAL = ptr->get_error_code();
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
SV *
|
||||
get_error(obj)
|
||||
SV *obj
|
||||
CODE:
|
||||
RETVAL = &PL_sv_undef;
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
const std::string s = ptr->get_error();
|
||||
RETVAL = newSVpvn(s.data(), s.size());
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
open_index(obj, id, db, table, index, fields, ffields = 0)
|
||||
SV *obj
|
||||
int id
|
||||
const char *db
|
||||
const char *table
|
||||
const char *index
|
||||
const char *fields
|
||||
SV *ffields
|
||||
CODE:
|
||||
const char *const ffields_str = sv_get_strval(ffields);
|
||||
RETVAL = 0;
|
||||
dena::hstcpcli_i *const ptr =
|
||||
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
|
||||
do {
|
||||
ptr->request_buf_open_index(id, db, table, index, fields, ffields_str);
|
||||
if (ptr->request_send() != 0) {
|
||||
break;
|
||||
}
|
||||
size_t nflds = 0;
|
||||
ptr->response_recv(nflds);
|
||||
const int e = ptr->get_error_code();
|
||||
DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
|
||||
if (e >= 0) {
|
||||
ptr->response_buf_remove();
|
||||
}
|
||||
DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
|
||||
} while (0);
|
||||
RETVAL = ptr->get_error_code();
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
AV *
|
||||
execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
|
||||
SV *obj
|
||||
int id
|
||||
const char *op
|
||||
AV *keys
|
||||
int limit
|
||||
int skip
|
||||
SV *mop
|
||||
SV *mvs
|
||||
SV *fils
|
||||
CODE:
|
||||
const char *const mop_str = sv_get_strval(mop);
|
||||
AV *const mvs_av = sv_get_arrval(mvs);
|
||||
AV *const fils_av = sv_get_arrval(fils);
|
||||
RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
|
||||
fils_av);
|
||||
sv_2mortal((SV *)RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
AV *
|
||||
execute_multi(obj, cmds)
|
||||
SV *obj
|
||||
AV *cmds
|
||||
CODE:
|
||||
DBG(fprintf(stderr, "execute_multi0\n"));
|
||||
const I32 cmdsmax = av_len(cmds);
|
||||
execute_arg args[cmdsmax + 1]; /* GNU */
|
||||
for (I32 i = 0; i <= cmdsmax; ++i) {
|
||||
AV *const avtarget = arr_get_arrval(cmds, cmdsmax, i);
|
||||
if (avtarget == 0) {
|
||||
DBG(fprintf(stderr, "execute_multi1 %d\n", i));
|
||||
continue;
|
||||
}
|
||||
const I32 argmax = av_len(avtarget);
|
||||
if (argmax < 2) {
|
||||
DBG(fprintf(stderr, "execute_multi2 %d\n", i));
|
||||
continue;
|
||||
}
|
||||
execute_arg& ag = args[i];
|
||||
ag.id = arr_get_intval(avtarget, argmax, 0);
|
||||
ag.op = arr_get_strval(avtarget, argmax, 1);
|
||||
ag.keys = arr_get_arrval(avtarget, argmax, 2);
|
||||
ag.limit = arr_get_intval(avtarget, argmax, 3);
|
||||
ag.skip = arr_get_intval(avtarget, argmax, 4);
|
||||
ag.modop = arr_get_strval(avtarget, argmax, 5);
|
||||
ag.modvals = arr_get_arrval(avtarget, argmax, 6);
|
||||
ag.filters = arr_get_arrval(avtarget, argmax, 7);
|
||||
DBG(fprintf(stderr, "execute_multi3 %d: %d %s %p %d %d %s %p %p\n",
|
||||
i, ag.id, ag.op, ag.keys, ag.limit, ag.skip, ag.modop, ag.modvals,
|
||||
ag.filters));
|
||||
}
|
||||
RETVAL = execute_multi_internal(obj, args, cmdsmax + 1);
|
||||
sv_2mortal((SV *)RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
AV *
|
||||
execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
|
||||
SV *obj
|
||||
int id
|
||||
const char *op
|
||||
AV *keys
|
||||
int limit
|
||||
int skip
|
||||
SV *mop
|
||||
SV *mvs
|
||||
SV *fils
|
||||
CODE:
|
||||
const char *const mop_str = sv_get_strval(mop);
|
||||
AV *const mvs_av = sv_get_arrval(mvs);
|
||||
AV *const fils_av = sv_get_arrval(fils);
|
||||
RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
|
||||
fils_av);
|
||||
sv_2mortal((SV *)RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
AV *
|
||||
execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0)
|
||||
SV *obj
|
||||
int id
|
||||
const char *op
|
||||
AV *keys
|
||||
int limit
|
||||
int skip
|
||||
AV *modvals
|
||||
SV *fils
|
||||
CODE:
|
||||
AV *const fils_av = sv_get_arrval(fils);
|
||||
RETVAL = execute_internal(obj, id, op, keys, limit, skip, "U",
|
||||
modvals, fils_av);
|
||||
sv_2mortal((SV *)RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
AV *
|
||||
execute_delete(obj, id, op, keys, limit, skip, fils = 0)
|
||||
SV *obj
|
||||
int id
|
||||
const char *op
|
||||
AV *keys
|
||||
int limit
|
||||
int skip
|
||||
SV *fils
|
||||
CODE:
|
||||
AV *const fils_av = sv_get_arrval(fils);
|
||||
RETVAL = execute_internal(obj, id, op, keys, limit, skip, "D", 0, fils_av);
|
||||
sv_2mortal((SV *)RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
AV *
|
||||
execute_insert(obj, id, fvals)
|
||||
SV *obj
|
||||
int id
|
||||
AV *fvals
|
||||
CODE:
|
||||
RETVAL = execute_internal(obj, id, "+", fvals, 0, 0, 0, 0, 0);
|
||||
sv_2mortal((SV *)RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
8
plugin/handler_socket/perl-Net-HandlerSocket/MANIFEST
Normal file
8
plugin/handler_socket/perl-Net-HandlerSocket/MANIFEST
Normal file
@ -0,0 +1,8 @@
|
||||
Changes
|
||||
HandlerSocket.xs
|
||||
Makefile.PL
|
||||
MANIFEST
|
||||
ppport.h
|
||||
README
|
||||
t/HandlerSocket.t
|
||||
lib/HandlerSocket.pm
|
18
plugin/handler_socket/perl-Net-HandlerSocket/Makefile.PL
Normal file
18
plugin/handler_socket/perl-Net-HandlerSocket/Makefile.PL
Normal file
@ -0,0 +1,18 @@
|
||||
# use 5.010000;
|
||||
use ExtUtils::MakeMaker;
|
||||
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
|
||||
# the contents of the Makefile that is written.
|
||||
WriteMakefile(
|
||||
NAME => 'Net::HandlerSocket',
|
||||
VERSION_FROM => 'lib/Net/HandlerSocket.pm', # finds $VERSION
|
||||
PREREQ_PM => {}, # e.g., Module::Name => 1.1
|
||||
($] >= 5.005 ? ## Add these new keywords supported since 5.005
|
||||
(ABSTRACT_FROM => 'lib/Net/HandlerSocket.pm', # retrieve abstract from module
|
||||
AUTHOR => 'higuchi dot akira at dena dot jp>') : ()),
|
||||
CC => 'g++ -fPIC',
|
||||
LD => 'g++ -fPIC',
|
||||
LIBS => ['-L../libhsclient -L../libhsclient/.libs -lhsclient'],
|
||||
DEFINE => '',
|
||||
INC => '-I. -I../libhsclient',
|
||||
OPTIMIZE => '-g -O3 -Wall -Wno-unused',
|
||||
);
|
@ -0,0 +1,20 @@
|
||||
# use 5.010000;
|
||||
use ExtUtils::MakeMaker;
|
||||
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
|
||||
# the contents of the Makefile that is written.
|
||||
WriteMakefile(
|
||||
NAME => 'Net::HandlerSocket',
|
||||
VERSION_FROM => 'lib/Net/HandlerSocket.pm', # finds $VERSION
|
||||
PREREQ_PM => {}, # e.g., Module::Name => 1.1
|
||||
($] >= 5.005 ? ## Add these new keywords supported since 5.005
|
||||
(ABSTRACT_FROM => 'lib/Net/HandlerSocket.pm', # retrieve abstract from module
|
||||
AUTHOR => 'higuchi dot akira at dena dot jp>') : ()),
|
||||
CC => 'g++ -fPIC',
|
||||
LD => 'g++ -fPIC',
|
||||
LIBS => ['-lhsclient'], # e.g., '-lm'
|
||||
DEFINE => '', # e.g., '-DHAVE_SOMETHING'
|
||||
INC => '-I. -I/usr/include/handlersocket',
|
||||
OPTIMIZE => '-g -O3 -Wall -Wno-unused',
|
||||
# Un-comment this if you add C files to link with later:
|
||||
# OBJECT => '$(O_FILES)', # link all the C files too
|
||||
);
|
30
plugin/handler_socket/perl-Net-HandlerSocket/README
Normal file
30
plugin/handler_socket/perl-Net-HandlerSocket/README
Normal file
@ -0,0 +1,30 @@
|
||||
HandlerSocket version 0.01
|
||||
==========================
|
||||
|
||||
The README is used to introduce the module and provide instructions on
|
||||
how to install the module, any machine dependencies it may have (for
|
||||
example C compilers and installed libraries) and any other information
|
||||
that should be provided before the module is installed.
|
||||
|
||||
A README file is required for CPAN modules since CPAN extracts the
|
||||
README file from a module distribution so that people browsing the
|
||||
archive can use it get an idea of the modules uses. It is usually a
|
||||
good idea to provide version information here so that people can
|
||||
decide whether fixes for the module are worth downloading.
|
||||
|
||||
INSTALLATION
|
||||
|
||||
To install this module type the following:
|
||||
|
||||
perl Makefile.PL
|
||||
make
|
||||
make test
|
||||
make install
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
COPYRIGHT AND LICENCE
|
||||
|
||||
Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
See COPYRIGHT.txt for details.
|
||||
|
@ -0,0 +1,68 @@
|
||||
|
||||
package Net::HandlerSocket;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
# Items to export into callers namespace by default. Note: do not export
|
||||
# names by default without a very good reason. Use EXPORT_OK instead.
|
||||
# Do not simply export all your public functions/methods/constants.
|
||||
|
||||
# This allows declaration use Net::HandlerSocket ':all';
|
||||
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
||||
# will save memory.
|
||||
our %EXPORT_TAGS = ( 'all' => [ qw(
|
||||
|
||||
) ] );
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
|
||||
our @EXPORT = qw(
|
||||
|
||||
);
|
||||
|
||||
our $VERSION = '0.01';
|
||||
|
||||
require XSLoader;
|
||||
XSLoader::load('Net::HandlerSocket', $VERSION);
|
||||
|
||||
# Preloaded methods go here.
|
||||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Net::HandlerSocket - Perl extension for blah blah blah
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Net::HandlerSocket;
|
||||
my $hsargs = { host => 'localhost', port => 9999 };
|
||||
my $cli = new Net::HandlerSocket($hsargs);
|
||||
$cli->open_index(1, 'testdb', 'testtable1', 'PRIMARY', 'foo,bar,baz');
|
||||
$cli->open_index(2, 'testdb', 'testtable2', 'i2', 'hoge,fuga');
|
||||
$cli->execute_find(1, '>=', [ 'aaa', 'bbb' ], 5, 100);
|
||||
# select foo,bar,baz from testdb.testtable1
|
||||
# where pk1 = 'aaa' and pk2 = 'bbb' order by pk1, pk2
|
||||
# limit 100, 5
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Stub documentation for Net::HandlerSocket, created by h2xs.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Akira HiguchiE<lt>higuchi dot akira at dena dot jpE<gt>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
|
||||
See COPYRIGHT.txt for details.
|
||||
|
||||
=cut
|
362
plugin/handler_socket/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm
Executable file
362
plugin/handler_socket/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm
Executable file
@ -0,0 +1,362 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
package Net::HandlerSocket::HSPool;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Net::HandlerSocket;
|
||||
use Socket;
|
||||
|
||||
sub new {
|
||||
my $self = {
|
||||
config => $_[1],
|
||||
reopen_interval => 60,
|
||||
hostmap => { },
|
||||
};
|
||||
return bless $self, $_[0];
|
||||
}
|
||||
|
||||
sub clear_pool {
|
||||
my ($self) = @_;
|
||||
$self->{hostmap} = { };
|
||||
}
|
||||
|
||||
sub on_error {
|
||||
my ($self, $obj) = @_;
|
||||
my $error_func = $self->{config}->{error};
|
||||
if (defined($error_func)) {
|
||||
return &{$error_func}($obj);
|
||||
}
|
||||
die $obj;
|
||||
}
|
||||
|
||||
sub on_warning {
|
||||
my ($self, $obj) = @_;
|
||||
my $warning_func = $self->{config}->{warning};
|
||||
if (defined($warning_func)) {
|
||||
return &{$warning_func}($obj);
|
||||
}
|
||||
}
|
||||
|
||||
sub get_conf {
|
||||
my ($self, $dbtbl) = @_;
|
||||
my $hcent = $self->{config}->{hostmap}->{$dbtbl};
|
||||
if (!defined($hcent)) {
|
||||
$self->on_error("get_conf: $dbtbl not found");
|
||||
return undef;
|
||||
}
|
||||
my %cpy = %$hcent;
|
||||
$cpy{port} ||= 9998;
|
||||
$cpy{timeout} ||= 2;
|
||||
return \%cpy;
|
||||
}
|
||||
|
||||
sub resolve_hostname {
|
||||
my ($self, $hcent, $host_ip_list) = @_;
|
||||
if (defined($host_ip_list)) {
|
||||
if (scalar(@$host_ip_list) > 0) {
|
||||
$hcent->{host} = shift(@$host_ip_list);
|
||||
return $host_ip_list;
|
||||
}
|
||||
return undef; # no more ip
|
||||
}
|
||||
my $host = $hcent->{host}; # unresolved name
|
||||
$hcent->{hostname} = $host;
|
||||
my $resolve_list_func = $self->{config}->{resolve_list};
|
||||
if (defined($resolve_list_func)) {
|
||||
$host_ip_list = &{$resolve_list_func}($host);
|
||||
if (scalar(@$host_ip_list) > 0) {
|
||||
$hcent->{host} = shift(@$host_ip_list);
|
||||
return $host_ip_list;
|
||||
}
|
||||
return undef; # no more ip
|
||||
}
|
||||
my $resolve_func = $self->{config}->{resolve};
|
||||
if (defined($resolve_func)) {
|
||||
$hcent->{host} = &{$resolve_func}($host);
|
||||
return [];
|
||||
}
|
||||
my $packed = gethostbyname($host);
|
||||
if (!defined($packed)) {
|
||||
return undef;
|
||||
}
|
||||
$hcent->{host} = inet_ntoa($packed);
|
||||
return [];
|
||||
}
|
||||
|
||||
sub get_handle_exec {
|
||||
my ($self, $db, $tbl, $idx, $cols, $exec_multi, $exec_args) = @_;
|
||||
my $now = time();
|
||||
my $dbtbl = join('.', $db, $tbl);
|
||||
my $hcent = $self->get_conf($dbtbl); # copy
|
||||
if (!defined($hcent)) {
|
||||
return undef;
|
||||
}
|
||||
my $hmkey = join(':', $hcent->{host}, $hcent->{port});
|
||||
my $hment = $self->{hostmap}->{$hmkey};
|
||||
# [ open_time, handle, index_map, host, next_index_id ]
|
||||
my $host_ip_list;
|
||||
TRY_OTHER_IP:
|
||||
if (!defined($hment) ||
|
||||
$hment->[0] + $self->{reopen_interval} < $now ||
|
||||
!$hment->[1]->stable_point()) {
|
||||
$host_ip_list = $self->resolve_hostname($hcent, $host_ip_list);
|
||||
if (!defined($host_ip_list)) {
|
||||
my $hostport = $hmkey . '(' . $hcent->{host} . ')';
|
||||
$self->on_error("HSPool::get_handle" .
|
||||
"($db, $tbl, $idx, $cols): host=$hmkey: " .
|
||||
"no more active ip");
|
||||
return undef;
|
||||
}
|
||||
my $hnd = new Net::HandlerSocket($hcent);
|
||||
my %m = ();
|
||||
$hment = [ $now, $hnd, \%m, $hcent->{host}, 1 ];
|
||||
$self->{hostmap}->{$hmkey} = $hment;
|
||||
}
|
||||
my $hnd = $hment->[1];
|
||||
my $idxmap = $hment->[2];
|
||||
my $imkey = join(':', $idx, $cols);
|
||||
my $idx_id = $idxmap->{$imkey};
|
||||
if (!defined($idx_id)) {
|
||||
$idx_id = $hment->[4];
|
||||
my $e = $hnd->open_index($idx_id, $db, $tbl, $idx, $cols);
|
||||
if ($e != 0) {
|
||||
my $estr = $hnd->get_error();
|
||||
my $hostport = $hmkey . '(' . $hcent->{host} . ')';
|
||||
my $errmess = "HSPool::get_handle open_index" .
|
||||
"($db, $tbl, $idx, $cols): host=$hostport " .
|
||||
"err=$e($estr)";
|
||||
$self->on_warning($errmess);
|
||||
$hnd->close();
|
||||
$hment = undef;
|
||||
goto TRY_OTHER_IP;
|
||||
}
|
||||
$hment->[4]++;
|
||||
$idxmap->{$imkey} = $idx_id;
|
||||
}
|
||||
if ($exec_multi) {
|
||||
my $resarr;
|
||||
for my $cmdent (@$exec_args) {
|
||||
$cmdent->[0] = $idx_id;
|
||||
}
|
||||
if (scalar(@$exec_args) == 0) {
|
||||
$resarr = [];
|
||||
} else {
|
||||
$resarr = $hnd->execute_multi($exec_args);
|
||||
}
|
||||
my $i = 0;
|
||||
for my $res (@$resarr) {
|
||||
if ($res->[0] != 0) {
|
||||
my $cmdent = $exec_args->[$i];
|
||||
my $ec = $res->[0];
|
||||
my $estr = $res->[1];
|
||||
my $op = $cmdent->[1];
|
||||
my $kfvs = $cmdent->[2];
|
||||
my $kvstr = defined($kfvs)
|
||||
? join(',', @$kfvs) : '';
|
||||
my $limit = $cmdent->[3] || 0;
|
||||
my $skip = $cmdent->[4] || 0;
|
||||
my $hostport = $hmkey . '(' . $hcent->{host}
|
||||
. ')';
|
||||
my $errmess = "HSPool::get_handle execm" .
|
||||
"($db, $tbl, $idx, [$cols], " .
|
||||
"($idx_id), $op, [$kvstr] " .
|
||||
"$limit, $skip): " .
|
||||
"host=$hostport err=$ec($estr)";
|
||||
if ($res->[0] < 0 || $res->[0] == 2) {
|
||||
$self->on_warning($errmess);
|
||||
$hnd->close();
|
||||
$hment = undef;
|
||||
goto TRY_OTHER_IP;
|
||||
} else {
|
||||
$self->on_error($errmess);
|
||||
}
|
||||
}
|
||||
shift(@$res);
|
||||
++$i;
|
||||
}
|
||||
return $resarr;
|
||||
} else {
|
||||
my $res = $hnd->execute_find($idx_id, @$exec_args);
|
||||
if ($res->[0] != 0) {
|
||||
my ($op, $kfvals, $limit, $skip) = @$exec_args;
|
||||
my $ec = $res->[0];
|
||||
my $estr = $res->[1];
|
||||
my $kvstr = join(',', @$kfvals);
|
||||
my $hostport = $hmkey . '(' . $hcent->{host} . ')';
|
||||
my $errmess = "HSPool::get_handle exec" .
|
||||
"($db, $tbl, $idx, [$cols], ($idx_id), " .
|
||||
"$op, [$kvstr], $limit, $skip): " .
|
||||
"host=$hostport err=$ec($estr)";
|
||||
if ($res->[0] < 0 || $res->[0] == 2) {
|
||||
$self->on_warning($errmess);
|
||||
$hnd->close();
|
||||
$hment = undef;
|
||||
goto TRY_OTHER_IP;
|
||||
} else {
|
||||
$self->on_error($errmess);
|
||||
}
|
||||
}
|
||||
shift(@$res);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
sub index_find {
|
||||
my ($self, $db, $tbl, $idx, $cols, $op, $kfvals, $limit, $skip) = @_;
|
||||
# cols: comma separated list
|
||||
# kfvals: arrayref
|
||||
$limit ||= 0;
|
||||
$skip ||= 0;
|
||||
my $res = $self->get_handle_exec($db, $tbl, $idx, $cols,
|
||||
0, [ $op, $kfvals, $limit, $skip ]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub index_find_multi {
|
||||
my ($self, $db, $tbl, $idx, $cols, $cmdlist) = @_;
|
||||
# cols : comma separated list
|
||||
# cmdlist : [ dummy, op, kfvals, limit, skip ]
|
||||
# kfvals : arrayref
|
||||
my $resarr = $self->get_handle_exec($db, $tbl, $idx, $cols,
|
||||
1, $cmdlist);
|
||||
return $resarr;
|
||||
}
|
||||
|
||||
sub result_single_to_arrarr {
|
||||
my ($numcols, $hsres, $ret) = @_;
|
||||
my $hsreslen = scalar(@$hsres);
|
||||
my $rlen = int($hsreslen / $numcols);
|
||||
$ret = [ ] if !defined($ret);
|
||||
my @r = ();
|
||||
my $p = 0;
|
||||
for (my $i = 0; $i < $rlen; ++$i) {
|
||||
my @a = splice(@$hsres, $p, $numcols);
|
||||
$p += $numcols;
|
||||
push(@$ret, \@a);
|
||||
}
|
||||
return $ret; # arrayref of arrayrefs
|
||||
}
|
||||
|
||||
sub result_multi_to_arrarr {
|
||||
my ($numcols, $mhsres, $ret) = @_;
|
||||
$ret = [ ] if !defined($ret);
|
||||
for my $hsres (@$mhsres) {
|
||||
my $hsreslen = scalar(@$hsres);
|
||||
my $rlen = int($hsreslen / $numcols);
|
||||
my $p = 0;
|
||||
for (my $i = 0; $i < $rlen; ++$i) {
|
||||
my @a = splice(@$hsres, $p, $numcols);
|
||||
$p += $numcols;
|
||||
push(@$ret, \@a);
|
||||
}
|
||||
}
|
||||
return $ret; # arrayref of arrayrefs
|
||||
}
|
||||
|
||||
sub result_single_to_hasharr {
|
||||
my ($names, $hsres, $ret) = @_;
|
||||
my $nameslen = scalar(@$names);
|
||||
my $hsreslen = scalar(@$hsres);
|
||||
my $rlen = int($hsreslen / $nameslen);
|
||||
$ret = [ ] if !defined($ret);
|
||||
my $p = 0;
|
||||
for (my $i = 0; $i < $rlen; ++$i) {
|
||||
my %h = ();
|
||||
for (my $j = 0; $j < $nameslen; ++$j, ++$p) {
|
||||
$h{$names->[$j]} = $hsres->[$p];
|
||||
}
|
||||
push(@$ret, \%h);
|
||||
}
|
||||
return $ret; # arrayref of hashrefs
|
||||
}
|
||||
|
||||
sub result_multi_to_hasharr {
|
||||
my ($names, $mhsres, $ret) = @_;
|
||||
my $nameslen = scalar(@$names);
|
||||
$ret = [ ] if !defined($ret);
|
||||
for my $hsres (@$mhsres) {
|
||||
my $hsreslen = scalar(@$hsres);
|
||||
my $rlen = int($hsreslen / $nameslen);
|
||||
my $p = 0;
|
||||
for (my $i = 0; $i < $rlen; ++$i) {
|
||||
my %h = ();
|
||||
for (my $j = 0; $j < $nameslen; ++$j, ++$p) {
|
||||
$h{$names->[$j]} = $hsres->[$p];
|
||||
}
|
||||
push(@$ret, \%h);
|
||||
}
|
||||
}
|
||||
return $ret; # arrayref of hashrefs
|
||||
}
|
||||
|
||||
sub result_single_to_hashhash {
|
||||
my ($names, $key, $hsres, $ret) = @_;
|
||||
my $nameslen = scalar(@$names);
|
||||
my $hsreslen = scalar(@$hsres);
|
||||
my $rlen = int($hsreslen / $nameslen);
|
||||
$ret = { } if !defined($ret);
|
||||
my $p = 0;
|
||||
for (my $i = 0; $i < $rlen; ++$i) {
|
||||
my %h = ();
|
||||
for (my $j = 0; $j < $nameslen; ++$j, ++$p) {
|
||||
$h{$names->[$j]} = $hsres->[$p];
|
||||
}
|
||||
my $k = $h{$key};
|
||||
$ret->{$k} = \%h if defined($k);
|
||||
}
|
||||
return $ret; # hashref of hashrefs
|
||||
}
|
||||
|
||||
sub result_multi_to_hashhash {
|
||||
my ($names, $key, $mhsres, $ret) = @_;
|
||||
my $nameslen = scalar(@$names);
|
||||
$ret = { } if !defined($ret);
|
||||
for my $hsres (@$mhsres) {
|
||||
my $hsreslen = scalar(@$hsres);
|
||||
my $rlen = int($hsreslen / $nameslen);
|
||||
my $p = 0;
|
||||
for (my $i = 0; $i < $rlen; ++$i) {
|
||||
my %h = ();
|
||||
for (my $j = 0; $j < $nameslen; ++$j, ++$p) {
|
||||
$h{$names->[$j]} = $hsres->[$p];
|
||||
}
|
||||
my $k = $h{$key};
|
||||
$ret->{$k} = \%h if defined($k);
|
||||
}
|
||||
}
|
||||
return $ret; # hashref of hashrefs
|
||||
}
|
||||
|
||||
sub select_cols_where_eq_aa {
|
||||
# SELECT $cols FROM $db.$tbl WHERE $idx_key = $kv LIMIT 1
|
||||
my ($self, $db, $tbl, $idx, $cols_aref, $kv_aref) = @_;
|
||||
my $cols_str = join(',', @$cols_aref);
|
||||
my $res = $self->index_find($db, $tbl, $idx, $cols_str, '=', $kv_aref);
|
||||
return result_single_to_arrarr(scalar(@$cols_aref), $res);
|
||||
}
|
||||
|
||||
sub select_cols_where_eq_hh {
|
||||
# SELECT $cols FROM $db.$tbl WHERE $idx_key = $kv LIMIT 1
|
||||
my ($self, $db, $tbl, $idx, $cols_aref, $kv_aref, $retkey) = @_;
|
||||
my $cols_str = join(',', @$cols_aref);
|
||||
my $res = $self->index_find($db, $tbl, $idx, $cols_str, '=', $kv_aref);
|
||||
my $r = result_single_to_hashhash($cols_aref, $retkey, $res);
|
||||
return $r;
|
||||
}
|
||||
|
||||
sub select_cols_where_in_hh {
|
||||
# SELECT $cols FROM $db.$tbl WHERE $idx_key in ($vals)
|
||||
my ($self, $db, $tbl, $idx, $cols_aref, $vals_aref, $retkey) = @_;
|
||||
my $cols_str = join(',', @$cols_aref);
|
||||
my @cmdlist = ();
|
||||
for my $v (@$vals_aref) {
|
||||
push(@cmdlist, [ -1, '=', [ $v ] ]);
|
||||
}
|
||||
my $res = $self->index_find_multi($db, $tbl, $idx, $cols_str,
|
||||
\@cmdlist);
|
||||
return result_multi_to_hashhash($cols_aref, $retkey, $res);
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -0,0 +1,127 @@
|
||||
#
|
||||
# - HandlerSocket -
|
||||
# This spec file was automatically generated by cpan2rpm [ver: 2.027]
|
||||
# The following arguments were used:
|
||||
# --no-sign perl-Net-HandlerSocket.tar.gz
|
||||
# For more information on cpan2rpm please visit: http://perl.arix.com/
|
||||
#
|
||||
|
||||
%define pkgname perl-Net-HandlerSocket
|
||||
%define filelist %{pkgname}-%{version}-filelist
|
||||
%define NVR %{pkgname}-%{version}-%{release}
|
||||
%define maketest 1
|
||||
|
||||
name: perl-Net-HandlerSocket
|
||||
summary: HandlerSocket - Perl extension for handlersocket
|
||||
version: HANDLERSOCKET_VERSION
|
||||
release: 1%{?dist}
|
||||
packager: Akira Higuchi <higuchi dot akira at dena dot jp>
|
||||
license: BSD
|
||||
group: Applications/CPAN
|
||||
group: System Environment/Libraries
|
||||
buildroot: %{_tmppath}/%{name}-%{version}-%(id -u -n)
|
||||
prefix: %(echo %{_prefix})
|
||||
source: perl-Net-HandlerSocket.tar.gz
|
||||
BuildRequires: libhsclient
|
||||
Requires: libhsclient
|
||||
Obsoletes: perl-DB-HandlerSocket
|
||||
|
||||
%description
|
||||
Stub documentation for HandlerSocket, created by h2xs. It looks like the
|
||||
author of the extension was negligent enough to leave the stub
|
||||
unedited.
|
||||
|
||||
#
|
||||
# This package was generated automatically with the cpan2rpm
|
||||
# utility. To get this software or for more information
|
||||
# please visit: http://perl.arix.com/
|
||||
#
|
||||
|
||||
%prep
|
||||
%setup -q -n %{pkgname}
|
||||
chmod -R u+w %{_builddir}/%{pkgname}
|
||||
|
||||
%build
|
||||
grep -rsl '^#!.*perl' . |
|
||||
grep -v '.bak$' |xargs --no-run-if-empty \
|
||||
%__perl -MExtUtils::MakeMaker -e 'MY->fixin(@ARGV)'
|
||||
CFLAGS="$RPM_OPT_FLAGS"
|
||||
%{__perl} Makefile.PL.installed `%{__perl} -MExtUtils::MakeMaker -e ' print qq|PREFIX=%{buildroot}%{_prefix}| if \$ExtUtils::MakeMaker::VERSION =~ /5\.9[1-6]|6\.0[0-5]/ '`
|
||||
%{__make}
|
||||
%if %maketest
|
||||
%{__make} test
|
||||
%endif
|
||||
|
||||
%install
|
||||
[ "%{buildroot}" != "/" ] && rm -rf %{buildroot}
|
||||
|
||||
%{makeinstall} `%{__perl} -MExtUtils::MakeMaker -e ' print \$ExtUtils::MakeMaker::VERSION <= 6.05 ? qq|PREFIX=%{buildroot}%{_prefix}| : qq|DESTDIR=%{buildroot}| '`
|
||||
|
||||
cmd=/usr/share/spec-helper/compress_files
|
||||
[ -x $cmd ] || cmd=/usr/lib/rpm/brp-compress
|
||||
[ -x $cmd ] && $cmd
|
||||
|
||||
# SuSE Linux
|
||||
if [ -e /etc/SuSE-release -o -e /etc/UnitedLinux-release ]
|
||||
then
|
||||
%{__mkdir_p} %{buildroot}/var/adm/perl-modules
|
||||
%{__cat} `find %{buildroot} -name "perllocal.pod"` \
|
||||
| %{__sed} -e s+%{buildroot}++g \
|
||||
> %{buildroot}/var/adm/perl-modules/%{name}
|
||||
fi
|
||||
|
||||
# remove special files
|
||||
find %{buildroot} -name "perllocal.pod" \
|
||||
-o -name ".packlist" \
|
||||
-o -name "*.bs" \
|
||||
|xargs -i rm -f {}
|
||||
|
||||
# no empty directories
|
||||
find %{buildroot}%{_prefix} \
|
||||
-type d -depth \
|
||||
-exec rmdir {} \; 2>/dev/null
|
||||
|
||||
%{__perl} -MFile::Find -le '
|
||||
find({ wanted => \&wanted, no_chdir => 1}, "%{buildroot}");
|
||||
print "%doc Changes README";
|
||||
for my $x (sort @dirs, @files) {
|
||||
push @ret, $x unless indirs($x);
|
||||
}
|
||||
print join "\n", sort @ret;
|
||||
|
||||
sub wanted {
|
||||
return if /auto$/;
|
||||
|
||||
local $_ = $File::Find::name;
|
||||
my $f = $_; s|^\Q%{buildroot}\E||;
|
||||
return unless length;
|
||||
return $files[@files] = $_ if -f $f;
|
||||
|
||||
$d = $_;
|
||||
/\Q$d\E/ && return for reverse sort @INC;
|
||||
$d =~ /\Q$_\E/ && return
|
||||
for qw|/etc %_prefix/man %_prefix/bin %_prefix/share|;
|
||||
|
||||
$dirs[@dirs] = $_;
|
||||
}
|
||||
|
||||
sub indirs {
|
||||
my $x = shift;
|
||||
$x =~ /^\Q$_\E\// && $x ne $_ && return 1 for @dirs;
|
||||
}
|
||||
' > %filelist
|
||||
|
||||
[ -z %filelist ] && {
|
||||
echo "ERROR: empty %files listing"
|
||||
exit -1
|
||||
}
|
||||
|
||||
%clean
|
||||
[ "%{buildroot}" != "/" ] && rm -rf %{buildroot}
|
||||
|
||||
%files -f %filelist
|
||||
%defattr(-,root,root)
|
||||
|
||||
%changelog
|
||||
* Thu Apr 1 2010 a@localhost.localdomain
|
||||
- Initial build.
|
6375
plugin/handler_socket/perl-Net-HandlerSocket/ppport.h
Normal file
6375
plugin/handler_socket/perl-Net-HandlerSocket/ppport.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
||||
# Before `make install' is performed this script should be runnable with
|
||||
# `make test'. After `make install' it should work as `perl HandlerSocket.t'
|
||||
|
||||
#########################
|
||||
|
||||
# change 'tests => 1' to 'tests => last_test_to_print';
|
||||
|
||||
use Test::More tests => 1;
|
||||
BEGIN { use_ok('Net::HandlerSocket') };
|
||||
|
||||
#########################
|
||||
|
||||
# Insert your test code below, the Test::More module is use()ed here so read
|
||||
# its man page ( perldoc Test::More ) for help writing this test script.
|
||||
|
19
plugin/handler_socket/plug.in
Normal file
19
plugin/handler_socket/plug.in
Normal file
@ -0,0 +1,19 @@
|
||||
MYSQL_PLUGIN(handlersocket, [HandlerSocket], [HandlerSocket], [max])
|
||||
MYSQL_PLUGIN_DYNAMIC(handlersocket, handlersocket.la)
|
||||
MYSQL_PLUGIN_ACTIONS(handlersocket,
|
||||
[
|
||||
ac_mysql_source_dir='$(top_srcdir)'
|
||||
MYSQL_INC="-I$ac_mysql_source_dir/sql"
|
||||
MYSQL_INC="$MYSQL_INC -I$ac_mysql_source_dir/include"
|
||||
MYSQL_INC="$MYSQL_INC -I$ac_mysql_source_dir/regex"
|
||||
MYSQL_INC="$MYSQL_INC -I$ac_mysql_source_dir"
|
||||
MYSQL_LIB='-L$(top_builddir)/libservices -lmysqlservices'
|
||||
PLUGIN_DIR='$(pkglibdir)/plugin'
|
||||
HANDLERSOCKET_SUBDIRS="libhsclient handlersocket client"
|
||||
|
||||
AC_SUBST(MYSQL_INC)
|
||||
AC_SUBST(MYSQL_CFLAGS)
|
||||
AC_SUBST(MYSQL_LIB)
|
||||
AC_SUBST(PLUGIN_DIR)
|
||||
AC_SUBST(HANDLERSOCKET_SUBDIRS)
|
||||
])
|
4
plugin/handler_socket/regtest/common/binary_my.cnf
Normal file
4
plugin/handler_socket/regtest/common/binary_my.cnf
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
[perl]
|
||||
default-character-set-name = binary
|
||||
|
29
plugin/handler_socket/regtest/common/compat.sh
Normal file
29
plugin/handler_socket/regtest/common/compat.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "`uname -o`" = "Cygwin" ]; then
|
||||
export DIFF='diff --ignore-space --strip-trailing-cr'
|
||||
elif [ "`uname`" = "Darwin" ]; then
|
||||
export DIFF='diff'
|
||||
else
|
||||
export DIFF='diff --ignore-space --strip-trailing-cr'
|
||||
fi
|
||||
|
||||
compile_c() {
|
||||
if [ "`uname -o`" = "Cygwin" ]; then
|
||||
cl /W3 /I../.. /EHsc /FD /MD "$1" /link /DLL "/OUT:$2.dll" \
|
||||
../../libase.lib 2> cl.log
|
||||
else
|
||||
$CXX -I../.. -O3 -g -Wall -fPIC -shared "$1" -o "$2.so"
|
||||
fi
|
||||
}
|
||||
|
||||
compile_j() {
|
||||
if [ "`uname -o`" = "Cygwin" ]; then
|
||||
jdk="`echo /cygdrive/c/Program\ Files/Java/jdk* | head -1`"
|
||||
else
|
||||
jdk="$SUNJDK"
|
||||
fi
|
||||
"$jdk/bin/javac" -g "$1"/*.java
|
||||
"$jdk/bin/jar" -cf "$1.jar" "$1"/*.class
|
||||
}
|
||||
|
62
plugin/handler_socket/regtest/common/hstest.pm
Normal file
62
plugin/handler_socket/regtest/common/hstest.pm
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
package hstest;
|
||||
|
||||
use DBI;
|
||||
use Net::HandlerSocket;
|
||||
|
||||
our %conf = ();
|
||||
|
||||
sub get_conf_env {
|
||||
my ($key, $defval) = @_;
|
||||
return $ENV{$key} || $defval;
|
||||
}
|
||||
|
||||
sub init_conf {
|
||||
$conf{host} = get_conf_env("MYHOST", "localhost");
|
||||
$conf{myport} = get_conf_env("MYPORT", 3306);
|
||||
$conf{dbname} = get_conf_env("MYDBNAME", "hstestdb");
|
||||
$conf{ssps} = get_conf_env("MYSSPS");
|
||||
$conf{user} = get_conf_env("MYSQLUSER", "root");
|
||||
$conf{pass} = get_conf_env("MYSQLPASS", "");
|
||||
$conf{hsport} = get_conf_env("HSPORT", 9998);
|
||||
}
|
||||
|
||||
sub get_dbi_connection {
|
||||
my ($dbname, $host, $myport, $ssps, $user, $pass)
|
||||
= ($conf{dbname}, $conf{host}, $conf{myport}, $conf{ssps},
|
||||
$conf{user}, $conf{pass});
|
||||
my $mycnf = "binary_my.cnf";
|
||||
my $dsn = "DBI:mysql:database=;host=$host;port=$myport"
|
||||
. ";mysql_server_prepare=$ssps"
|
||||
. ";mysql_read_default_group=perl"
|
||||
. ";mysql_read_default_file=../common/$mycnf";
|
||||
my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1 });
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
sub init_testdb {
|
||||
my $charset = $_[0] || "binary";
|
||||
my $dbh = get_dbi_connection();
|
||||
my $dbname = $conf{dbname};
|
||||
$dbh->do("drop database if exists $dbname");
|
||||
$dbh->do("create database $dbname default character set $charset");
|
||||
$dbh->do("use $dbname");
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
sub get_hs_connection {
|
||||
my ($host, $port) = @_;
|
||||
$host ||= $conf{host};
|
||||
$port ||= $conf{hsport};
|
||||
my $hsargs = { 'host' => $host, 'port' => $port };
|
||||
my $conn = new Net::HandlerSocket($hsargs);
|
||||
return $conn;
|
||||
}
|
||||
|
||||
|
||||
init_conf();
|
||||
|
||||
1;
|
||||
|
27
plugin/handler_socket/regtest/test_01_lib/run.sh
Executable file
27
plugin/handler_socket/regtest/test_01_lib/run.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13";
|
||||
|
||||
source ../common/compat.sh
|
||||
|
||||
for i in $TESTS; do
|
||||
perl "test$i.pl" > test$i.log 2> test$i.log2
|
||||
done
|
||||
for i in $TESTS; do
|
||||
if ! $DIFF -u test$i.log test$i.expected; then
|
||||
echo "test$i failed";
|
||||
exit 1
|
||||
fi
|
||||
if [ -f "test$i.expect2" ]; then
|
||||
lines="`wc -l < test$i.expect2`"
|
||||
head -$lines test$i.log2 > test$i.log2h
|
||||
if ! $DIFF -u test$i.log2h test$i.expect2 && \
|
||||
! $DIFF -u test$i.log2h test$i.expect2ef; then
|
||||
echo "test$i failed";
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo "OK."
|
||||
exit 0
|
||||
|
100
plugin/handler_socket/regtest/test_01_lib/test01.expected
Normal file
100
plugin/handler_socket/regtest/test_01_lib/test01.expected
Normal file
@ -0,0 +1,100 @@
|
||||
k0 v1020
|
||||
k1 v6351
|
||||
k10 v70410
|
||||
k11 v75111
|
||||
k12 v36712
|
||||
k13 v40013
|
||||
k14 v39714
|
||||
k15 v17015
|
||||
k16 v71916
|
||||
k17 v73417
|
||||
k18 v58718
|
||||
k19 v49419
|
||||
k2 v8032
|
||||
k20 v52320
|
||||
k21 v95421
|
||||
k22 v43322
|
||||
k23 v82023
|
||||
k24 v28324
|
||||
k25 v83725
|
||||
k26 v20526
|
||||
k27 v41527
|
||||
k28 v54528
|
||||
k29 v58329
|
||||
k3 v9253
|
||||
k30 v5230
|
||||
k31 v32331
|
||||
k32 v61432
|
||||
k33 v67933
|
||||
k34 v80534
|
||||
k35 v45135
|
||||
k36 v11536
|
||||
k37 v26937
|
||||
k38 v21838
|
||||
k39 v61739
|
||||
k4 v7754
|
||||
k40 v87840
|
||||
k41 v34541
|
||||
k42 v51242
|
||||
k43 v96943
|
||||
k44 v40844
|
||||
k45 v29145
|
||||
k46 v85846
|
||||
k47 v95347
|
||||
k48 v71048
|
||||
k49 v14249
|
||||
k5 v5375
|
||||
k50 v68250
|
||||
k51 v93451
|
||||
k52 v62152
|
||||
k53 v96553
|
||||
k54 v57454
|
||||
k55 v20455
|
||||
k56 v29856
|
||||
k57 v13457
|
||||
k58 v98358
|
||||
k59 v44459
|
||||
k6 v5926
|
||||
k60 v14460
|
||||
k61 v15261
|
||||
k62 v18762
|
||||
k63 v21563
|
||||
k64 v864
|
||||
k65 v69765
|
||||
k66 v65166
|
||||
k67 v28067
|
||||
k68 v70168
|
||||
k69 v53769
|
||||
k7 v4147
|
||||
k70 v41370
|
||||
k71 v6971
|
||||
k72 v8672
|
||||
k73 v82273
|
||||
k74 v67074
|
||||
k75 v37075
|
||||
k76 v80676
|
||||
k77 v68877
|
||||
k78 v2678
|
||||
k79 v6679
|
||||
k8 v5908
|
||||
k80 v80280
|
||||
k81 v17181
|
||||
k82 v55782
|
||||
k83 v84783
|
||||
k84 v77784
|
||||
k85 v73085
|
||||
k86 v98786
|
||||
k87 v11587
|
||||
k88 v64688
|
||||
k89 v49689
|
||||
k9 v3029
|
||||
k90 v12090
|
||||
k91 v68491
|
||||
k92 v37492
|
||||
k93 v6593
|
||||
k94 v37094
|
||||
k95 v17495
|
||||
k96 v82896
|
||||
k97 v86797
|
||||
k98 v75998
|
||||
k99 v70399
|
38
plugin/handler_socket/regtest/test_01_lib/test01.pl
Normal file
38
plugin/handler_socket/regtest/test_01_lib/test01.pl
Normal file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for libmysql
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 100;
|
||||
$dbh->do(
|
||||
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
|
||||
"engine = innodb");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "k" . $i;
|
||||
my $v = "v" . int(rand(1000)) . $i;
|
||||
$sth->execute($k, $v);
|
||||
$valmap{$k} = $v;
|
||||
}
|
||||
|
||||
my $aref = $dbh->selectall_arrayref("select k,v from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v) = @$row;
|
||||
print "$k $v\n";
|
||||
}
|
||||
|
100
plugin/handler_socket/regtest/test_01_lib/test02.expected
Normal file
100
plugin/handler_socket/regtest/test_01_lib/test02.expected
Normal file
@ -0,0 +1,100 @@
|
||||
k0 v1020
|
||||
k1 v6351
|
||||
k10 v70410
|
||||
k11 v75111
|
||||
k12 v36712
|
||||
k13 v40013
|
||||
k14 v39714
|
||||
k15 v17015
|
||||
k16 v71916
|
||||
k17 v73417
|
||||
k18 v58718
|
||||
k19 v49419
|
||||
k2 v8032
|
||||
k20 v52320
|
||||
k21 v95421
|
||||
k22 v43322
|
||||
k23 v82023
|
||||
k24 v28324
|
||||
k25 v83725
|
||||
k26 v20526
|
||||
k27 v41527
|
||||
k28 v54528
|
||||
k29 v58329
|
||||
k3 v9253
|
||||
k30 v5230
|
||||
k31 v32331
|
||||
k32 v61432
|
||||
k33 v67933
|
||||
k34 v80534
|
||||
k35 v45135
|
||||
k36 v11536
|
||||
k37 v26937
|
||||
k38 v21838
|
||||
k39 v61739
|
||||
k4 v7754
|
||||
k40 v87840
|
||||
k41 v34541
|
||||
k42 v51242
|
||||
k43 v96943
|
||||
k44 v40844
|
||||
k45 v29145
|
||||
k46 v85846
|
||||
k47 v95347
|
||||
k48 v71048
|
||||
k49 v14249
|
||||
k5 v5375
|
||||
k50 v68250
|
||||
k51 v93451
|
||||
k52 v62152
|
||||
k53 v96553
|
||||
k54 v57454
|
||||
k55 v20455
|
||||
k56 v29856
|
||||
k57 v13457
|
||||
k58 v98358
|
||||
k59 v44459
|
||||
k6 v5926
|
||||
k60 v14460
|
||||
k61 v15261
|
||||
k62 v18762
|
||||
k63 v21563
|
||||
k64 v864
|
||||
k65 v69765
|
||||
k66 v65166
|
||||
k67 v28067
|
||||
k68 v70168
|
||||
k69 v53769
|
||||
k7 v4147
|
||||
k70 v41370
|
||||
k71 v6971
|
||||
k72 v8672
|
||||
k73 v82273
|
||||
k74 v67074
|
||||
k75 v37075
|
||||
k76 v80676
|
||||
k77 v68877
|
||||
k78 v2678
|
||||
k79 v6679
|
||||
k8 v5908
|
||||
k80 v80280
|
||||
k81 v17181
|
||||
k82 v55782
|
||||
k83 v84783
|
||||
k84 v77784
|
||||
k85 v73085
|
||||
k86 v98786
|
||||
k87 v11587
|
||||
k88 v64688
|
||||
k89 v49689
|
||||
k9 v3029
|
||||
k90 v12090
|
||||
k91 v68491
|
||||
k92 v37492
|
||||
k93 v6593
|
||||
k94 v37094
|
||||
k95 v17495
|
||||
k96 v82896
|
||||
k97 v86797
|
||||
k98 v75998
|
||||
k99 v70399
|
49
plugin/handler_socket/regtest/test_01_lib/test02.pl
Normal file
49
plugin/handler_socket/regtest/test_01_lib/test02.pl
Normal file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for '>='
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 100;
|
||||
$dbh->do(
|
||||
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
|
||||
"engine = innodb");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "k" . $i;
|
||||
my $v = "v" . int(rand(1000)) . $i;
|
||||
$sth->execute($k, $v);
|
||||
$valmap{$k} = $v;
|
||||
}
|
||||
|
||||
my $hs = hstest::get_hs_connection();
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v');
|
||||
my $r = $hs->execute_single(1, '>=', [ '' ], 10000, 0);
|
||||
shift(@$r);
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = $r->[$i * 2];
|
||||
my $v = $r->[$i * 2 + 1];
|
||||
print "$k $v\n";
|
||||
}
|
||||
|
||||
my $aref = $dbh->selectall_arrayref("select k,v from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v) = @$row;
|
||||
#print "$k $v\n";
|
||||
}
|
||||
|
771
plugin/handler_socket/regtest/test_01_lib/test03.expected
Normal file
771
plugin/handler_socket/regtest/test_01_lib/test03.expected
Normal file
@ -0,0 +1,771 @@
|
||||
WR
|
||||
0 0
|
||||
1 1
|
||||
2 2
|
||||
3 3
|
||||
4 4
|
||||
5 5
|
||||
6 6
|
||||
7 7
|
||||
8 8
|
||||
9 9
|
||||
10 10
|
||||
11 11
|
||||
12 12
|
||||
13 13
|
||||
14 14
|
||||
15 15
|
||||
16 16
|
||||
17 17
|
||||
18 18
|
||||
19 19
|
||||
20 20
|
||||
21 21
|
||||
22 22
|
||||
23 23
|
||||
24 24
|
||||
25 25
|
||||
26 26
|
||||
27 27
|
||||
28 28
|
||||
29 29
|
||||
30 30
|
||||
31 31
|
||||
32 32
|
||||
33 33
|
||||
34 34
|
||||
35 35
|
||||
36 36
|
||||
37 37
|
||||
38 38
|
||||
39 39
|
||||
40 40
|
||||
41 41
|
||||
42 42
|
||||
43 43
|
||||
44 44
|
||||
45 45
|
||||
46 46
|
||||
47 47
|
||||
48 48
|
||||
49 49
|
||||
50 50
|
||||
51 51
|
||||
52 52
|
||||
53 53
|
||||
54 54
|
||||
55 55
|
||||
56 56
|
||||
57 57
|
||||
58 58
|
||||
59 59
|
||||
60 60
|
||||
61 61
|
||||
62 62
|
||||
63 63
|
||||
64 64
|
||||
65 65
|
||||
66 66
|
||||
67 67
|
||||
68 68
|
||||
69 69
|
||||
70 70
|
||||
71 71
|
||||
72 72
|
||||
73 73
|
||||
74 74
|
||||
75 75
|
||||
76 76
|
||||
77 77
|
||||
78 78
|
||||
79 79
|
||||
80 80
|
||||
81 81
|
||||
82 82
|
||||
83 83
|
||||
84 84
|
||||
85 85
|
||||
86 86
|
||||
87 87
|
||||
88 88
|
||||
89 89
|
||||
90 90
|
||||
91 91
|
||||
92 92
|
||||
93 93
|
||||
94 94
|
||||
95 95
|
||||
96 96
|
||||
97 97
|
||||
98 98
|
||||
99 99
|
||||
100 100
|
||||
101 101
|
||||
102 102
|
||||
103 103
|
||||
104 104
|
||||
105 105
|
||||
106 106
|
||||
107 107
|
||||
108 108
|
||||
109 109
|
||||
110 110
|
||||
111 111
|
||||
112 112
|
||||
113 113
|
||||
114 114
|
||||
115 115
|
||||
116 116
|
||||
117 117
|
||||
118 118
|
||||
119 119
|
||||
120 120
|
||||
121 121
|
||||
122 122
|
||||
123 123
|
||||
124 124
|
||||
125 125
|
||||
126 126
|
||||
127 127
|
||||
128 128
|
||||
129 129
|
||||
130 130
|
||||
131 131
|
||||
132 132
|
||||
133 133
|
||||
134 134
|
||||
135 135
|
||||
136 136
|
||||
137 137
|
||||
138 138
|
||||
139 139
|
||||
140 140
|
||||
141 141
|
||||
142 142
|
||||
143 143
|
||||
144 144
|
||||
145 145
|
||||
146 146
|
||||
147 147
|
||||
148 148
|
||||
149 149
|
||||
150 150
|
||||
151 151
|
||||
152 152
|
||||
153 153
|
||||
154 154
|
||||
155 155
|
||||
156 156
|
||||
157 157
|
||||
158 158
|
||||
159 159
|
||||
160 160
|
||||
161 161
|
||||
162 162
|
||||
163 163
|
||||
164 164
|
||||
165 165
|
||||
166 166
|
||||
167 167
|
||||
168 168
|
||||
169 169
|
||||
170 170
|
||||
171 171
|
||||
172 172
|
||||
173 173
|
||||
174 174
|
||||
175 175
|
||||
176 176
|
||||
177 177
|
||||
178 178
|
||||
179 179
|
||||
180 180
|
||||
181 181
|
||||
182 182
|
||||
183 183
|
||||
184 184
|
||||
185 185
|
||||
186 186
|
||||
187 187
|
||||
188 188
|
||||
189 189
|
||||
190 190
|
||||
191 191
|
||||
192 192
|
||||
193 193
|
||||
194 194
|
||||
195 195
|
||||
196 196
|
||||
197 197
|
||||
198 198
|
||||
199 199
|
||||
200 200
|
||||
201 201
|
||||
202 202
|
||||
203 203
|
||||
204 204
|
||||
205 205
|
||||
206 206
|
||||
207 207
|
||||
208 208
|
||||
209 209
|
||||
210 210
|
||||
211 211
|
||||
212 212
|
||||
213 213
|
||||
214 214
|
||||
215 215
|
||||
216 216
|
||||
217 217
|
||||
218 218
|
||||
219 219
|
||||
220 220
|
||||
221 221
|
||||
222 222
|
||||
223 223
|
||||
224 224
|
||||
225 225
|
||||
226 226
|
||||
227 227
|
||||
228 228
|
||||
229 229
|
||||
230 230
|
||||
231 231
|
||||
232 232
|
||||
233 233
|
||||
234 234
|
||||
235 235
|
||||
236 236
|
||||
237 237
|
||||
238 238
|
||||
239 239
|
||||
240 240
|
||||
241 241
|
||||
242 242
|
||||
243 243
|
||||
244 244
|
||||
245 245
|
||||
246 246
|
||||
247 247
|
||||
248 248
|
||||
249 249
|
||||
250 250
|
||||
251 251
|
||||
252 252
|
||||
253 253
|
||||
254 254
|
||||
255 255
|
||||
HS
|
||||
0 0
|
||||
1 1
|
||||
10 10
|
||||
100 100
|
||||
101 101
|
||||
102 102
|
||||
103 103
|
||||
104 104
|
||||
105 105
|
||||
106 106
|
||||
107 107
|
||||
108 108
|
||||
109 109
|
||||
11 11
|
||||
110 110
|
||||
111 111
|
||||
112 112
|
||||
113 113
|
||||
114 114
|
||||
115 115
|
||||
116 116
|
||||
117 117
|
||||
118 118
|
||||
119 119
|
||||
12 12
|
||||
120 120
|
||||
121 121
|
||||
122 122
|
||||
123 123
|
||||
124 124
|
||||
125 125
|
||||
126 126
|
||||
127 127
|
||||
128 128
|
||||
129 129
|
||||
13 13
|
||||
130 130
|
||||
131 131
|
||||
132 132
|
||||
133 133
|
||||
134 134
|
||||
135 135
|
||||
136 136
|
||||
137 137
|
||||
138 138
|
||||
139 139
|
||||
14 14
|
||||
140 140
|
||||
141 141
|
||||
142 142
|
||||
143 143
|
||||
144 144
|
||||
145 145
|
||||
146 146
|
||||
147 147
|
||||
148 148
|
||||
149 149
|
||||
15 15
|
||||
150 150
|
||||
151 151
|
||||
152 152
|
||||
153 153
|
||||
154 154
|
||||
155 155
|
||||
156 156
|
||||
157 157
|
||||
158 158
|
||||
159 159
|
||||
16 16
|
||||
160 160
|
||||
161 161
|
||||
162 162
|
||||
163 163
|
||||
164 164
|
||||
165 165
|
||||
166 166
|
||||
167 167
|
||||
168 168
|
||||
169 169
|
||||
17 17
|
||||
170 170
|
||||
171 171
|
||||
172 172
|
||||
173 173
|
||||
174 174
|
||||
175 175
|
||||
176 176
|
||||
177 177
|
||||
178 178
|
||||
179 179
|
||||
18 18
|
||||
180 180
|
||||
181 181
|
||||
182 182
|
||||
183 183
|
||||
184 184
|
||||
185 185
|
||||
186 186
|
||||
187 187
|
||||
188 188
|
||||
189 189
|
||||
19 19
|
||||
190 190
|
||||
191 191
|
||||
192 192
|
||||
193 193
|
||||
194 194
|
||||
195 195
|
||||
196 196
|
||||
197 197
|
||||
198 198
|
||||
199 199
|
||||
2 2
|
||||
20 20
|
||||
200 200
|
||||
201 201
|
||||
202 202
|
||||
203 203
|
||||
204 204
|
||||
205 205
|
||||
206 206
|
||||
207 207
|
||||
208 208
|
||||
209 209
|
||||
21 21
|
||||
210 210
|
||||
211 211
|
||||
212 212
|
||||
213 213
|
||||
214 214
|
||||
215 215
|
||||
216 216
|
||||
217 217
|
||||
218 218
|
||||
219 219
|
||||
22 22
|
||||
220 220
|
||||
221 221
|
||||
222 222
|
||||
223 223
|
||||
224 224
|
||||
225 225
|
||||
226 226
|
||||
227 227
|
||||
228 228
|
||||
229 229
|
||||
23 23
|
||||
230 230
|
||||
231 231
|
||||
232 232
|
||||
233 233
|
||||
234 234
|
||||
235 235
|
||||
236 236
|
||||
237 237
|
||||
238 238
|
||||
239 239
|
||||
24 24
|
||||
240 240
|
||||
241 241
|
||||
242 242
|
||||
243 243
|
||||
244 244
|
||||
245 245
|
||||
246 246
|
||||
247 247
|
||||
248 248
|
||||
249 249
|
||||
25 25
|
||||
250 250
|
||||
251 251
|
||||
252 252
|
||||
253 253
|
||||
254 254
|
||||
255 255
|
||||
26 26
|
||||
27 27
|
||||
28 28
|
||||
29 29
|
||||
3 3
|
||||
30 30
|
||||
31 31
|
||||
32 32
|
||||
33 33
|
||||
34 34
|
||||
35 35
|
||||
36 36
|
||||
37 37
|
||||
38 38
|
||||
39 39
|
||||
4 4
|
||||
40 40
|
||||
41 41
|
||||
42 42
|
||||
43 43
|
||||
44 44
|
||||
45 45
|
||||
46 46
|
||||
47 47
|
||||
48 48
|
||||
49 49
|
||||
5 5
|
||||
50 50
|
||||
51 51
|
||||
52 52
|
||||
53 53
|
||||
54 54
|
||||
55 55
|
||||
56 56
|
||||
57 57
|
||||
58 58
|
||||
59 59
|
||||
6 6
|
||||
60 60
|
||||
61 61
|
||||
62 62
|
||||
63 63
|
||||
64 64
|
||||
65 65
|
||||
66 66
|
||||
67 67
|
||||
68 68
|
||||
69 69
|
||||
7 7
|
||||
70 70
|
||||
71 71
|
||||
72 72
|
||||
73 73
|
||||
74 74
|
||||
75 75
|
||||
76 76
|
||||
77 77
|
||||
78 78
|
||||
79 79
|
||||
8 8
|
||||
80 80
|
||||
81 81
|
||||
82 82
|
||||
83 83
|
||||
84 84
|
||||
85 85
|
||||
86 86
|
||||
87 87
|
||||
88 88
|
||||
89 89
|
||||
9 9
|
||||
90 90
|
||||
91 91
|
||||
92 92
|
||||
93 93
|
||||
94 94
|
||||
95 95
|
||||
96 96
|
||||
97 97
|
||||
98 98
|
||||
99 99
|
||||
MY
|
||||
0 0
|
||||
1 1
|
||||
10 10
|
||||
100 100
|
||||
101 101
|
||||
102 102
|
||||
103 103
|
||||
104 104
|
||||
105 105
|
||||
106 106
|
||||
107 107
|
||||
108 108
|
||||
109 109
|
||||
11 11
|
||||
110 110
|
||||
111 111
|
||||
112 112
|
||||
113 113
|
||||
114 114
|
||||
115 115
|
||||
116 116
|
||||
117 117
|
||||
118 118
|
||||
119 119
|
||||
12 12
|
||||
120 120
|
||||
121 121
|
||||
122 122
|
||||
123 123
|
||||
124 124
|
||||
125 125
|
||||
126 126
|
||||
127 127
|
||||
128 128
|
||||
129 129
|
||||
13 13
|
||||
130 130
|
||||
131 131
|
||||
132 132
|
||||
133 133
|
||||
134 134
|
||||
135 135
|
||||
136 136
|
||||
137 137
|
||||
138 138
|
||||
139 139
|
||||
14 14
|
||||
140 140
|
||||
141 141
|
||||
142 142
|
||||
143 143
|
||||
144 144
|
||||
145 145
|
||||
146 146
|
||||
147 147
|
||||
148 148
|
||||
149 149
|
||||
15 15
|
||||
150 150
|
||||
151 151
|
||||
152 152
|
||||
153 153
|
||||
154 154
|
||||
155 155
|
||||
156 156
|
||||
157 157
|
||||
158 158
|
||||
159 159
|
||||
16 16
|
||||
160 160
|
||||
161 161
|
||||
162 162
|
||||
163 163
|
||||
164 164
|
||||
165 165
|
||||
166 166
|
||||
167 167
|
||||
168 168
|
||||
169 169
|
||||
17 17
|
||||
170 170
|
||||
171 171
|
||||
172 172
|
||||
173 173
|
||||
174 174
|
||||
175 175
|
||||
176 176
|
||||
177 177
|
||||
178 178
|
||||
179 179
|
||||
18 18
|
||||
180 180
|
||||
181 181
|
||||
182 182
|
||||
183 183
|
||||
184 184
|
||||
185 185
|
||||
186 186
|
||||
187 187
|
||||
188 188
|
||||
189 189
|
||||
19 19
|
||||
190 190
|
||||
191 191
|
||||
192 192
|
||||
193 193
|
||||
194 194
|
||||
195 195
|
||||
196 196
|
||||
197 197
|
||||
198 198
|
||||
199 199
|
||||
2 2
|
||||
20 20
|
||||
200 200
|
||||
201 201
|
||||
202 202
|
||||
203 203
|
||||
204 204
|
||||
205 205
|
||||
206 206
|
||||
207 207
|
||||
208 208
|
||||
209 209
|
||||
21 21
|
||||
210 210
|
||||
211 211
|
||||
212 212
|
||||
213 213
|
||||
214 214
|
||||
215 215
|
||||
216 216
|
||||
217 217
|
||||
218 218
|
||||
219 219
|
||||
22 22
|
||||
220 220
|
||||
221 221
|
||||
222 222
|
||||
223 223
|
||||
224 224
|
||||
225 225
|
||||
226 226
|
||||
227 227
|
||||
228 228
|
||||
229 229
|
||||
23 23
|
||||
230 230
|
||||
231 231
|
||||
232 232
|
||||
233 233
|
||||
234 234
|
||||
235 235
|
||||
236 236
|
||||
237 237
|
||||
238 238
|
||||
239 239
|
||||
24 24
|
||||
240 240
|
||||
241 241
|
||||
242 242
|
||||
243 243
|
||||
244 244
|
||||
245 245
|
||||
246 246
|
||||
247 247
|
||||
248 248
|
||||
249 249
|
||||
25 25
|
||||
250 250
|
||||
251 251
|
||||
252 252
|
||||
253 253
|
||||
254 254
|
||||
255 255
|
||||
26 26
|
||||
27 27
|
||||
28 28
|
||||
29 29
|
||||
3 3
|
||||
30 30
|
||||
31 31
|
||||
32 32
|
||||
33 33
|
||||
34 34
|
||||
35 35
|
||||
36 36
|
||||
37 37
|
||||
38 38
|
||||
39 39
|
||||
4 4
|
||||
40 40
|
||||
41 41
|
||||
42 42
|
||||
43 43
|
||||
44 44
|
||||
45 45
|
||||
46 46
|
||||
47 47
|
||||
48 48
|
||||
49 49
|
||||
5 5
|
||||
50 50
|
||||
51 51
|
||||
52 52
|
||||
53 53
|
||||
54 54
|
||||
55 55
|
||||
56 56
|
||||
57 57
|
||||
58 58
|
||||
59 59
|
||||
6 6
|
||||
60 60
|
||||
61 61
|
||||
62 62
|
||||
63 63
|
||||
64 64
|
||||
65 65
|
||||
66 66
|
||||
67 67
|
||||
68 68
|
||||
69 69
|
||||
7 7
|
||||
70 70
|
||||
71 71
|
||||
72 72
|
||||
73 73
|
||||
74 74
|
||||
75 75
|
||||
76 76
|
||||
77 77
|
||||
78 78
|
||||
79 79
|
||||
8 8
|
||||
80 80
|
||||
81 81
|
||||
82 82
|
||||
83 83
|
||||
84 84
|
||||
85 85
|
||||
86 86
|
||||
87 87
|
||||
88 88
|
||||
89 89
|
||||
9 9
|
||||
90 90
|
||||
91 91
|
||||
92 92
|
||||
93 93
|
||||
94 94
|
||||
95 95
|
||||
96 96
|
||||
97 97
|
||||
98 98
|
||||
99 99
|
61
plugin/handler_socket/regtest/test_01_lib/test03.pl
Normal file
61
plugin/handler_socket/regtest/test_01_lib/test03.pl
Normal file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for binary cleanness (#1)
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 256;
|
||||
$dbh->do(
|
||||
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
|
||||
"engine = innodb default charset = binary");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
print "WR\n";
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v = pack("C", $i);
|
||||
my $vnum = unpack("C", $v);
|
||||
print "$k $vnum\n";
|
||||
$sth->execute($k, $v);
|
||||
$valmap{$k} = $v;
|
||||
}
|
||||
|
||||
my $hs = hstest::get_hs_connection();
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v');
|
||||
my $r = $hs->execute_single(1, '>=', [ '' ], 10000, 0);
|
||||
shift(@$r);
|
||||
print "HS\n";
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = $r->[$i * 2];
|
||||
my $v = $r->[$i * 2 + 1];
|
||||
my $vnum = unpack("C", $v);
|
||||
print "$k $vnum\n";
|
||||
print "MISMATCH\n" if ($k ne $vnum);
|
||||
print "LEN\n" if (length($v) != 1);
|
||||
}
|
||||
undef $hs;
|
||||
|
||||
print "MY\n";
|
||||
my $aref = $dbh->selectall_arrayref("select k,v from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v) = @$row;
|
||||
my $vnum = unpack("C", $v);
|
||||
print "$k $vnum\n";
|
||||
print "MISMATCH\n" if ($k ne $vnum);
|
||||
print "LEN\n" if (length($v) != 1);
|
||||
}
|
||||
|
BIN
plugin/handler_socket/regtest/test_01_lib/test04.expected
Normal file
BIN
plugin/handler_socket/regtest/test_01_lib/test04.expected
Normal file
Binary file not shown.
63
plugin/handler_socket/regtest/test_01_lib/test04.pl
Normal file
63
plugin/handler_socket/regtest/test_01_lib/test04.pl
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for binary cleanness (#2)
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 256;
|
||||
$dbh->do(
|
||||
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
|
||||
"engine = innodb default charset = binary");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
print "WR\n";
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v = pack("C", $i);
|
||||
my $vnum = unpack("C", $v);
|
||||
print "$k $vnum\n";
|
||||
$sth->execute($k, "a" . $v . "a");
|
||||
$valmap{$k} = $v;
|
||||
}
|
||||
|
||||
my $hs = hstest::get_hs_connection();
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v');
|
||||
my $r = $hs->execute_single(1, '>=', [ '' ], 10000, 0);
|
||||
shift(@$r);
|
||||
print "HS\n";
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = $r->[$i * 2];
|
||||
my $v = $r->[$i * 2 + 1];
|
||||
my $len = length($v);
|
||||
my $vnum = unpack("C", substr($v, 1, 1));
|
||||
print "$k $vnum $len [$v]\n";
|
||||
print "MISMATCH\n" if ($k ne $vnum);
|
||||
print "LEN\n" if $len != 3;
|
||||
}
|
||||
undef $hs;
|
||||
|
||||
print "MY\n";
|
||||
my $aref = $dbh->selectall_arrayref("select k,v from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v) = @$row;
|
||||
my $len = length($v);
|
||||
my $vnum = unpack("C", substr($v, 1, 1));
|
||||
print "$k $vnum $len [$v]\n";
|
||||
print "MISMATCH\n" if ($k ne $vnum);
|
||||
print "LEN\n" if $len != 3;
|
||||
}
|
||||
|
771
plugin/handler_socket/regtest/test_01_lib/test05.expected
Normal file
771
plugin/handler_socket/regtest/test_01_lib/test05.expected
Normal file
@ -0,0 +1,771 @@
|
||||
WR
|
||||
0 [null]
|
||||
1 1
|
||||
2 [null]
|
||||
3 3
|
||||
4 [null]
|
||||
5 5
|
||||
6 [null]
|
||||
7 7
|
||||
8 [null]
|
||||
9 9
|
||||
10 [null]
|
||||
11 11
|
||||
12 [null]
|
||||
13 13
|
||||
14 [null]
|
||||
15 15
|
||||
16 [null]
|
||||
17 17
|
||||
18 [null]
|
||||
19 19
|
||||
20 [null]
|
||||
21 21
|
||||
22 [null]
|
||||
23 23
|
||||
24 [null]
|
||||
25 25
|
||||
26 [null]
|
||||
27 27
|
||||
28 [null]
|
||||
29 29
|
||||
30 [null]
|
||||
31 31
|
||||
32 [null]
|
||||
33 33
|
||||
34 [null]
|
||||
35 35
|
||||
36 [null]
|
||||
37 37
|
||||
38 [null]
|
||||
39 39
|
||||
40 [null]
|
||||
41 41
|
||||
42 [null]
|
||||
43 43
|
||||
44 [null]
|
||||
45 45
|
||||
46 [null]
|
||||
47 47
|
||||
48 [null]
|
||||
49 49
|
||||
50 [null]
|
||||
51 51
|
||||
52 [null]
|
||||
53 53
|
||||
54 [null]
|
||||
55 55
|
||||
56 [null]
|
||||
57 57
|
||||
58 [null]
|
||||
59 59
|
||||
60 [null]
|
||||
61 61
|
||||
62 [null]
|
||||
63 63
|
||||
64 [null]
|
||||
65 65
|
||||
66 [null]
|
||||
67 67
|
||||
68 [null]
|
||||
69 69
|
||||
70 [null]
|
||||
71 71
|
||||
72 [null]
|
||||
73 73
|
||||
74 [null]
|
||||
75 75
|
||||
76 [null]
|
||||
77 77
|
||||
78 [null]
|
||||
79 79
|
||||
80 [null]
|
||||
81 81
|
||||
82 [null]
|
||||
83 83
|
||||
84 [null]
|
||||
85 85
|
||||
86 [null]
|
||||
87 87
|
||||
88 [null]
|
||||
89 89
|
||||
90 [null]
|
||||
91 91
|
||||
92 [null]
|
||||
93 93
|
||||
94 [null]
|
||||
95 95
|
||||
96 [null]
|
||||
97 97
|
||||
98 [null]
|
||||
99 99
|
||||
100 [null]
|
||||
101 101
|
||||
102 [null]
|
||||
103 103
|
||||
104 [null]
|
||||
105 105
|
||||
106 [null]
|
||||
107 107
|
||||
108 [null]
|
||||
109 109
|
||||
110 [null]
|
||||
111 111
|
||||
112 [null]
|
||||
113 113
|
||||
114 [null]
|
||||
115 115
|
||||
116 [null]
|
||||
117 117
|
||||
118 [null]
|
||||
119 119
|
||||
120 [null]
|
||||
121 121
|
||||
122 [null]
|
||||
123 123
|
||||
124 [null]
|
||||
125 125
|
||||
126 [null]
|
||||
127 127
|
||||
128 [null]
|
||||
129 129
|
||||
130 [null]
|
||||
131 131
|
||||
132 [null]
|
||||
133 133
|
||||
134 [null]
|
||||
135 135
|
||||
136 [null]
|
||||
137 137
|
||||
138 [null]
|
||||
139 139
|
||||
140 [null]
|
||||
141 141
|
||||
142 [null]
|
||||
143 143
|
||||
144 [null]
|
||||
145 145
|
||||
146 [null]
|
||||
147 147
|
||||
148 [null]
|
||||
149 149
|
||||
150 [null]
|
||||
151 151
|
||||
152 [null]
|
||||
153 153
|
||||
154 [null]
|
||||
155 155
|
||||
156 [null]
|
||||
157 157
|
||||
158 [null]
|
||||
159 159
|
||||
160 [null]
|
||||
161 161
|
||||
162 [null]
|
||||
163 163
|
||||
164 [null]
|
||||
165 165
|
||||
166 [null]
|
||||
167 167
|
||||
168 [null]
|
||||
169 169
|
||||
170 [null]
|
||||
171 171
|
||||
172 [null]
|
||||
173 173
|
||||
174 [null]
|
||||
175 175
|
||||
176 [null]
|
||||
177 177
|
||||
178 [null]
|
||||
179 179
|
||||
180 [null]
|
||||
181 181
|
||||
182 [null]
|
||||
183 183
|
||||
184 [null]
|
||||
185 185
|
||||
186 [null]
|
||||
187 187
|
||||
188 [null]
|
||||
189 189
|
||||
190 [null]
|
||||
191 191
|
||||
192 [null]
|
||||
193 193
|
||||
194 [null]
|
||||
195 195
|
||||
196 [null]
|
||||
197 197
|
||||
198 [null]
|
||||
199 199
|
||||
200 [null]
|
||||
201 201
|
||||
202 [null]
|
||||
203 203
|
||||
204 [null]
|
||||
205 205
|
||||
206 [null]
|
||||
207 207
|
||||
208 [null]
|
||||
209 209
|
||||
210 [null]
|
||||
211 211
|
||||
212 [null]
|
||||
213 213
|
||||
214 [null]
|
||||
215 215
|
||||
216 [null]
|
||||
217 217
|
||||
218 [null]
|
||||
219 219
|
||||
220 [null]
|
||||
221 221
|
||||
222 [null]
|
||||
223 223
|
||||
224 [null]
|
||||
225 225
|
||||
226 [null]
|
||||
227 227
|
||||
228 [null]
|
||||
229 229
|
||||
230 [null]
|
||||
231 231
|
||||
232 [null]
|
||||
233 233
|
||||
234 [null]
|
||||
235 235
|
||||
236 [null]
|
||||
237 237
|
||||
238 [null]
|
||||
239 239
|
||||
240 [null]
|
||||
241 241
|
||||
242 [null]
|
||||
243 243
|
||||
244 [null]
|
||||
245 245
|
||||
246 [null]
|
||||
247 247
|
||||
248 [null]
|
||||
249 249
|
||||
250 [null]
|
||||
251 251
|
||||
252 [null]
|
||||
253 253
|
||||
254 [null]
|
||||
255 255
|
||||
HS
|
||||
0 [null]
|
||||
1 1
|
||||
10 [null]
|
||||
100 [null]
|
||||
101 101
|
||||
102 [null]
|
||||
103 103
|
||||
104 [null]
|
||||
105 105
|
||||
106 [null]
|
||||
107 107
|
||||
108 [null]
|
||||
109 109
|
||||
11 11
|
||||
110 [null]
|
||||
111 111
|
||||
112 [null]
|
||||
113 113
|
||||
114 [null]
|
||||
115 115
|
||||
116 [null]
|
||||
117 117
|
||||
118 [null]
|
||||
119 119
|
||||
12 [null]
|
||||
120 [null]
|
||||
121 121
|
||||
122 [null]
|
||||
123 123
|
||||
124 [null]
|
||||
125 125
|
||||
126 [null]
|
||||
127 127
|
||||
128 [null]
|
||||
129 129
|
||||
13 13
|
||||
130 [null]
|
||||
131 131
|
||||
132 [null]
|
||||
133 133
|
||||
134 [null]
|
||||
135 135
|
||||
136 [null]
|
||||
137 137
|
||||
138 [null]
|
||||
139 139
|
||||
14 [null]
|
||||
140 [null]
|
||||
141 141
|
||||
142 [null]
|
||||
143 143
|
||||
144 [null]
|
||||
145 145
|
||||
146 [null]
|
||||
147 147
|
||||
148 [null]
|
||||
149 149
|
||||
15 15
|
||||
150 [null]
|
||||
151 151
|
||||
152 [null]
|
||||
153 153
|
||||
154 [null]
|
||||
155 155
|
||||
156 [null]
|
||||
157 157
|
||||
158 [null]
|
||||
159 159
|
||||
16 [null]
|
||||
160 [null]
|
||||
161 161
|
||||
162 [null]
|
||||
163 163
|
||||
164 [null]
|
||||
165 165
|
||||
166 [null]
|
||||
167 167
|
||||
168 [null]
|
||||
169 169
|
||||
17 17
|
||||
170 [null]
|
||||
171 171
|
||||
172 [null]
|
||||
173 173
|
||||
174 [null]
|
||||
175 175
|
||||
176 [null]
|
||||
177 177
|
||||
178 [null]
|
||||
179 179
|
||||
18 [null]
|
||||
180 [null]
|
||||
181 181
|
||||
182 [null]
|
||||
183 183
|
||||
184 [null]
|
||||
185 185
|
||||
186 [null]
|
||||
187 187
|
||||
188 [null]
|
||||
189 189
|
||||
19 19
|
||||
190 [null]
|
||||
191 191
|
||||
192 [null]
|
||||
193 193
|
||||
194 [null]
|
||||
195 195
|
||||
196 [null]
|
||||
197 197
|
||||
198 [null]
|
||||
199 199
|
||||
2 [null]
|
||||
20 [null]
|
||||
200 [null]
|
||||
201 201
|
||||
202 [null]
|
||||
203 203
|
||||
204 [null]
|
||||
205 205
|
||||
206 [null]
|
||||
207 207
|
||||
208 [null]
|
||||
209 209
|
||||
21 21
|
||||
210 [null]
|
||||
211 211
|
||||
212 [null]
|
||||
213 213
|
||||
214 [null]
|
||||
215 215
|
||||
216 [null]
|
||||
217 217
|
||||
218 [null]
|
||||
219 219
|
||||
22 [null]
|
||||
220 [null]
|
||||
221 221
|
||||
222 [null]
|
||||
223 223
|
||||
224 [null]
|
||||
225 225
|
||||
226 [null]
|
||||
227 227
|
||||
228 [null]
|
||||
229 229
|
||||
23 23
|
||||
230 [null]
|
||||
231 231
|
||||
232 [null]
|
||||
233 233
|
||||
234 [null]
|
||||
235 235
|
||||
236 [null]
|
||||
237 237
|
||||
238 [null]
|
||||
239 239
|
||||
24 [null]
|
||||
240 [null]
|
||||
241 241
|
||||
242 [null]
|
||||
243 243
|
||||
244 [null]
|
||||
245 245
|
||||
246 [null]
|
||||
247 247
|
||||
248 [null]
|
||||
249 249
|
||||
25 25
|
||||
250 [null]
|
||||
251 251
|
||||
252 [null]
|
||||
253 253
|
||||
254 [null]
|
||||
255 255
|
||||
26 [null]
|
||||
27 27
|
||||
28 [null]
|
||||
29 29
|
||||
3 3
|
||||
30 [null]
|
||||
31 31
|
||||
32 [null]
|
||||
33 33
|
||||
34 [null]
|
||||
35 35
|
||||
36 [null]
|
||||
37 37
|
||||
38 [null]
|
||||
39 39
|
||||
4 [null]
|
||||
40 [null]
|
||||
41 41
|
||||
42 [null]
|
||||
43 43
|
||||
44 [null]
|
||||
45 45
|
||||
46 [null]
|
||||
47 47
|
||||
48 [null]
|
||||
49 49
|
||||
5 5
|
||||
50 [null]
|
||||
51 51
|
||||
52 [null]
|
||||
53 53
|
||||
54 [null]
|
||||
55 55
|
||||
56 [null]
|
||||
57 57
|
||||
58 [null]
|
||||
59 59
|
||||
6 [null]
|
||||
60 [null]
|
||||
61 61
|
||||
62 [null]
|
||||
63 63
|
||||
64 [null]
|
||||
65 65
|
||||
66 [null]
|
||||
67 67
|
||||
68 [null]
|
||||
69 69
|
||||
7 7
|
||||
70 [null]
|
||||
71 71
|
||||
72 [null]
|
||||
73 73
|
||||
74 [null]
|
||||
75 75
|
||||
76 [null]
|
||||
77 77
|
||||
78 [null]
|
||||
79 79
|
||||
8 [null]
|
||||
80 [null]
|
||||
81 81
|
||||
82 [null]
|
||||
83 83
|
||||
84 [null]
|
||||
85 85
|
||||
86 [null]
|
||||
87 87
|
||||
88 [null]
|
||||
89 89
|
||||
9 9
|
||||
90 [null]
|
||||
91 91
|
||||
92 [null]
|
||||
93 93
|
||||
94 [null]
|
||||
95 95
|
||||
96 [null]
|
||||
97 97
|
||||
98 [null]
|
||||
99 99
|
||||
MY
|
||||
0 [null]
|
||||
1 1
|
||||
10 [null]
|
||||
100 [null]
|
||||
101 101
|
||||
102 [null]
|
||||
103 103
|
||||
104 [null]
|
||||
105 105
|
||||
106 [null]
|
||||
107 107
|
||||
108 [null]
|
||||
109 109
|
||||
11 11
|
||||
110 [null]
|
||||
111 111
|
||||
112 [null]
|
||||
113 113
|
||||
114 [null]
|
||||
115 115
|
||||
116 [null]
|
||||
117 117
|
||||
118 [null]
|
||||
119 119
|
||||
12 [null]
|
||||
120 [null]
|
||||
121 121
|
||||
122 [null]
|
||||
123 123
|
||||
124 [null]
|
||||
125 125
|
||||
126 [null]
|
||||
127 127
|
||||
128 [null]
|
||||
129 129
|
||||
13 13
|
||||
130 [null]
|
||||
131 131
|
||||
132 [null]
|
||||
133 133
|
||||
134 [null]
|
||||
135 135
|
||||
136 [null]
|
||||
137 137
|
||||
138 [null]
|
||||
139 139
|
||||
14 [null]
|
||||
140 [null]
|
||||
141 141
|
||||
142 [null]
|
||||
143 143
|
||||
144 [null]
|
||||
145 145
|
||||
146 [null]
|
||||
147 147
|
||||
148 [null]
|
||||
149 149
|
||||
15 15
|
||||
150 [null]
|
||||
151 151
|
||||
152 [null]
|
||||
153 153
|
||||
154 [null]
|
||||
155 155
|
||||
156 [null]
|
||||
157 157
|
||||
158 [null]
|
||||
159 159
|
||||
16 [null]
|
||||
160 [null]
|
||||
161 161
|
||||
162 [null]
|
||||
163 163
|
||||
164 [null]
|
||||
165 165
|
||||
166 [null]
|
||||
167 167
|
||||
168 [null]
|
||||
169 169
|
||||
17 17
|
||||
170 [null]
|
||||
171 171
|
||||
172 [null]
|
||||
173 173
|
||||
174 [null]
|
||||
175 175
|
||||
176 [null]
|
||||
177 177
|
||||
178 [null]
|
||||
179 179
|
||||
18 [null]
|
||||
180 [null]
|
||||
181 181
|
||||
182 [null]
|
||||
183 183
|
||||
184 [null]
|
||||
185 185
|
||||
186 [null]
|
||||
187 187
|
||||
188 [null]
|
||||
189 189
|
||||
19 19
|
||||
190 [null]
|
||||
191 191
|
||||
192 [null]
|
||||
193 193
|
||||
194 [null]
|
||||
195 195
|
||||
196 [null]
|
||||
197 197
|
||||
198 [null]
|
||||
199 199
|
||||
2 [null]
|
||||
20 [null]
|
||||
200 [null]
|
||||
201 201
|
||||
202 [null]
|
||||
203 203
|
||||
204 [null]
|
||||
205 205
|
||||
206 [null]
|
||||
207 207
|
||||
208 [null]
|
||||
209 209
|
||||
21 21
|
||||
210 [null]
|
||||
211 211
|
||||
212 [null]
|
||||
213 213
|
||||
214 [null]
|
||||
215 215
|
||||
216 [null]
|
||||
217 217
|
||||
218 [null]
|
||||
219 219
|
||||
22 [null]
|
||||
220 [null]
|
||||
221 221
|
||||
222 [null]
|
||||
223 223
|
||||
224 [null]
|
||||
225 225
|
||||
226 [null]
|
||||
227 227
|
||||
228 [null]
|
||||
229 229
|
||||
23 23
|
||||
230 [null]
|
||||
231 231
|
||||
232 [null]
|
||||
233 233
|
||||
234 [null]
|
||||
235 235
|
||||
236 [null]
|
||||
237 237
|
||||
238 [null]
|
||||
239 239
|
||||
24 [null]
|
||||
240 [null]
|
||||
241 241
|
||||
242 [null]
|
||||
243 243
|
||||
244 [null]
|
||||
245 245
|
||||
246 [null]
|
||||
247 247
|
||||
248 [null]
|
||||
249 249
|
||||
25 25
|
||||
250 [null]
|
||||
251 251
|
||||
252 [null]
|
||||
253 253
|
||||
254 [null]
|
||||
255 255
|
||||
26 [null]
|
||||
27 27
|
||||
28 [null]
|
||||
29 29
|
||||
3 3
|
||||
30 [null]
|
||||
31 31
|
||||
32 [null]
|
||||
33 33
|
||||
34 [null]
|
||||
35 35
|
||||
36 [null]
|
||||
37 37
|
||||
38 [null]
|
||||
39 39
|
||||
4 [null]
|
||||
40 [null]
|
||||
41 41
|
||||
42 [null]
|
||||
43 43
|
||||
44 [null]
|
||||
45 45
|
||||
46 [null]
|
||||
47 47
|
||||
48 [null]
|
||||
49 49
|
||||
5 5
|
||||
50 [null]
|
||||
51 51
|
||||
52 [null]
|
||||
53 53
|
||||
54 [null]
|
||||
55 55
|
||||
56 [null]
|
||||
57 57
|
||||
58 [null]
|
||||
59 59
|
||||
6 [null]
|
||||
60 [null]
|
||||
61 61
|
||||
62 [null]
|
||||
63 63
|
||||
64 [null]
|
||||
65 65
|
||||
66 [null]
|
||||
67 67
|
||||
68 [null]
|
||||
69 69
|
||||
7 7
|
||||
70 [null]
|
||||
71 71
|
||||
72 [null]
|
||||
73 73
|
||||
74 [null]
|
||||
75 75
|
||||
76 [null]
|
||||
77 77
|
||||
78 [null]
|
||||
79 79
|
||||
8 [null]
|
||||
80 [null]
|
||||
81 81
|
||||
82 [null]
|
||||
83 83
|
||||
84 [null]
|
||||
85 85
|
||||
86 [null]
|
||||
87 87
|
||||
88 [null]
|
||||
89 89
|
||||
9 9
|
||||
90 [null]
|
||||
91 91
|
||||
92 [null]
|
||||
93 93
|
||||
94 [null]
|
||||
95 95
|
||||
96 [null]
|
||||
97 97
|
||||
98 [null]
|
||||
99 99
|
59
plugin/handler_socket/regtest/test_01_lib/test05.pl
Normal file
59
plugin/handler_socket/regtest/test_01_lib/test05.pl
Normal file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for binary cleanness (#3)
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 256;
|
||||
$dbh->do(
|
||||
"create table $table (k varchar(30) primary key, v varchar(30)) " .
|
||||
"engine = innodb default charset = binary");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
print "WR\n";
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v = ($i % 2 == 1) ? $i : undef;
|
||||
$sth->execute($k, $v);
|
||||
$v = "[null]" if !defined($v);
|
||||
print "$k $v\n";
|
||||
$valmap{$k} = $v;
|
||||
}
|
||||
|
||||
my $hs = hstest::get_hs_connection();
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v');
|
||||
my $r = $hs->execute_single(1, '>=', [ '' ], 10000, 0);
|
||||
shift(@$r);
|
||||
print "HS\n";
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = $r->[$i * 2];
|
||||
my $v = $r->[$i * 2 + 1];
|
||||
$v = "[null]" if !defined($v);
|
||||
print "$k $v\n";
|
||||
print "MISMATCH\n" if ($valmap{$k} ne $v);
|
||||
}
|
||||
undef $hs;
|
||||
|
||||
print "MY\n";
|
||||
my $aref = $dbh->selectall_arrayref("select k,v from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v) = @$row;
|
||||
$v = "[null]" if !defined($v);
|
||||
print "$k $v\n";
|
||||
print "MISMATCH\n" if ($valmap{$k} ne $v);
|
||||
}
|
||||
|
644
plugin/handler_socket/regtest/test_01_lib/test06.expected
Normal file
644
plugin/handler_socket/regtest/test_01_lib/test06.expected
Normal file
@ -0,0 +1,644 @@
|
||||
HSINSERTDUMP_TABLE
|
||||
0 v1_0 v2_0
|
||||
1 v1_1 v2_1
|
||||
10 v1_10 v2_10
|
||||
100 v1_100 v2_100
|
||||
101 v1_101 v2_101
|
||||
102 v1_102 v2_102
|
||||
103 v1_103 v2_103
|
||||
104 v1_104 v2_104
|
||||
105 v1_105 v2_105
|
||||
106 v1_106 v2_106
|
||||
107 v1_107 v2_107
|
||||
108 v1_108 v2_108
|
||||
109 v1_109 v2_109
|
||||
11 v1_11 v2_11
|
||||
110 v1_110 v2_110
|
||||
111 v1_111 v2_111
|
||||
112 v1_112 v2_112
|
||||
113 v1_113 v2_113
|
||||
114 v1_114 v2_114
|
||||
115 v1_115 v2_115
|
||||
116 v1_116 v2_116
|
||||
117 v1_117 v2_117
|
||||
118 v1_118 v2_118
|
||||
119 v1_119 v2_119
|
||||
12 v1_12 v2_12
|
||||
120 v1_120 v2_120
|
||||
121 v1_121 v2_121
|
||||
122 v1_122 v2_122
|
||||
123 v1_123 v2_123
|
||||
124 v1_124 v2_124
|
||||
125 v1_125 v2_125
|
||||
126 v1_126 v2_126
|
||||
127 v1_127 v2_127
|
||||
128 v1_128 v2_128
|
||||
129 v1_129 v2_129
|
||||
13 v1_13 v2_13
|
||||
130 v1_130 v2_130
|
||||
131 v1_131 v2_131
|
||||
132 v1_132 v2_132
|
||||
133 v1_133 v2_133
|
||||
134 v1_134 v2_134
|
||||
135 v1_135 v2_135
|
||||
136 v1_136 v2_136
|
||||
137 v1_137 v2_137
|
||||
138 v1_138 v2_138
|
||||
139 v1_139 v2_139
|
||||
14 v1_14 v2_14
|
||||
140 v1_140 v2_140
|
||||
141 v1_141 v2_141
|
||||
142 v1_142 v2_142
|
||||
143 v1_143 v2_143
|
||||
144 v1_144 v2_144
|
||||
145 v1_145 v2_145
|
||||
146 v1_146 v2_146
|
||||
147 v1_147 v2_147
|
||||
148 v1_148 v2_148
|
||||
149 v1_149 v2_149
|
||||
15 v1_15 v2_15
|
||||
150 v1_150 v2_150
|
||||
151 v1_151 v2_151
|
||||
152 v1_152 v2_152
|
||||
153 v1_153 v2_153
|
||||
154 v1_154 v2_154
|
||||
155 v1_155 v2_155
|
||||
156 v1_156 v2_156
|
||||
157 v1_157 v2_157
|
||||
158 v1_158 v2_158
|
||||
159 v1_159 v2_159
|
||||
16 v1_16 v2_16
|
||||
160 v1_160 v2_160
|
||||
161 v1_161 v2_161
|
||||
162 v1_162 v2_162
|
||||
163 v1_163 v2_163
|
||||
164 v1_164 v2_164
|
||||
165 v1_165 v2_165
|
||||
166 v1_166 v2_166
|
||||
167 v1_167 v2_167
|
||||
168 v1_168 v2_168
|
||||
169 v1_169 v2_169
|
||||
17 v1_17 v2_17
|
||||
170 v1_170 v2_170
|
||||
171 v1_171 v2_171
|
||||
172 v1_172 v2_172
|
||||
173 v1_173 v2_173
|
||||
174 v1_174 v2_174
|
||||
175 v1_175 v2_175
|
||||
176 v1_176 v2_176
|
||||
177 v1_177 v2_177
|
||||
178 v1_178 v2_178
|
||||
179 v1_179 v2_179
|
||||
18 v1_18 v2_18
|
||||
180 v1_180 v2_180
|
||||
181 v1_181 v2_181
|
||||
182 v1_182 v2_182
|
||||
183 v1_183 v2_183
|
||||
184 v1_184 v2_184
|
||||
185 v1_185 v2_185
|
||||
186 v1_186 v2_186
|
||||
187 v1_187 v2_187
|
||||
188 v1_188 v2_188
|
||||
189 v1_189 v2_189
|
||||
19 v1_19 v2_19
|
||||
190 v1_190 v2_190
|
||||
191 v1_191 v2_191
|
||||
192 v1_192 v2_192
|
||||
193 v1_193 v2_193
|
||||
194 v1_194 v2_194
|
||||
195 v1_195 v2_195
|
||||
196 v1_196 v2_196
|
||||
197 v1_197 v2_197
|
||||
198 v1_198 v2_198
|
||||
199 v1_199 v2_199
|
||||
2 v1_2 v2_2
|
||||
20 v1_20 v2_20
|
||||
200 v1_200 v2_200
|
||||
201 v1_201 v2_201
|
||||
202 v1_202 v2_202
|
||||
203 v1_203 v2_203
|
||||
204 v1_204 v2_204
|
||||
205 v1_205 v2_205
|
||||
206 v1_206 v2_206
|
||||
207 v1_207 v2_207
|
||||
208 v1_208 v2_208
|
||||
209 v1_209 v2_209
|
||||
21 v1_21 v2_21
|
||||
210 v1_210 v2_210
|
||||
211 v1_211 v2_211
|
||||
212 v1_212 v2_212
|
||||
213 v1_213 v2_213
|
||||
214 v1_214 v2_214
|
||||
215 v1_215 v2_215
|
||||
216 v1_216 v2_216
|
||||
217 v1_217 v2_217
|
||||
218 v1_218 v2_218
|
||||
219 v1_219 v2_219
|
||||
22 v1_22 v2_22
|
||||
220 v1_220 v2_220
|
||||
221 v1_221 v2_221
|
||||
222 v1_222 v2_222
|
||||
223 v1_223 v2_223
|
||||
224 v1_224 v2_224
|
||||
225 v1_225 v2_225
|
||||
226 v1_226 v2_226
|
||||
227 v1_227 v2_227
|
||||
228 v1_228 v2_228
|
||||
229 v1_229 v2_229
|
||||
23 v1_23 v2_23
|
||||
230 v1_230 v2_230
|
||||
231 v1_231 v2_231
|
||||
232 v1_232 v2_232
|
||||
233 v1_233 v2_233
|
||||
234 v1_234 v2_234
|
||||
235 v1_235 v2_235
|
||||
236 v1_236 v2_236
|
||||
237 v1_237 v2_237
|
||||
238 v1_238 v2_238
|
||||
239 v1_239 v2_239
|
||||
24 v1_24 v2_24
|
||||
240 v1_240 v2_240
|
||||
241 v1_241 v2_241
|
||||
242 v1_242 v2_242
|
||||
243 v1_243 v2_243
|
||||
244 v1_244 v2_244
|
||||
245 v1_245 v2_245
|
||||
246 v1_246 v2_246
|
||||
247 v1_247 v2_247
|
||||
248 v1_248 v2_248
|
||||
249 v1_249 v2_249
|
||||
25 v1_25 v2_25
|
||||
250 v1_250 v2_250
|
||||
251 v1_251 v2_251
|
||||
252 v1_252 v2_252
|
||||
253 v1_253 v2_253
|
||||
254 v1_254 v2_254
|
||||
255 v1_255 v2_255
|
||||
26 v1_26 v2_26
|
||||
27 v1_27 v2_27
|
||||
28 v1_28 v2_28
|
||||
29 v1_29 v2_29
|
||||
3 v1_3 v2_3
|
||||
30 v1_30 v2_30
|
||||
31 v1_31 v2_31
|
||||
32 v1_32 v2_32
|
||||
33 v1_33 v2_33
|
||||
34 v1_34 v2_34
|
||||
35 v1_35 v2_35
|
||||
36 v1_36 v2_36
|
||||
37 v1_37 v2_37
|
||||
38 v1_38 v2_38
|
||||
39 v1_39 v2_39
|
||||
4 v1_4 v2_4
|
||||
40 v1_40 v2_40
|
||||
41 v1_41 v2_41
|
||||
42 v1_42 v2_42
|
||||
43 v1_43 v2_43
|
||||
44 v1_44 v2_44
|
||||
45 v1_45 v2_45
|
||||
46 v1_46 v2_46
|
||||
47 v1_47 v2_47
|
||||
48 v1_48 v2_48
|
||||
49 v1_49 v2_49
|
||||
5 v1_5 v2_5
|
||||
50 v1_50 v2_50
|
||||
51 v1_51 v2_51
|
||||
52 v1_52 v2_52
|
||||
53 v1_53 v2_53
|
||||
54 v1_54 v2_54
|
||||
55 v1_55 v2_55
|
||||
56 v1_56 v2_56
|
||||
57 v1_57 v2_57
|
||||
58 v1_58 v2_58
|
||||
59 v1_59 v2_59
|
||||
6 v1_6 v2_6
|
||||
60 v1_60 v2_60
|
||||
61 v1_61 v2_61
|
||||
62 v1_62 v2_62
|
||||
63 v1_63 v2_63
|
||||
64 v1_64 v2_64
|
||||
65 v1_65 v2_65
|
||||
66 v1_66 v2_66
|
||||
67 v1_67 v2_67
|
||||
68 v1_68 v2_68
|
||||
69 v1_69 v2_69
|
||||
7 v1_7 v2_7
|
||||
70 v1_70 v2_70
|
||||
71 v1_71 v2_71
|
||||
72 v1_72 v2_72
|
||||
73 v1_73 v2_73
|
||||
74 v1_74 v2_74
|
||||
75 v1_75 v2_75
|
||||
76 v1_76 v2_76
|
||||
77 v1_77 v2_77
|
||||
78 v1_78 v2_78
|
||||
79 v1_79 v2_79
|
||||
8 v1_8 v2_8
|
||||
80 v1_80 v2_80
|
||||
81 v1_81 v2_81
|
||||
82 v1_82 v2_82
|
||||
83 v1_83 v2_83
|
||||
84 v1_84 v2_84
|
||||
85 v1_85 v2_85
|
||||
86 v1_86 v2_86
|
||||
87 v1_87 v2_87
|
||||
88 v1_88 v2_88
|
||||
89 v1_89 v2_89
|
||||
9 v1_9 v2_9
|
||||
90 v1_90 v2_90
|
||||
91 v1_91 v2_91
|
||||
92 v1_92 v2_92
|
||||
93 v1_93 v2_93
|
||||
94 v1_94 v2_94
|
||||
95 v1_95 v2_95
|
||||
96 v1_96 v2_96
|
||||
97 v1_97 v2_97
|
||||
98 v1_98 v2_98
|
||||
99 v1_99 v2_99
|
||||
HSUPDATEDUMP_TABLE
|
||||
0 mod_0 v2_0
|
||||
1 mod_1 v2_1
|
||||
10 mod_10 v2_10
|
||||
100 mod_100 v2_100
|
||||
101 mod_101 v2_101
|
||||
102 mod_102 v2_102
|
||||
103 mod_103 v2_103
|
||||
104 mod_104 v2_104
|
||||
105 mod_105 v2_105
|
||||
106 mod_106 v2_106
|
||||
107 mod_107 v2_107
|
||||
108 mod_108 v2_108
|
||||
109 mod_109 v2_109
|
||||
11 mod_11 v2_11
|
||||
110 mod_110 v2_110
|
||||
111 mod_111 v2_111
|
||||
112 mod_112 v2_112
|
||||
113 mod_113 v2_113
|
||||
114 mod_114 v2_114
|
||||
115 mod_115 v2_115
|
||||
116 mod_116 v2_116
|
||||
117 mod_117 v2_117
|
||||
118 mod_118 v2_118
|
||||
119 mod_119 v2_119
|
||||
12 mod_12 v2_12
|
||||
120 mod_120 v2_120
|
||||
121 mod_121 v2_121
|
||||
122 mod_122 v2_122
|
||||
123 mod_123 v2_123
|
||||
124 mod_124 v2_124
|
||||
125 mod_125 v2_125
|
||||
126 mod_126 v2_126
|
||||
127 mod_127 v2_127
|
||||
128 mod_128 v2_128
|
||||
129 mod_129 v2_129
|
||||
13 mod_13 v2_13
|
||||
130 mod_130 v2_130
|
||||
131 mod_131 v2_131
|
||||
132 mod_132 v2_132
|
||||
133 mod_133 v2_133
|
||||
134 mod_134 v2_134
|
||||
135 mod_135 v2_135
|
||||
136 mod_136 v2_136
|
||||
137 mod_137 v2_137
|
||||
138 mod_138 v2_138
|
||||
139 mod_139 v2_139
|
||||
14 mod_14 v2_14
|
||||
140 mod_140 v2_140
|
||||
141 mod_141 v2_141
|
||||
142 mod_142 v2_142
|
||||
143 mod_143 v2_143
|
||||
144 mod_144 v2_144
|
||||
145 mod_145 v2_145
|
||||
146 mod_146 v2_146
|
||||
147 mod_147 v2_147
|
||||
148 mod_148 v2_148
|
||||
149 mod_149 v2_149
|
||||
15 mod_15 v2_15
|
||||
150 mod_150 v2_150
|
||||
151 mod_151 v2_151
|
||||
152 mod_152 v2_152
|
||||
153 mod_153 v2_153
|
||||
154 mod_154 v2_154
|
||||
155 mod_155 v2_155
|
||||
156 mod_156 v2_156
|
||||
157 mod_157 v2_157
|
||||
158 mod_158 v2_158
|
||||
159 mod_159 v2_159
|
||||
16 mod_16 v2_16
|
||||
160 mod_160 v2_160
|
||||
161 mod_161 v2_161
|
||||
162 mod_162 v2_162
|
||||
163 mod_163 v2_163
|
||||
164 mod_164 v2_164
|
||||
165 mod_165 v2_165
|
||||
166 mod_166 v2_166
|
||||
167 mod_167 v2_167
|
||||
168 mod_168 v2_168
|
||||
169 mod_169 v2_169
|
||||
17 mod_17 v2_17
|
||||
170 mod_170 v2_170
|
||||
171 mod_171 v2_171
|
||||
172 mod_172 v2_172
|
||||
173 mod_173 v2_173
|
||||
174 mod_174 v2_174
|
||||
175 mod_175 v2_175
|
||||
176 mod_176 v2_176
|
||||
177 mod_177 v2_177
|
||||
178 mod_178 v2_178
|
||||
179 mod_179 v2_179
|
||||
18 mod_18 v2_18
|
||||
180 mod_180 v2_180
|
||||
181 mod_181 v2_181
|
||||
182 mod_182 v2_182
|
||||
183 mod_183 v2_183
|
||||
184 mod_184 v2_184
|
||||
185 mod_185 v2_185
|
||||
186 mod_186 v2_186
|
||||
187 mod_187 v2_187
|
||||
188 mod_188 v2_188
|
||||
189 mod_189 v2_189
|
||||
19 mod_19 v2_19
|
||||
190 mod_190 v2_190
|
||||
191 mod_191 v2_191
|
||||
192 mod_192 v2_192
|
||||
193 mod_193 v2_193
|
||||
194 mod_194 v2_194
|
||||
195 mod_195 v2_195
|
||||
196 mod_196 v2_196
|
||||
197 mod_197 v2_197
|
||||
198 mod_198 v2_198
|
||||
199 mod_199 v2_199
|
||||
2 mod_2 v2_2
|
||||
20 mod_20 v2_20
|
||||
200 mod_200 v2_200
|
||||
201 mod_201 v2_201
|
||||
202 mod_202 v2_202
|
||||
203 mod_203 v2_203
|
||||
204 mod_204 v2_204
|
||||
205 mod_205 v2_205
|
||||
206 mod_206 v2_206
|
||||
207 mod_207 v2_207
|
||||
208 mod_208 v2_208
|
||||
209 mod_209 v2_209
|
||||
21 mod_21 v2_21
|
||||
210 mod_210 v2_210
|
||||
211 mod_211 v2_211
|
||||
212 mod_212 v2_212
|
||||
213 mod_213 v2_213
|
||||
214 mod_214 v2_214
|
||||
215 mod_215 v2_215
|
||||
216 mod_216 v2_216
|
||||
217 mod_217 v2_217
|
||||
218 mod_218 v2_218
|
||||
219 mod_219 v2_219
|
||||
22 mod_22 v2_22
|
||||
220 mod_220 v2_220
|
||||
221 mod_221 v2_221
|
||||
222 mod_222 v2_222
|
||||
223 mod_223 v2_223
|
||||
224 mod_224 v2_224
|
||||
225 mod_225 v2_225
|
||||
226 mod_226 v2_226
|
||||
227 mod_227 v2_227
|
||||
228 mod_228 v2_228
|
||||
229 mod_229 v2_229
|
||||
23 mod_23 v2_23
|
||||
230 mod_230 v2_230
|
||||
231 mod_231 v2_231
|
||||
232 mod_232 v2_232
|
||||
233 mod_233 v2_233
|
||||
234 mod_234 v2_234
|
||||
235 mod_235 v2_235
|
||||
236 mod_236 v2_236
|
||||
237 mod_237 v2_237
|
||||
238 mod_238 v2_238
|
||||
239 mod_239 v2_239
|
||||
24 mod_24 v2_24
|
||||
240 mod_240 v2_240
|
||||
241 mod_241 v2_241
|
||||
242 mod_242 v2_242
|
||||
243 mod_243 v2_243
|
||||
244 mod_244 v2_244
|
||||
245 mod_245 v2_245
|
||||
246 mod_246 v2_246
|
||||
247 mod_247 v2_247
|
||||
248 mod_248 v2_248
|
||||
249 mod_249 v2_249
|
||||
25 mod_25 v2_25
|
||||
250 mod_250 v2_250
|
||||
251 mod_251 v2_251
|
||||
252 mod_252 v2_252
|
||||
253 mod_253 v2_253
|
||||
254 mod_254 v2_254
|
||||
255 mod_255 v2_255
|
||||
26 mod_26 v2_26
|
||||
27 mod_27 v2_27
|
||||
28 mod_28 v2_28
|
||||
29 mod_29 v2_29
|
||||
3 mod_3 v2_3
|
||||
30 mod_30 v2_30
|
||||
31 mod_31 v2_31
|
||||
32 mod_32 v2_32
|
||||
33 mod_33 v2_33
|
||||
34 mod_34 v2_34
|
||||
35 mod_35 v2_35
|
||||
36 mod_36 v2_36
|
||||
37 mod_37 v2_37
|
||||
38 mod_38 v2_38
|
||||
39 mod_39 v2_39
|
||||
4 mod_4 v2_4
|
||||
40 mod_40 v2_40
|
||||
41 mod_41 v2_41
|
||||
42 mod_42 v2_42
|
||||
43 mod_43 v2_43
|
||||
44 mod_44 v2_44
|
||||
45 mod_45 v2_45
|
||||
46 mod_46 v2_46
|
||||
47 mod_47 v2_47
|
||||
48 mod_48 v2_48
|
||||
49 mod_49 v2_49
|
||||
5 mod_5 v2_5
|
||||
50 mod_50 v2_50
|
||||
51 mod_51 v2_51
|
||||
52 mod_52 v2_52
|
||||
53 mod_53 v2_53
|
||||
54 mod_54 v2_54
|
||||
55 mod_55 v2_55
|
||||
56 mod_56 v2_56
|
||||
57 mod_57 v2_57
|
||||
58 mod_58 v2_58
|
||||
59 mod_59 v2_59
|
||||
6 mod_6 v2_6
|
||||
60 mod_60 v2_60
|
||||
61 mod_61 v2_61
|
||||
62 mod_62 v2_62
|
||||
63 mod_63 v2_63
|
||||
64 mod_64 v2_64
|
||||
65 mod_65 v2_65
|
||||
66 mod_66 v2_66
|
||||
67 mod_67 v2_67
|
||||
68 mod_68 v2_68
|
||||
69 mod_69 v2_69
|
||||
7 mod_7 v2_7
|
||||
70 mod_70 v2_70
|
||||
71 mod_71 v2_71
|
||||
72 mod_72 v2_72
|
||||
73 mod_73 v2_73
|
||||
74 mod_74 v2_74
|
||||
75 mod_75 v2_75
|
||||
76 mod_76 v2_76
|
||||
77 mod_77 v2_77
|
||||
78 mod_78 v2_78
|
||||
79 mod_79 v2_79
|
||||
8 mod_8 v2_8
|
||||
80 mod_80 v2_80
|
||||
81 mod_81 v2_81
|
||||
82 mod_82 v2_82
|
||||
83 mod_83 v2_83
|
||||
84 mod_84 v2_84
|
||||
85 mod_85 v2_85
|
||||
86 mod_86 v2_86
|
||||
87 mod_87 v2_87
|
||||
88 mod_88 v2_88
|
||||
89 mod_89 v2_89
|
||||
9 mod_9 v2_9
|
||||
90 mod_90 v2_90
|
||||
91 mod_91 v2_91
|
||||
92 mod_92 v2_92
|
||||
93 mod_93 v2_93
|
||||
94 mod_94 v2_94
|
||||
95 mod_95 v2_95
|
||||
96 mod_96 v2_96
|
||||
97 mod_97 v2_97
|
||||
98 mod_98 v2_98
|
||||
99 mod_99 v2_99
|
||||
HSDELETE
|
||||
DUMP_TABLE
|
||||
1 mod_1 v2_1
|
||||
101 mod_101 v2_101
|
||||
103 mod_103 v2_103
|
||||
105 mod_105 v2_105
|
||||
107 mod_107 v2_107
|
||||
109 mod_109 v2_109
|
||||
11 mod_11 v2_11
|
||||
111 mod_111 v2_111
|
||||
113 mod_113 v2_113
|
||||
115 mod_115 v2_115
|
||||
117 mod_117 v2_117
|
||||
119 mod_119 v2_119
|
||||
121 mod_121 v2_121
|
||||
123 mod_123 v2_123
|
||||
125 mod_125 v2_125
|
||||
127 mod_127 v2_127
|
||||
129 mod_129 v2_129
|
||||
13 mod_13 v2_13
|
||||
131 mod_131 v2_131
|
||||
133 mod_133 v2_133
|
||||
135 mod_135 v2_135
|
||||
137 mod_137 v2_137
|
||||
139 mod_139 v2_139
|
||||
141 mod_141 v2_141
|
||||
143 mod_143 v2_143
|
||||
145 mod_145 v2_145
|
||||
147 mod_147 v2_147
|
||||
149 mod_149 v2_149
|
||||
15 mod_15 v2_15
|
||||
151 mod_151 v2_151
|
||||
153 mod_153 v2_153
|
||||
155 mod_155 v2_155
|
||||
157 mod_157 v2_157
|
||||
159 mod_159 v2_159
|
||||
161 mod_161 v2_161
|
||||
163 mod_163 v2_163
|
||||
165 mod_165 v2_165
|
||||
167 mod_167 v2_167
|
||||
169 mod_169 v2_169
|
||||
17 mod_17 v2_17
|
||||
171 mod_171 v2_171
|
||||
173 mod_173 v2_173
|
||||
175 mod_175 v2_175
|
||||
177 mod_177 v2_177
|
||||
179 mod_179 v2_179
|
||||
181 mod_181 v2_181
|
||||
183 mod_183 v2_183
|
||||
185 mod_185 v2_185
|
||||
187 mod_187 v2_187
|
||||
189 mod_189 v2_189
|
||||
19 mod_19 v2_19
|
||||
191 mod_191 v2_191
|
||||
193 mod_193 v2_193
|
||||
195 mod_195 v2_195
|
||||
197 mod_197 v2_197
|
||||
199 mod_199 v2_199
|
||||
201 mod_201 v2_201
|
||||
203 mod_203 v2_203
|
||||
205 mod_205 v2_205
|
||||
207 mod_207 v2_207
|
||||
209 mod_209 v2_209
|
||||
21 mod_21 v2_21
|
||||
211 mod_211 v2_211
|
||||
213 mod_213 v2_213
|
||||
215 mod_215 v2_215
|
||||
217 mod_217 v2_217
|
||||
219 mod_219 v2_219
|
||||
221 mod_221 v2_221
|
||||
223 mod_223 v2_223
|
||||
225 mod_225 v2_225
|
||||
227 mod_227 v2_227
|
||||
229 mod_229 v2_229
|
||||
23 mod_23 v2_23
|
||||
231 mod_231 v2_231
|
||||
233 mod_233 v2_233
|
||||
235 mod_235 v2_235
|
||||
237 mod_237 v2_237
|
||||
239 mod_239 v2_239
|
||||
241 mod_241 v2_241
|
||||
243 mod_243 v2_243
|
||||
245 mod_245 v2_245
|
||||
247 mod_247 v2_247
|
||||
249 mod_249 v2_249
|
||||
25 mod_25 v2_25
|
||||
251 mod_251 v2_251
|
||||
253 mod_253 v2_253
|
||||
255 mod_255 v2_255
|
||||
27 mod_27 v2_27
|
||||
29 mod_29 v2_29
|
||||
3 mod_3 v2_3
|
||||
31 mod_31 v2_31
|
||||
33 mod_33 v2_33
|
||||
35 mod_35 v2_35
|
||||
37 mod_37 v2_37
|
||||
39 mod_39 v2_39
|
||||
41 mod_41 v2_41
|
||||
43 mod_43 v2_43
|
||||
45 mod_45 v2_45
|
||||
47 mod_47 v2_47
|
||||
49 mod_49 v2_49
|
||||
5 mod_5 v2_5
|
||||
51 mod_51 v2_51
|
||||
53 mod_53 v2_53
|
||||
55 mod_55 v2_55
|
||||
57 mod_57 v2_57
|
||||
59 mod_59 v2_59
|
||||
61 mod_61 v2_61
|
||||
63 mod_63 v2_63
|
||||
65 mod_65 v2_65
|
||||
67 mod_67 v2_67
|
||||
69 mod_69 v2_69
|
||||
7 mod_7 v2_7
|
||||
71 mod_71 v2_71
|
||||
73 mod_73 v2_73
|
||||
75 mod_75 v2_75
|
||||
77 mod_77 v2_77
|
||||
79 mod_79 v2_79
|
||||
81 mod_81 v2_81
|
||||
83 mod_83 v2_83
|
||||
85 mod_85 v2_85
|
||||
87 mod_87 v2_87
|
||||
89 mod_89 v2_89
|
||||
9 mod_9 v2_9
|
||||
91 mod_91 v2_91
|
||||
93 mod_93 v2_93
|
||||
95 mod_95 v2_95
|
||||
97 mod_97 v2_97
|
||||
99 mod_99 v2_99
|
90
plugin/handler_socket/regtest/test_01_lib/test06.pl
Normal file
90
plugin/handler_socket/regtest/test_01_lib/test06.pl
Normal file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for insert/update/delete
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 256;
|
||||
$dbh->do(
|
||||
"create table $table (" .
|
||||
"k varchar(30) primary key, " .
|
||||
"v1 varchar(30), " .
|
||||
"v2 varchar(30)) " .
|
||||
"engine = innodb default charset = binary");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
print "HSINSERT";
|
||||
my $hs = hstest::get_hs_connection(undef, 9999);
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v1,v2');
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v1 = "v1_" . $i;
|
||||
my $v2 = "v2_" . $i;
|
||||
my $r = $hs->execute_insert(1, [ $k, $v1, $v2 ]);
|
||||
my $err = $r->[0];
|
||||
if ($err != 0) {
|
||||
my $err_str = $r->[1];
|
||||
print "$err $err_str\n";
|
||||
}
|
||||
}
|
||||
undef $hs;
|
||||
|
||||
dump_table();
|
||||
|
||||
print "HSUPDATE";
|
||||
$hs = hstest::get_hs_connection(undef, 9999);
|
||||
$dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(2, $dbname, $table, '', 'v1');
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $r = $hs->execute_single(2, '=', [ $i ], 1000, 0, 'U', [ "mod_$i" ]);
|
||||
my $err = $r->[0];
|
||||
if ($err != 0) {
|
||||
my $err_str = $r->[1];
|
||||
print "$err $err_str\n";
|
||||
}
|
||||
}
|
||||
undef $hs;
|
||||
|
||||
dump_table();
|
||||
|
||||
print "HSDELETE\n";
|
||||
$hs = hstest::get_hs_connection(undef, 9999);
|
||||
$dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(3, $dbname, $table, '', '');
|
||||
for (my $i = 0; $i < $tablesize; $i = $i + 2) {
|
||||
my $r = $hs->execute_single(3, '=', [ $i ], 1000, 0, 'D');
|
||||
my $err = $r->[0];
|
||||
if ($err != 0) {
|
||||
my $err_str = $r->[1];
|
||||
print "$err $err_str\n";
|
||||
}
|
||||
}
|
||||
undef $hs;
|
||||
|
||||
dump_table();
|
||||
|
||||
sub dump_table {
|
||||
print "DUMP_TABLE\n";
|
||||
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v1, $v2) = @$row;
|
||||
$v1 = "[null]" if !defined($v1);
|
||||
$v2 = "[null]" if !defined($v2);
|
||||
print "$k $v1 $v2\n";
|
||||
# print "MISMATCH\n" if ($valmap{$k} ne $v);
|
||||
}
|
||||
}
|
||||
|
304
plugin/handler_socket/regtest/test_01_lib/test07.expected
Normal file
304
plugin/handler_socket/regtest/test_01_lib/test07.expected
Normal file
@ -0,0 +1,304 @@
|
||||
MY
|
||||
0 1v1020 2v6350
|
||||
1 1v8031 2v9251
|
||||
2 1v7752 2v5372
|
||||
3 [NULL] 2v4143
|
||||
4 1v5904 2v3024
|
||||
5 1v7045 2v7515
|
||||
6 1v3676 2v4006
|
||||
7 1v3977 2v1707
|
||||
8 1v7198 2v7348
|
||||
9 1v5879 2v4949
|
||||
10 1v52310 2v95410
|
||||
11 1v43311 2v82011
|
||||
12 1v28312 2v83712
|
||||
13 [NULL] 2v41513
|
||||
14 1v54514 2v58314
|
||||
15 1v5215 2v32315
|
||||
16 1v61416 2v67916
|
||||
17 1v80517 2v45117
|
||||
18 1v11518 2v26918
|
||||
19 1v21819 2v61719
|
||||
20 1v87820 2v34520
|
||||
21 1v51221 2v96921
|
||||
22 1v40822 2v29122
|
||||
23 [NULL] 2v95323
|
||||
24 1v71024 2v14224
|
||||
25 1v68225 2v93425
|
||||
26 1v62126 2v96526
|
||||
27 1v57427 2v20427
|
||||
28 1v29828 2v13428
|
||||
29 1v98329 2v44429
|
||||
30 1v14430 2v15230
|
||||
31 1v18731 2v21531
|
||||
32 1v832 2v69732
|
||||
33 [NULL] 2v28033
|
||||
34 1v70134 2v53734
|
||||
35 1v41335 2v6935
|
||||
36 1v8636 2v82236
|
||||
37 1v67037 2v37037
|
||||
38 1v80638 2v68838
|
||||
39 1v2639 2v6639
|
||||
40 1v80240 2v17140
|
||||
41 1v55741 2v84741
|
||||
42 1v77742 2v73042
|
||||
43 [NULL] 2v11543
|
||||
44 1v64644 2v49644
|
||||
45 1v12045 2v68445
|
||||
46 1v37446 2v6546
|
||||
47 1v37047 2v17447
|
||||
48 1v82848 2v86748
|
||||
49 1v75949 2v70349
|
||||
50 1v84350 2v94250
|
||||
51 1v40151 2v36251
|
||||
52 1v36752 2v30752
|
||||
53 [NULL] 2v16753
|
||||
54 1v79954 2v82954
|
||||
55 1v53955 2v37955
|
||||
56 1v56056 2v85856
|
||||
57 1v57957 2v2657
|
||||
58 1v88758 2v50758
|
||||
59 1v34559 2v89859
|
||||
60 1v43060 2v80160
|
||||
61 1v84561 2v32561
|
||||
62 1v62462 2v48062
|
||||
63 [NULL] 2v67663
|
||||
64 1v5364 2v73664
|
||||
65 1v80965 2v27065
|
||||
66 1v17566 2v83966
|
||||
67 1v6167 2v22267
|
||||
68 1v35868 2v50568
|
||||
69 1v62769 2v90669
|
||||
70 1v4670 2v98170
|
||||
71 1v11971 2v471
|
||||
72 1v1472 2v48072
|
||||
73 [NULL] 2v40573
|
||||
74 1v87574 2v63974
|
||||
75 1v82775 2v34475
|
||||
76 1v59876 2v56376
|
||||
77 1v77077 2v51677
|
||||
78 1v53878 2v54878
|
||||
79 1v35779 2v32279
|
||||
80 1v3680 2v37080
|
||||
81 1v33181 2v81581
|
||||
82 1v76982 2v66882
|
||||
83 [NULL] 2v28183
|
||||
84 1v69684 2v45284
|
||||
85 1v40685 2v185
|
||||
86 1v39586 2v32486
|
||||
87 1v3687 2v73887
|
||||
88 1v16088 2v7988
|
||||
89 1v75989 2v65789
|
||||
90 1v3190 2v78390
|
||||
91 1v65091 2v82491
|
||||
92 1v85292 2v6892
|
||||
93 [NULL] 2v54693
|
||||
94 1v81394 2v77594
|
||||
95 1v8795 2v69695
|
||||
96 1v19696 2v38096
|
||||
97 1v7997 2v75197
|
||||
98 1v32398 2v21798
|
||||
99 1v3799 2v70199
|
||||
HS
|
||||
0 1v1020 2v6350
|
||||
1 1v8031 2v9251
|
||||
2 1v7752 2v5372
|
||||
3 [NULL] 2v4143
|
||||
4 1v5904 2v3024
|
||||
5 1v7045 2v7515
|
||||
6 1v3676 2v4006
|
||||
7 1v3977 2v1707
|
||||
8 1v7198 2v7348
|
||||
9 1v5879 2v4949
|
||||
10 1v52310 2v95410
|
||||
11 1v43311 2v82011
|
||||
12 1v28312 2v83712
|
||||
13 [NULL] 2v41513
|
||||
14 1v54514 2v58314
|
||||
15 1v5215 2v32315
|
||||
16 1v61416 2v67916
|
||||
17 1v80517 2v45117
|
||||
18 1v11518 2v26918
|
||||
19 1v21819 2v61719
|
||||
20 1v87820 2v34520
|
||||
21 1v51221 2v96921
|
||||
22 1v40822 2v29122
|
||||
23 [NULL] 2v95323
|
||||
24 1v71024 2v14224
|
||||
25 1v68225 2v93425
|
||||
26 1v62126 2v96526
|
||||
27 1v57427 2v20427
|
||||
28 1v29828 2v13428
|
||||
29 1v98329 2v44429
|
||||
30 1v14430 2v15230
|
||||
31 1v18731 2v21531
|
||||
32 1v832 2v69732
|
||||
33 [NULL] 2v28033
|
||||
34 1v70134 2v53734
|
||||
35 1v41335 2v6935
|
||||
36 1v8636 2v82236
|
||||
37 1v67037 2v37037
|
||||
38 1v80638 2v68838
|
||||
39 1v2639 2v6639
|
||||
40 1v80240 2v17140
|
||||
41 1v55741 2v84741
|
||||
42 1v77742 2v73042
|
||||
43 [NULL] 2v11543
|
||||
44 1v64644 2v49644
|
||||
45 1v12045 2v68445
|
||||
46 1v37446 2v6546
|
||||
47 1v37047 2v17447
|
||||
48 1v82848 2v86748
|
||||
49 1v75949 2v70349
|
||||
50 1v84350 2v94250
|
||||
51 1v40151 2v36251
|
||||
52 1v36752 2v30752
|
||||
53 [NULL] 2v16753
|
||||
54 1v79954 2v82954
|
||||
55 1v53955 2v37955
|
||||
56 1v56056 2v85856
|
||||
57 1v57957 2v2657
|
||||
58 1v88758 2v50758
|
||||
59 1v34559 2v89859
|
||||
60 1v43060 2v80160
|
||||
61 1v84561 2v32561
|
||||
62 1v62462 2v48062
|
||||
63 [NULL] 2v67663
|
||||
64 1v5364 2v73664
|
||||
65 1v80965 2v27065
|
||||
66 1v17566 2v83966
|
||||
67 1v6167 2v22267
|
||||
68 1v35868 2v50568
|
||||
69 1v62769 2v90669
|
||||
70 1v4670 2v98170
|
||||
71 1v11971 2v471
|
||||
72 1v1472 2v48072
|
||||
73 [NULL] 2v40573
|
||||
74 1v87574 2v63974
|
||||
75 1v82775 2v34475
|
||||
76 1v59876 2v56376
|
||||
77 1v77077 2v51677
|
||||
78 1v53878 2v54878
|
||||
79 1v35779 2v32279
|
||||
80 1v3680 2v37080
|
||||
81 1v33181 2v81581
|
||||
82 1v76982 2v66882
|
||||
83 [NULL] 2v28183
|
||||
84 1v69684 2v45284
|
||||
85 1v40685 2v185
|
||||
86 1v39586 2v32486
|
||||
87 1v3687 2v73887
|
||||
88 1v16088 2v7988
|
||||
89 1v75989 2v65789
|
||||
90 1v3190 2v78390
|
||||
91 1v65091 2v82491
|
||||
92 1v85292 2v6892
|
||||
93 [NULL] 2v54693
|
||||
94 1v81394 2v77594
|
||||
95 1v8795 2v69695
|
||||
96 1v19696 2v38096
|
||||
97 1v7997 2v75197
|
||||
98 1v32398 2v21798
|
||||
99 1v3799 2v70199
|
||||
2ndIDX
|
||||
2ndidx 0 1v1020 => 0 1v1020 2v6350
|
||||
2ndidx 1 1v8031 => 1 1v8031 2v9251
|
||||
2ndidx 2 1v7752 => 2 1v7752 2v5372
|
||||
2ndidx 4 1v5904 => 4 1v5904 2v3024
|
||||
2ndidx 5 1v7045 => 5 1v7045 2v7515
|
||||
2ndidx 6 1v3676 => 6 1v3676 2v4006
|
||||
2ndidx 7 1v3977 => 7 1v3977 2v1707
|
||||
2ndidx 8 1v7198 => 8 1v7198 2v7348
|
||||
2ndidx 9 1v5879 => 9 1v5879 2v4949
|
||||
2ndidx 10 1v52310 => 10 1v52310 2v95410
|
||||
2ndidx 11 1v43311 => 11 1v43311 2v82011
|
||||
2ndidx 12 1v28312 => 12 1v28312 2v83712
|
||||
2ndidx 14 1v54514 => 14 1v54514 2v58314
|
||||
2ndidx 15 1v5215 => 15 1v5215 2v32315
|
||||
2ndidx 16 1v61416 => 16 1v61416 2v67916
|
||||
2ndidx 17 1v80517 => 17 1v80517 2v45117
|
||||
2ndidx 18 1v11518 => 18 1v11518 2v26918
|
||||
2ndidx 19 1v21819 => 19 1v21819 2v61719
|
||||
2ndidx 20 1v87820 => 20 1v87820 2v34520
|
||||
2ndidx 21 1v51221 => 21 1v51221 2v96921
|
||||
2ndidx 22 1v40822 => 22 1v40822 2v29122
|
||||
2ndidx 24 1v71024 => 24 1v71024 2v14224
|
||||
2ndidx 25 1v68225 => 25 1v68225 2v93425
|
||||
2ndidx 26 1v62126 => 26 1v62126 2v96526
|
||||
2ndidx 27 1v57427 => 27 1v57427 2v20427
|
||||
2ndidx 28 1v29828 => 28 1v29828 2v13428
|
||||
2ndidx 29 1v98329 => 29 1v98329 2v44429
|
||||
2ndidx 30 1v14430 => 30 1v14430 2v15230
|
||||
2ndidx 31 1v18731 => 31 1v18731 2v21531
|
||||
2ndidx 32 1v832 => 32 1v832 2v69732
|
||||
2ndidx 34 1v70134 => 34 1v70134 2v53734
|
||||
2ndidx 35 1v41335 => 35 1v41335 2v6935
|
||||
2ndidx 36 1v8636 => 36 1v8636 2v82236
|
||||
2ndidx 37 1v67037 => 37 1v67037 2v37037
|
||||
2ndidx 38 1v80638 => 38 1v80638 2v68838
|
||||
2ndidx 39 1v2639 => 39 1v2639 2v6639
|
||||
2ndidx 40 1v80240 => 40 1v80240 2v17140
|
||||
2ndidx 41 1v55741 => 41 1v55741 2v84741
|
||||
2ndidx 42 1v77742 => 42 1v77742 2v73042
|
||||
2ndidx 44 1v64644 => 44 1v64644 2v49644
|
||||
2ndidx 45 1v12045 => 45 1v12045 2v68445
|
||||
2ndidx 46 1v37446 => 46 1v37446 2v6546
|
||||
2ndidx 47 1v37047 => 47 1v37047 2v17447
|
||||
2ndidx 48 1v82848 => 48 1v82848 2v86748
|
||||
2ndidx 49 1v75949 => 49 1v75949 2v70349
|
||||
2ndidx 50 1v84350 => 50 1v84350 2v94250
|
||||
2ndidx 51 1v40151 => 51 1v40151 2v36251
|
||||
2ndidx 52 1v36752 => 52 1v36752 2v30752
|
||||
2ndidx 54 1v79954 => 54 1v79954 2v82954
|
||||
2ndidx 55 1v53955 => 55 1v53955 2v37955
|
||||
2ndidx 56 1v56056 => 56 1v56056 2v85856
|
||||
2ndidx 57 1v57957 => 57 1v57957 2v2657
|
||||
2ndidx 58 1v88758 => 58 1v88758 2v50758
|
||||
2ndidx 59 1v34559 => 59 1v34559 2v89859
|
||||
2ndidx 60 1v43060 => 60 1v43060 2v80160
|
||||
2ndidx 61 1v84561 => 61 1v84561 2v32561
|
||||
2ndidx 62 1v62462 => 62 1v62462 2v48062
|
||||
2ndidx 64 1v5364 => 64 1v5364 2v73664
|
||||
2ndidx 65 1v80965 => 65 1v80965 2v27065
|
||||
2ndidx 66 1v17566 => 66 1v17566 2v83966
|
||||
2ndidx 67 1v6167 => 67 1v6167 2v22267
|
||||
2ndidx 68 1v35868 => 68 1v35868 2v50568
|
||||
2ndidx 69 1v62769 => 69 1v62769 2v90669
|
||||
2ndidx 70 1v4670 => 70 1v4670 2v98170
|
||||
2ndidx 71 1v11971 => 71 1v11971 2v471
|
||||
2ndidx 72 1v1472 => 72 1v1472 2v48072
|
||||
2ndidx 74 1v87574 => 74 1v87574 2v63974
|
||||
2ndidx 75 1v82775 => 75 1v82775 2v34475
|
||||
2ndidx 76 1v59876 => 76 1v59876 2v56376
|
||||
2ndidx 77 1v77077 => 77 1v77077 2v51677
|
||||
2ndidx 78 1v53878 => 78 1v53878 2v54878
|
||||
2ndidx 79 1v35779 => 79 1v35779 2v32279
|
||||
2ndidx 80 1v3680 => 80 1v3680 2v37080
|
||||
2ndidx 81 1v33181 => 81 1v33181 2v81581
|
||||
2ndidx 82 1v76982 => 82 1v76982 2v66882
|
||||
2ndidx 84 1v69684 => 84 1v69684 2v45284
|
||||
2ndidx 85 1v40685 => 85 1v40685 2v185
|
||||
2ndidx 86 1v39586 => 86 1v39586 2v32486
|
||||
2ndidx 87 1v3687 => 87 1v3687 2v73887
|
||||
2ndidx 88 1v16088 => 88 1v16088 2v7988
|
||||
2ndidx 89 1v75989 => 89 1v75989 2v65789
|
||||
2ndidx 90 1v3190 => 90 1v3190 2v78390
|
||||
2ndidx 91 1v65091 => 91 1v65091 2v82491
|
||||
2ndidx 92 1v85292 => 92 1v85292 2v6892
|
||||
2ndidx 94 1v81394 => 94 1v81394 2v77594
|
||||
2ndidx 95 1v8795 => 95 1v8795 2v69695
|
||||
2ndidx 96 1v19696 => 96 1v19696 2v38096
|
||||
2ndidx 97 1v7997 => 97 1v7997 2v75197
|
||||
2ndidx 98 1v32398 => 98 1v32398 2v21798
|
||||
2ndidx 99 1v3799 => 99 1v3799 2v70199
|
||||
2ndIDX NULL
|
||||
2ndidxnull 3 2v4143
|
||||
2ndidxnull 13 2v41513
|
||||
2ndidxnull 23 2v95323
|
||||
2ndidxnull 33 2v28033
|
||||
2ndidxnull 43 2v11543
|
||||
2ndidxnull 53 2v16753
|
||||
2ndidxnull 63 2v67663
|
||||
2ndidxnull 73 2v40573
|
||||
2ndidxnull 83 2v28183
|
||||
2ndidxnull 93 2v54693
|
98
plugin/handler_socket/regtest/test_01_lib/test07.pl
Normal file
98
plugin/handler_socket/regtest/test_01_lib/test07.pl
Normal file
@ -0,0 +1,98 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for nulls
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
# use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 100;
|
||||
$dbh->do(
|
||||
"create table $table (" .
|
||||
"k int primary key, v1 varchar(30), v2 varchar(30), " .
|
||||
"key idxv1 (v1) " .
|
||||
") engine = innodb");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v1 = "1v" . int(rand(1000)) . $i;
|
||||
my $v2 = "2v" . int(rand(1000)) . $i;
|
||||
if ($i % 10 == 3) {
|
||||
$v1 = undef;
|
||||
}
|
||||
$sth->execute($k, $v1, $v2);
|
||||
$valmap{$k} = $v1;
|
||||
}
|
||||
|
||||
print "MY\n";
|
||||
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
|
||||
for my $row (@$aref) {
|
||||
my ($k, $v1, $v2) = @$row;
|
||||
$v1 = "[NULL]" if (!defined($v1));
|
||||
print "$k $v1 $v2\n";
|
||||
}
|
||||
|
||||
print "HS\n";
|
||||
my $hs = hstest::get_hs_connection();
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v1,v2');
|
||||
my $r = $hs->execute_single(1, '>=', [ '' ], 10000, 0);
|
||||
shift(@$r);
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = $r->[$i * 3];
|
||||
my $v1 = $r->[$i * 3 + 1];
|
||||
my $v2 = $r->[$i * 3 + 2];
|
||||
$v1 = "[NULL]" if (!defined($v1));
|
||||
print "$k $v1 $v2\n";
|
||||
}
|
||||
|
||||
print "2ndIDX\n";
|
||||
$hs->open_index(2, $dbname, $table, 'idxv1', 'k,v1,v2');
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "" . $i;
|
||||
my $v1 = $valmap{$k};
|
||||
next if !defined($v1);
|
||||
my $r = $hs->execute_single(2, '=', [ $v1 ], 1, 0);
|
||||
shift(@$r);
|
||||
my $r_k = $r->[0];
|
||||
my $r_v1 = $r->[1];
|
||||
my $r_v2 = $r->[2];
|
||||
print "2ndidx $k $v1 => $r_k $r_v1 $r_v2\n";
|
||||
}
|
||||
|
||||
print "2ndIDX NULL\n";
|
||||
{
|
||||
my %rvals = ();
|
||||
my $v1 = undef;
|
||||
my @arr;
|
||||
push(@arr, undef);
|
||||
my $kv = \@arr;
|
||||
my $r = $hs->execute_single(2, "=", $kv, 10000, 0);
|
||||
shift(@$r);
|
||||
for (my $i = 0; $i < scalar(@$r); $i += 3) {
|
||||
my $k = $r->[$i];
|
||||
my $v1 = $r->[$i + 1];
|
||||
my $v2 = $r->[$i + 2];
|
||||
$rvals{$k} = [ $k, $v1, $v2 ];
|
||||
}
|
||||
for my $i (sort { $a <=> $b } keys %rvals) {
|
||||
my $rec = $rvals{$i};
|
||||
my $k = $rec->[0];
|
||||
my $v1 = $rec->[1];
|
||||
my $v2 = $rec->[2];
|
||||
print "2ndidxnull $k $v2\n";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
[0][k5][v5375]
|
||||
[0]
|
48
plugin/handler_socket/regtest/test_01_lib/test08.pl
Normal file
48
plugin/handler_socket/regtest/test_01_lib/test08.pl
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# vim:sw=2:ai
|
||||
|
||||
# test for not-found
|
||||
|
||||
BEGIN {
|
||||
push @INC, "../common/";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use hstest;
|
||||
|
||||
my $dbh = hstest::init_testdb();
|
||||
my $table = 'hstesttbl';
|
||||
my $tablesize = 100;
|
||||
$dbh->do(
|
||||
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
|
||||
"engine = innodb");
|
||||
srand(999);
|
||||
|
||||
my %valmap = ();
|
||||
|
||||
my $sth = $dbh->prepare("insert into $table values (?,?)");
|
||||
for (my $i = 0; $i < $tablesize; ++$i) {
|
||||
my $k = "k" . $i;
|
||||
my $v = "v" . int(rand(1000)) . $i;
|
||||
$sth->execute($k, $v);
|
||||
$valmap{$k} = $v;
|
||||
}
|
||||
|
||||
my $hs = hstest::get_hs_connection();
|
||||
my $dbname = $hstest::conf{dbname};
|
||||
$hs->open_index(1, $dbname, $table, '', 'k,v');
|
||||
|
||||
dump_rec($hs, 1, 'k5'); # found
|
||||
dump_rec($hs, 1, 'k000000'); # notfound
|
||||
|
||||
sub dump_rec {
|
||||
my ($hs, $idxid, $key) = @_;
|
||||
my $r = $hs->execute_single($idxid, '=', [ $key ], 1, 0);
|
||||
for my $fld (@$r) {
|
||||
print "[$fld]";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
12
plugin/handler_socket/regtest/test_01_lib/test09.expected
Normal file
12
plugin/handler_socket/regtest/test_01_lib/test09.expected
Normal file
@ -0,0 +1,12 @@
|
||||
DEL
|
||||
[0][1]
|
||||
[0][k50][v68250][k51][v93451]
|
||||
DELINS
|
||||
[0][k6][v5926][k60][v14460][k61][v15261]
|
||||
[0][1]
|
||||
[0]
|
||||
[0][k6][v5926][k60][INS][k61][v15261]
|
||||
DELUPUP
|
||||
[0][k7][v4147][k70][v41370][k71][v6971]
|
||||
[0][1]
|
||||
[0][k7][v4147][k70][UP][k71][v6971]
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user