Commit 0b116de7 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-4438 - Spider storage engine

parent 107acbb9
......@@ -81,3 +81,4 @@ usr/share/mysql/mysql_performance_tables.sql
usr/share/mysql/mysql_test_data_timezone.sql
@CASSANDRA_DEB_FILES@
@OQGRAPH_DEB_FILES@
@SPIDER_DEB_FILES@
......@@ -83,3 +83,4 @@ usr/share/mysql/mysql_performance_tables.sql
usr/share/mysql/mysql_test_data_timezone.sql
@CASSANDRA_DEB_FILES@
@OQGRAPH_DEB_FILES@
@SPIDER_DEB_FILES@
......@@ -377,7 +377,7 @@ sub main {
# directly before it executes them, like "make test-force-pl" in RPM builds.
mtr_report("Logging: $0 ", join(" ", @ARGV));
$DEFAULT_SUITES.=",sequence,sql_discovery" if $source_dist;
$DEFAULT_SUITES.=",sequence,sql_discovery,spider,spider/bg" if $source_dist;
command_line_setup();
......
SET(SPIDER_SOURCES
spd_param.cc spd_sys_table.cc spd_trx.cc spd_db_conn.cc spd_conn.cc
spd_table.cc spd_direct_sql.cc spd_udf.cc spd_ping_table.cc
spd_copy_tables.cc spd_i_s.cc spd_malloc.cc ha_spider.cc spd_udf.def
spd_db_mysql.cc spd_db_handlersocket.cc spd_db_oracle.cc
hs_client/config.cpp hs_client/escape.cpp hs_client/fatal.cpp
hs_client/hstcpcli.cpp hs_client/socket.cpp hs_client/string_util.cpp
)
IF(DEFINED ENV{ORACLE_HOME})
SET(ORACLE_HOME $ENV{ORACLE_HOME})
FIND_PATH(ORACLE_INCLUDE_DIR oci.h PATHS ${ORACLE_HOME}/rdbms/public)
SET(ORACLE_OCI_LIB_NAME clntsh)
SET(ORACLE_LIB_DIR ${ORACLE_HOME}/lib)
FIND_LIBRARY(ORACLE_OCI_LIBRARY NAMES ${ORACLE_OCI_LIB_NAME} PATHS ${ORACLE_LIB_DIR})
ENDIF()
IF(EXISTS ${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake)
SET(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
SET(CMAKE_C_FLAGS_DEBUG
"${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /MAP /MAPINFO:EXPORTS")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql
${CMAKE_SOURCE_DIR}/regex)
MYSQL_STORAGE_ENGINE(SPIDER)
ELSE()
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/storage/spider/hs_client
${ORACLE_INCLUDE_DIR})
SET(SPIDER_DEB_FILES "usr/lib/mysql/plugin/ha_spider.so" PARENT_SCOPE)
MYSQL_ADD_PLUGIN(spider ${SPIDER_SOURCES} STORAGE_ENGINE MODULE_ONLY MODULE_OUTPUT_NAME "ha_spider")
ENDIF()
IF(ORACLE_INCLUDE_DIR AND ORACLE_OCI_LIBRARY)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_ORACLE_OCI -DLINUX -D_GNU_SOURCE -D_REENTRANT")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_ORACLE_OCI -DLINUX -D_GNU_SOURCE -D_REENTRANT")
TARGET_LINK_LIBRARIES (spider ${ORACLE_OCI_LIBRARY})
ENDIF()
HAVE_HANDLERSOCKET = "-DHAVE_HANDLERSOCKET"
pkgplugindir = $(pkglibdir)/plugin
INCLUDES = -I$(SPD_MYSQL_INC)$(top_srcdir)/include \
-I$(SPD_MYSQL_INC)$(top_srcdir)/regex \
-I$(SPD_MYSQL_INC)$(top_srcdir)/sql \
-I$(SPD_MYSQL_INC)$(top_srcdir)/extra/yassl/include \
-I./hs_client \
$(MYSQL_INCLUDE_PATH) \
$(HANDLERSOCKET_INCLUDE_PATH)
noinst_HEADERS = ha_spider.h spd_conn.h spd_db_conn.h \
spd_db_include.h spd_err.h spd_sys_table.h \
spd_table.h spd_trx.h spd_include.h spd_param.h \
spd_direct_sql.h spd_udf.h spd_ping_table.h \
spd_copy_tables.h spd_malloc.h \
spd_db_mysql.h spd_db_handlersocket.h \
hs_client/allocator.hpp hs_client/config.hpp \
hs_client/mutex.hpp hs_client/string_util.hpp \
hs_client/auto_addrinfo.hpp hs_client/escape.hpp \
hs_client/socket.hpp hs_client/thread.hpp \
hs_client/auto_file.hpp hs_client/fatal.hpp \
hs_client/string_buffer.hpp hs_client/util.hpp \
hs_client/auto_ptrcontainer.hpp \
hs_client/hstcpcli.hpp hs_client/string_ref.hpp \
hs_client/hs_compat.h
lib_LTLIBRARIES = $(PLUGIN_SPIDER_LTLIBRARIES_TARGET)
EXTRA_LTLIBRARIES = ha_spider.la
pkgplugin_LTLIBRARIES = @plugin_spider_shared_target@
ha_spider_la_LDFLAGS = -shared -module -rpath $(pkgplugindir)
ha_spider_la_CXXFLAGS = $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN \
$(HAVE_HANDLERSOCKET)
ha_spider_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN \
$(HAVE_HANDLERSOCKET)
ha_spider_la_SOURCES = \
spd_param.cc \
spd_sys_table.cc \
spd_trx.cc \
spd_db_conn.cc \
spd_conn.cc \
spd_table.cc \
spd_direct_sql.cc \
spd_udf.cc \
spd_ping_table.cc \
spd_copy_tables.cc \
spd_i_s.cc \
spd_malloc.cc \
ha_spider.cc \
spd_db_mysql.cc \
spd_db_handlersocket.cc \
hs_client/config.cpp \
hs_client/escape.cpp \
hs_client/fatal.cpp \
hs_client/hstcpcli.cpp \
hs_client/socket.cpp \
hs_client/string_util.cpp
lib_LIBRARIES = $(PLUGIN_SPIDER_LIBRARIES_TARGET)
EXTRA_LIBRARIES = libspider.a
noinst_LIBRARIES = @plugin_spider_static_target@
libspider_a_CXXFLAGS = $(AM_CXXFLAGS) $(HAVE_HANDLERSOCKET)
libspider_a_CFLAGS = $(AM_CFLAGS) $(HAVE_HANDLERSOCKET)
libspider_a_SOURCES = \
spd_param.cc \
spd_sys_table.cc \
spd_trx.cc \
spd_db_conn.cc \
spd_conn.cc \
spd_table.cc \
spd_direct_sql.cc \
spd_udf.cc \
spd_ping_table.cc \
spd_copy_tables.cc \
spd_i_s.cc \
spd_malloc.cc \
ha_spider.cc \
spd_db_mysql.cc \
spd_db_handlersocket.cc \
hs_client/config.cpp \
hs_client/escape.cpp \
hs_client/fatal.cpp \
hs_client/hstcpcli.cpp \
hs_client/socket.cpp \
hs_client/string_util.cpp
EXTRA_DIST = plug.in
# Don't update the files from bitkeeper
%::SCCS/s.%
AC_INIT([spider_engine], [1.0], [kentokushiba@gmail.com])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_PROG_CXX
AC_PROG_LIBTOOL
AC_TYPE_SIZE_T
AC_DEFUN([MYSQL_PATH_TEST],[
AC_MSG_CHECKING([mysql source path])
AC_ARG_WITH([mysql],
[AS_HELP_STRING([--with-mysql=PATH],[mysql source directory PATH])],
[
if test \
-f $withval/include/mysql/plugin.h -a \
-f $withval/include/mysql.h -a \
-f $withval/include/errmsg.h -a \
\( -f $withval/sql/mysql_priv.h -o -f $withval/sql/sql_priv.h \) ;
then
SPD_MYSQL_INC="$withval/"
AC_MSG_RESULT([yes])
plugin_spider_shared_target=""
AC_SUBST(plugin_spider_shared_target)
plugin_spider_static_target=""
AC_SUBST(plugin_spider_static_target)
PLUGIN_SPIDER_LTLIBRARIES_TARGET="ha_spider.la"
AC_SUBST(PLUGIN_SPIDER_LTLIBRARIES_TARGET)
PLUGIN_SPIDER_LIBRARIES_TARGET="libspider.a"
AC_SUBST(PLUGIN_SPIDER_LIBRARIES_TARGET)
LIBTOOL="$LIBTOOL --preserve-dup-deps"
AC_SUBST(LIBTOOL)
else
AC_MSG_ERROR([Can't find header files. Please check --with-mysql=PATH option])
fi
],
[
if test \
-f ../../include/mysql/plugin.h -a \
-f ../../include/mysql.h -a \
-f ../../include/errmsg.h -a \
\( -f ../../sql/mysql_priv.h -o ../../sql/sql_priv.h \) ;
then
SPD_MYSQL_INC="../../"
AC_MSG_RESULT([no])
else
AC_MSG_ERROR([Can't find header files. Please set --with-mysql=PATH option])
fi
]
)
])
MYSQL_PATH_TEST
AC_SUBST(SPD_MYSQL_INC)
AC_DEFUN([MYSQL_INCLUDE_PATH_TEST],[
AC_MSG_CHECKING([mysql include path])
AC_ARG_WITH([mysql-include],
[AS_HELP_STRING([--with-mysql-include=PATH],[mysql include directory PATH])],
[
if test \
-f $withval/mysql_version.h -a \
-f $withval/my_config.h ;
then
MYSQL_INCLUDE_PATH="-I $withval/"
AC_MSG_RESULT([yes])
else
AC_MSG_ERROR([Can't find "my_config.h". Please check --with-mysql-include=PATH option])
fi
],
[
if test \
-f ../../include/mysql_version.h -a \
-f ../../include/my_config.h ;
then
MYSQL_INCLUDE_PATH="-I ../../include/"
AC_MSG_RESULT([no])
else
AC_MSG_ERROR([Can't find "my_config.h". Please set --with-mysql-include=PATH option])
fi
]
)
])
MYSQL_INCLUDE_PATH_TEST
AC_SUBST(MYSQL_INCLUDE_PATH)
CXXFLAGS="$CXXFLAGS -fno-implicit-templates -fno-exceptions -fno-rtti"
AC_CHECK_FUNCS([memset strchr strncasecmp])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
This diff is collapsed.
This diff is collapsed.
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_ALLOCATOR_HPP
#define DENA_ALLOCATOR_HPP
#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)
#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)
#endif
#if 1
#define DENA_ALLOCA_ALLOCATE(typ, len) \
static_cast<typ *>(alloca((len) * sizeof(typ)))
#define DENA_ALLOCA_FREE(x)
#else
#define DENA_ALLOCA_ALLOCATE(typ, len) \
static_cast<typ *>(malloc((len) * sizeof(typ)))
#define DENA_ALLOCA_FREE(x) free(x)
#endif
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_AUTO_ADDRINFO_HPP
#define DENA_AUTO_ADDRINFO_HPP
#ifndef __WIN__
#include <netdb.h>
#endif
#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;
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
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_AUTO_FILE_HPP
#define DENA_AUTO_FILE_HPP
/*
#ifndef __WIN__
#include <dirent.h>
#endif
*/
#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
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* 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
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#endif
#include "config.hpp"
namespace dena {
unsigned int verbose_level = 0;
uchar *
conf_get_key(
conf_param *param,
size_t *length,
my_bool not_used __attribute__ ((unused))
) {
*length = param->key.length();
return (uchar*) param->key.ptr();
}
config::config()
{
if (my_hash_init(&conf_hash, &my_charset_bin, 32, 0, 0,
(my_hash_get_key) conf_get_key, 0, 0))
init = FALSE;
else
init = TRUE;
return;
}
config::~config()
{
if (init)
{
conf_param *param;
while ((param = (conf_param *) my_hash_element(&conf_hash, 0)))
{
my_hash_delete(&conf_hash, (uchar*) param);
delete param;
}
my_hash_free(&conf_hash);
}
}
conf_param *
config::find(const String& key) const
{
if (init)
return (conf_param *) my_hash_search(&conf_hash, (const uchar*) key.ptr(),
key.length());
else
return NULL;
}
conf_param *
config::find(const char *key) const
{
if (init)
return (conf_param *) my_hash_search(&conf_hash, (const uchar*) key,
strlen(key));
else
return NULL;
}
String
config::get_str(const String& key, const String& def) const
{
DENA_VERBOSE(30, list_all_params());
conf_param *param = find(key);
if (!param) {
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s(default)\n", key.ptr(),
def.ptr()));
return def;
}
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s\n", key.ptr(),
param->val.ptr()));
return param->val;
}
String
config::get_str(const char *key, const char *def) const
{
DENA_VERBOSE(30, list_all_params());
conf_param *param = find(key);
if (!param) {
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s(default)\n", key, def));
return String(def, strlen(def), &my_charset_bin);
}
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s\n",
key, param->val.ptr()));
return param->val;
}
long long
config::get_int(const String& key, long long def) const
{
int err;
DENA_VERBOSE(30, list_all_params());
conf_param *param = find(key);
if (!param) {
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld(default)\n", key.ptr(),
def));
return def;
}
const long long r = my_strtoll10(param->val.ptr(), (char**) NULL, &err);
if (err) {
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld(err)\n", key.ptr(),
def));
return def;
}
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld\n", key.ptr(), r));
return r;
}
long long
config::get_int(const char *key, long long def) const
{
int err;
DENA_VERBOSE(30, list_all_params());
conf_param *param = find(key);
if (!param) {
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld(default)\n", key, def));
return def;
}
const long long r = my_strtoll10(param->val.ptr(), (char**) NULL, &err);
if (err) {
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld(err)\n", key, def));
return def;
}
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%lld\n", key, r));
return r;
}
bool
config::replace(const char *key, const char *val)
{
uint32 val_len = strlen(val);
conf_param *param = find(key);
if (!param) {
/* create */
if (!(param = new conf_param()))
return TRUE;
uint32 key_len = strlen(key);
if (
param->key.reserve(key_len + 1) ||
param->val.reserve(val_len + 1)
) {
delete param;
return TRUE;
}
param->key.q_append(key, key_len);
param->val.q_append(val, val_len);
param->key.c_ptr_safe();
param->val.c_ptr_safe();
if (my_hash_insert(&conf_hash, (uchar*) param))
{
delete param;
return TRUE;
}
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s(create)\n",
param->key.ptr(), param->val.ptr()));
return FALSE;
}
/* replace */
param->val.length(0);
if (param->val.reserve(val_len + 1))
return TRUE;
param->val.q_append(val, val_len);
param->val.c_ptr_safe();
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s(replace)\n",
param->key.ptr(), param->val.ptr()));
return FALSE;
}
bool
config::replace(const char *key, long long val)
{
char val_str[22];
sprintf(val_str, "%lld", val);
return replace(key, val_str);
}
bool
config::compare(const char *key, const char *val)
{
conf_param *param = find(key);
if (!param)
return FALSE;
return !strcmp(param->val.ptr(), val);
}
void
config::list_all_params() const
{
conf_param *param;
DENA_VERBOSE(10, fprintf(stderr, "list_all_params start\n"));
for(ulong i = 0; i < conf_hash.records; i++)
{
if ((param = (conf_param *) my_hash_element((HASH *) &conf_hash, i)))
{
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s\n",
param->key.ptr(), param->val.ptr()));
}
}
DENA_VERBOSE(10, fprintf(stderr, "list_all_params end\n"));
}
config&
config::operator =(const config& x)
{
DENA_VERBOSE(10, fprintf(stderr, "config operator = start"));
if (this != &x && init && x.init) {
conf_param *param, *new_param;
for(ulong i = 0; i < x.conf_hash.records; i++)
{
if (
(param = (conf_param *) my_hash_element((HASH *) &x.conf_hash, i)) &&
(new_param = new conf_param())
) {
if (
!new_param->key.copy(param->key) &&
!new_param->val.copy(param->val)
) {
new_param->key.c_ptr_safe();
new_param->val.c_ptr_safe();
DENA_VERBOSE(10, fprintf(stderr, "CONFIG: %s=%s\n",
new_param->key.ptr(), new_param->val.ptr()));
if (my_hash_insert(&conf_hash, (uchar*) new_param))
delete new_param;
} else
delete new_param;
}
}
}
DENA_VERBOSE(10, fprintf(stderr, "config operator = end %p", this));
return *this;
}
void
parse_args(int argc, char **argv, config& conf)
{
conf_param *param;
for (int i = 1; i < argc; ++i) {
const char *const arg = argv[i];
const char *const eq = strchr(arg, '=');
if (eq == 0) {
continue;
}
if (!(param = new conf_param()))
continue;
uint32 key_len = eq - arg;
uint32 val_len = strlen(eq + 1);
if (
param->key.reserve(key_len + 1) ||
param->val.reserve(val_len + 1)
) {
delete param;
continue;
}
param->key.q_append(arg, key_len);
param->val.q_append(eq + 1, val_len);
param->key.c_ptr_safe();
param->val.c_ptr_safe();
if (my_hash_insert(&conf.conf_hash, (uchar*) param))
{
delete param;
continue;
}
}
param = conf.find("verbose");
if (param) {
verbose_level = atoi(param->val.c_ptr());
}
}
};
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_CONFIG_HPP
#define DENA_CONFIG_HPP
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#include "sql_class.h"
#endif
#define DENA_VERBOSE(lv, x) if (dena::verbose_level >= (lv)) { (x); }
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
#define INFO_KIND_HS_RET_FIELDS 1
#define INFO_KIND_HS_APPEND_STRING_REF 3
#define INFO_KIND_HS_CLEAR_STRING_REF 4
#define INFO_KIND_HS_INCREMENT_BEGIN 5
#define INFO_KIND_HS_INCREMENT_END 6
#define INFO_KIND_HS_DECREMENT_BEGIN 7
#define INFO_KIND_HS_DECREMENT_END 8
#endif
namespace dena {
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
struct uint32_info {
size_t info_size;
uint32 *info;
};
#endif
struct conf_param {
String key;
String val;
};
uchar *conf_get_key(
conf_param *share,
size_t *length,
my_bool not_used __attribute__ ((unused))
);
struct config {
bool init;
HASH conf_hash;
config();
~config();
conf_param *find(const String& key) const;
conf_param *find(const char *key) const;
String get_str(const String& key, const String& def =
String("", &my_charset_bin)) const;
String get_str(const char *key, const char *def = "") const;
long long get_int(const String& key, long long def = 0) const;
long long get_int(const char *key, long long def = 0) const;
bool replace(const char *key, const char *val);
bool replace(const char *key, long long val);
bool compare(const char *key, const char *val);
void list_all_params() const;
config& operator =(const config& x);
};
void parse_args(int argc, char **argv, config& conf);
extern unsigned int verbose_level;
};
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
* See COPYRIGHT.txt for details.
*/
#include "mysql_version.h"
#include "hs_compat.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
read_ui32(char *& start, char *finish)
{
char *const n_begin = start;
read_token(start, finish);
char *const n_end = start;
uint32 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 v)
{
char *wp = buf.make_space(12);
int len = snprintf(wp, 12, "%u", v);
if (len > 0) {
buf.space_wrote(len);
}
}
void
write_ui64(string_buffer& buf, uint64 v)
{
char *wp = buf.make_space(22);
int len = snprintf(wp, 22, "%llu", static_cast<unsigned long long>(v));
if (len > 0) {
buf.space_wrote(len);
}
}
};
// vim:sw=2:ai
/*
* Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
* See COPYRIGHT.txt for details.
*/
#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 read_ui32(char *& start, char *finish);
void write_ui32(string_buffer& buf, uint32 v);
void write_ui64(string_buffer& buf, uint64 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
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#endif
#include "fatal.hpp"
namespace dena {
/*
const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS;
*/
void
fatal_exit(const String& message)
{
fprintf(stderr, "FATAL_EXIT: %s\n", message.ptr());
/*
syslog(opt_syslog, "FATAL_EXIT: %s", message.ptr());
*/
_exit(1);
}
void
fatal_exit(const char *message)
{
fprintf(stderr, "FATAL_EXIT: %s\n", message);
/*
syslog(opt_syslog, "FATAL_EXIT: %s", message);
*/
_exit(1);
}
void
fatal_abort(const String& message)
{
fprintf(stderr, "FATAL_COREDUMP: %s\n", message.ptr());
/*
syslog(opt_syslog, "FATAL_COREDUMP: %s", message.ptr());
*/
abort();
}
void
fatal_abort(const char *message)
{
fprintf(stderr, "FATAL_COREDUMP: %s\n", message);
/*
syslog(opt_syslog, "FATAL_COREDUMP: %s", message);
*/
abort();
}
};
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_FATAL_HPP
#define DENA_FATAL_HPP
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#include "sql_class.h"
#endif
namespace dena {
void fatal_exit(const String& message);
void fatal_exit(const char *message);
void fatal_abort(const String& message);
void fatal_abort(const char *message);
};
#endif
/* Copyright (C) 2013 Kentoku Shiba
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef HS_COMPAT_H
#define HS_COMPAT_H
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000
#define SPD_INIT_DYNAMIC_ARRAY2(A, B, C, D, E, F) \
my_init_dynamic_array2(A, B, C, D, E, F)
#define SPD_INIT_ALLOC_ROOT(A, B, C, D) \
init_alloc_root(A, B, C, D)
#else
#define SPD_INIT_DYNAMIC_ARRAY2(A, B, C, D, E, F) \
my_init_dynamic_array2(A, B, C, D, E)
#define SPD_INIT_ALLOC_ROOT(A, B, C, D) \
init_alloc_root(A, B, C)
#endif
#endif
This diff is collapsed.
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_HSTCPCLI_HPP
#define DENA_HSTCPCLI_HPP
#define HANDLERSOCKET_MYSQL_UTIL 1
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#endif
#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 hstcpcli_i *hstcpcli_ptr;
struct hstresult {
hstresult();
virtual ~hstresult();
string_buffer readbuf;
size_t response_end_offset;
size_t num_flds;
size_t cur_row_offset;
DYNAMIC_ARRAY flds;
};
struct hstcpcli_i {
virtual ~hstcpcli_i() { }
virtual void close() = 0;
virtual int reconnect() = 0;
virtual bool stable_point() = 0;
virtual void request_buf_auth(const char *secret, const char *typ) = 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 limit, uint32 skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
const hstcpcli_filter *fils = 0, size_t filslen = 0,
int invalues_keypart = -1, const string_ref *invalues = 0,
size_t invalueslen = 0) = 0; // FIXME: too long
virtual size_t request_buf_append(const char *start, const char *finish) = 0;
virtual void request_reset() = 0;
virtual int request_send() = 0;
virtual int response_recv(size_t& num_flds_r) = 0;
virtual int get_result(hstresult& result) = 0;
virtual const string_ref *get_next_row() = 0;
virtual const string_ref *get_next_row_from_result(hstresult& result) = 0;
virtual void response_buf_remove() = 0;
virtual int get_error_code() = 0;
virtual String& get_error() = 0;
virtual void clear_error() = 0;
virtual int set_timeout(int send_timeout, int recv_timeout) = 0;
virtual size_t get_num_req_bufd() = 0;
virtual size_t get_num_req_sent() = 0;
virtual size_t get_num_req_rcvd() = 0;
virtual size_t get_response_end_offset() = 0;
virtual const char *get_readbuf_begin() = 0;
virtual const char *get_readbuf_end() = 0;
virtual void write_error_to_log(const char *func_name, const char *file_name,
ulong line_no) = 0;
static hstcpcli_ptr create(const socket_args& args);
};
};
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_MUTEX_HPP
#define DENA_MUTEX_HPP
#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
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef __WIN__
#include <sys/un.h>
#endif
#include "mysql_version.h"
#include "hs_compat.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000
#include <my_global.h>
#endif
#include "sql_priv.h"
#include "probes_mysql.h"
#endif
#include "socket.hpp"
#include "string_util.hpp"
#include "fatal.hpp"
/*
struct sockaddr_un {
short sun_family;
char sun_path[108];
};
*/
namespace dena {
void
ignore_sigpipe()
{
#if defined(SIGPIPE) && !defined(__WIN__)
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
fatal_abort("SIGPIPE SIG_IGN");
}
#endif
}
void
socket_args::set(const config& conf)
{
timeout = (int) conf.get_int("timeout", 600);
listen_backlog = (int) conf.get_int("listen_backlog", 256);
String node = conf.get_str("host", "");
String port = conf.get_str("port", "");
if (node.length() || port.length()) {
if (family == AF_UNIX || !strcmp(node.c_ptr(), "/")) {
set_unix_domain(port.c_ptr());
} else {
const char *nd = !node.length() ? 0 : node.c_ptr();
if (resolve(nd, port.c_ptr()) != 0) {
String message("getaddrinfo failed: ", &my_charset_bin);
message.reserve(node.length() + sizeof(":") - 1 + port.length());
message.append(node);
message.q_append(":", sizeof(":") - 1);
message.append(port);
fatal_exit(message);
}
}
}
sndbuf = (int) conf.get_int("sndbuf", 0);
rcvbuf = (int) conf.get_int("rcvbuf", 0);
}
void
socket_args::set_unix_domain(const char *path)
{
#ifndef __WIN__
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);
#endif
}
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_timeout(auto_file& fd, const socket_args& args, String& err_r)
{
if (!args.nonblocking) {
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
if (args.recv_timeout != 0) {
#ifndef __WIN__
struct timeval tv;
tv.tv_sec = args.recv_timeout;
tv.tv_usec = 0;
#else
int tv = args.recv_timeout * 1000;
#endif
if (setsockopt(fd.get(), SOL_SOCKET, SO_RCVTIMEO,
#ifndef __WIN__
(const void *) &tv,
#else
(const char *) &tv,
#endif
sizeof(tv)) != 0) {
return errno_string("setsockopt SO_RCVTIMEO", errno, err_r);
}
}
if (args.send_timeout != 0) {
#ifndef __WIN__
struct timeval tv;
tv.tv_sec = args.send_timeout;
tv.tv_usec = 0;
#else
int tv = args.send_timeout * 1000;
#endif
if (setsockopt(fd.get(), SOL_SOCKET, SO_SNDTIMEO,
#ifndef __WIN__
(const void *) &tv,
#else
(const char *) &tv,
#endif
sizeof(tv)) != 0) {
return errno_string("setsockopt SO_SNDTIMEO", errno, err_r);
}
}
#endif
}
return 0;
}
int
socket_set_options(auto_file& fd, const socket_args& args, String& err_r)
{
if (args.timeout != 0 && !args.nonblocking) {
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
#ifndef __WIN__
struct timeval tv;
tv.tv_sec = args.timeout;
tv.tv_usec = 0;
#else
int tv = args.timeout * 1000;
#endif
if (setsockopt(fd.get(), SOL_SOCKET, SO_RCVTIMEO,
#ifndef __WIN__
(const void *) &tv,
#else
(const char *) &tv,
#endif
sizeof(tv)) != 0) {
return errno_string("setsockopt SO_RCVTIMEO", errno, err_r);
}
#ifndef __WIN__
tv.tv_sec = args.timeout;
tv.tv_usec = 0;
#else
tv = args.timeout * 1000;
#endif
if (setsockopt(fd.get(), SOL_SOCKET, SO_SNDTIMEO,
#ifndef __WIN__
(const void *) &tv,
#else
(const char *) &tv,
#endif
sizeof(tv)) != 0) {
return errno_string("setsockopt SO_RCVTIMEO", errno, err_r);
}
#endif
}
#ifndef __WIN__
if (args.nonblocking && fcntl(fd.get(), F_SETFL, O_NONBLOCK) != 0) {
return errno_string("fcntl O_NONBLOCK", errno, err_r);
}
#endif
if (args.sndbuf != 0) {
const int v = args.sndbuf;
if (setsockopt(fd.get(), SOL_SOCKET, SO_SNDBUF,
#ifndef __WIN__
(const void *) &v,
#else
(const char *) &v,
#endif
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,
#ifndef __WIN__
(const void *) &v,
#else
(const char *) &v,
#endif
sizeof(v)) != 0) {
return errno_string("setsockopt SO_RCVBUF", errno, err_r);
}
}
return 0;
}
int
socket_open(auto_file& fd, const socket_args& args, 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, 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
#ifndef __WIN__
|| errno != EINPROGRESS
#endif
) {
return errno_string("connect", errno, err_r);
}
}
return 0;
}
int
socket_bind(auto_file& fd, const socket_args& args, 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) {
#ifndef __WIN__
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 {
#endif
int v = 1;
if (setsockopt(fd.get(), SOL_SOCKET, SO_REUSEADDR,
#ifndef __WIN__
(const void *) &v,
#else
(const char *) &v,
#endif
sizeof(v)) != 0) {
return errno_string("setsockopt SO_REUSEADDR", errno, err_r);
}
#ifndef __WIN__
}
#endif
}
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);
}
#ifndef __WIN__
if (args.nonblocking && fcntl(fd.get(), F_SETFL, O_NONBLOCK) != 0) {
return errno_string("fcntl O_NONBLOCK", errno, err_r);
}
#endif
return 0;
}
int
socket_accept(int listen_fd, auto_file& fd, const socket_args& args,
sockaddr_storage& addr_r, socklen_t& addrlen_r, 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);
}
};
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_SOCKET_HPP
#define DENA_SOCKET_HPP
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#endif
#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 send_timeout;
int recv_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), send_timeout(600), recv_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_set_timeout(auto_file& fd, const socket_args& args, String& err_r);
int socket_bind(auto_file& fd, const socket_args& args, String& err_r);
int socket_connect(auto_file& fd, const socket_args& args, String& err_r);
int socket_accept(int listen_fd, auto_file& fd, const socket_args& args,
sockaddr_storage& addr_r, socklen_t& addrlen_r, String& err_r);
};
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_STRING_BUFFER_HPP
#define DENA_STRING_BUFFER_HPP
/*
#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() {
real_free();
}
void real_free() {
if (alloc_size) {
DENA_FREE(buffer);
buffer = 0;
begin_offset = 0;
end_offset = 0;
alloc_size = 0;
}
}
size_t real_size() {
return alloc_size;
}
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 = len < alloc_size - end_offset ? len : alloc_size - end_offset;
end_offset += len;
}
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;
}
void swap(string_buffer& sb) {
char *tmp_buffer = buffer;
size_t tmp_begin_offset = begin_offset;
size_t tmp_end_offset = end_offset;
size_t tmp_alloc_size = alloc_size;
buffer = sb.buffer;
begin_offset = sb.begin_offset;
end_offset = sb.end_offset;
alloc_size = sb.alloc_size;
sb.buffer = tmp_buffer;
sb.begin_offset = tmp_begin_offset;
sb.end_offset = tmp_end_offset;
sb.alloc_size = tmp_alloc_size;
}
private:
char *buffer;
size_t begin_offset;
size_t end_offset;
size_t alloc_size;
};
};
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_STRING_REF_HPP
#define DENA_STRING_REF_HPP
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; }
void set(const char *s, size_t len) { start = s; length = len; }
void set(const char *s, const char *f) { start = s; length = f - s; }
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);
}
struct string_ref_list_wrap {
string_ref_list_wrap() {
if (SPD_INIT_DYNAMIC_ARRAY2(&string_ref_list, sizeof(string_ref),
NULL, 16, 16, MYF(MY_WME)))
string_ref_list_init = FALSE;
else
string_ref_list_init = TRUE;
}
virtual ~string_ref_list_wrap() {
if (string_ref_list_init) delete_dynamic(&string_ref_list); }
void clear() {
if (string_ref_list_init) string_ref_list.elements = 0; }
void push_back(string_ref &e) {
if (string_ref_list_init) insert_dynamic(&string_ref_list, (uchar*) &e);
return; }
size_t size() {
return string_ref_list_init ? string_ref_list.elements : 0; }
bool resize(size_t new_size) {
if (string_ref_list_init) {
if (string_ref_list.max_element < new_size && allocate_dynamic(
&string_ref_list, new_size)) return TRUE;
string_ref_list.elements = new_size;
return FALSE;
}
return TRUE;
}
bool empty() {
return string_ref_list_init ? string_ref_list.elements ?
FALSE : TRUE : TRUE; }
string_ref &operator [](size_t n) {
return ((string_ref *) (string_ref_list.buffer +
string_ref_list.size_of_element * n))[0]; }
bool string_ref_list_init;
DYNAMIC_ARRAY string_ref_list;
};
inline String *
q_append_str(String *str, const char *p) {
uint32 p_len = strlen(p);
if (str->reserve(p_len)) return NULL;
str->q_append(p, p_len); return str;
}
};
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#include "mysql_version.h"
#include "hs_compat.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
#include <mysql/plugin.h>
#else
#include "sql_priv.h"
#include "probes_mysql.h"
#endif
#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);
}
uint32
atoi_uint32_nocheck(const char *start, const char *finish)
{
uint32 v = 0;
for (; start != finish; ++start) {
const char c = *start;
if (c < '0' || c > '9') {
break;
}
v *= 10;
v += (uint32) (c - '0');
}
return v;
}
long long
atoll_nocheck(const char *start, const char *finish)
{
long long 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 -= (long long) (c - '0');
} else {
v += (long long) (c - '0');
}
}
return v;
}
void
append_uint32(string_buffer& buf, uint32 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);
}
}
/*
String *
to_stdstring(uint32 v)
{
char buf[64];
int str_len;
String *str;
str_len = snprintf(buf, sizeof(buf), "%lu", static_cast<unsigned long>(v));
if ((str = new String(str_len + 1)))
str->q_append(buf, str_len);
return str;
}
*/
int
errno_string(const char *s, int en, String& err_r)
{
char buf[64];
int str_len;
str_len = snprintf(buf, sizeof(buf), "%s: %d", s, en);
if (!err_r.reserve(str_len + 1))
err_r.q_append(buf, str_len);
return en;
}
size_t
split(char delim, const string_ref& buf, string_ref *parts,
size_t parts_len)
{
size_t i = 0;
const char *start = buf.begin();
const char *const finish = buf.end();
for (i = 0; i < parts_len; ++i) {
const char *const p = memchr_char(start, delim, finish - start);
if (p == 0) {
parts[i] = string_ref(start, finish - start);
++i;
break;
}
parts[i] = string_ref(start, p - start);
start = p + 1;
}
const size_t r = i;
for (; i < parts_len; ++i) {
parts[i] = string_ref();
}
return r;
}
size_t
split(char delim, const string_wref& buf, string_wref *parts,
size_t parts_len)
{
size_t i = 0;
char *start = buf.begin();
char *const finish = buf.end();
for (i = 0; i < parts_len; ++i) {
char *const p = memchr_char(start, delim, finish - start);
if (p == 0) {
parts[i] = string_wref(start, finish - start);
++i;
break;
}
parts[i] = string_wref(start, p - start);
start = p + 1;
}
const size_t r = i;
for (; i < parts_len; ++i) {
parts[i] = string_wref();
}
return r;
}
size_t
split(char delim, const string_ref& buf, DYNAMIC_ARRAY& parts_r)
{
size_t i = 0;
const char *start = buf.begin();
const char *finish = buf.end();
while (true) {
const char *p = memchr_char(start, delim, finish - start);
if (p == 0) {
string_ref param(start, finish - start);
insert_dynamic(&parts_r, (uchar *) &param);
break;
}
string_ref param(start, p - start);
insert_dynamic(&parts_r, (uchar *) &param);
start = p + 1;
}
const size_t r = i;
return r;
}
size_t
split(char delim, const string_wref& buf, DYNAMIC_ARRAY& parts_r)
{
size_t i = 0;
char *start = buf.begin();
char *finish = buf.end();
while (true) {
char *p = memchr_char(start, delim, finish - start);
if (p == 0) {
string_wref param(start, finish - start);
insert_dynamic(&parts_r, (uchar *) &param);
break;
}
string_wref param(start, p - start);
insert_dynamic(&parts_r, (uchar *) &param);
start = p + 1;
}
const size_t r = i;
return r;
}
};
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_STRING_UTIL_HPP
#define DENA_STRING_UTIL_HPP
#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 atoi_uint32_nocheck(const char *start, const char *finish);
/*
String *to_stdstring(uint32 v);
*/
void append_uint32(string_buffer& buf, uint32 v);
long long atoll_nocheck(const char *start, const char *finish);
int errno_string(const char *s, int en, 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,
DYNAMIC_ARRAY& parts_r);
size_t split(char delim, const string_wref& buf,
DYNAMIC_ARRAY& parts_r);
};
#endif
// vim:sw=2:ai
/*
* Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
* Copyright (C) 2011 Kentoku SHIBA
* See COPYRIGHT.txt for details.
*/
#ifndef DENA_THREAD_HPP
#define DENA_THREAD_HPP
#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;
}
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;
}
need_join = true;
return need_join;
}
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
// 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
let $CHILD2_1_HA_AS_DROP_TABLES=
$CHILD2_1_DROP_TABLES;
let $CHILD2_1_HA_AS_CREATE_TABLES=
$CHILD2_1_CREATE_TABLES;
let $CHILD2_1_HA_AS_DROP_TABLES2=
$CHILD2_1_DROP_TABLES2;
let $CHILD2_1_HA_AS_CREATE_TABLES2=
$CHILD2_1_CREATE_TABLES2;
let $CHILD2_2_HA_DROP_TABLES=
$CHILD2_2_DROP_TABLES;
let $CHILD2_2_HA_CREATE_TABLES=
$CHILD2_2_CREATE_TABLES;
let $CHILD2_3_HA_DROP_TABLES=
$CHILD2_3_DROP_TABLES;
let $CHILD2_3_HA_CREATE_TABLES=
$CHILD2_3_CREATE_TABLES;
--let $CHILD3_1_ENGINE_TYPE=Spider
--let $CHILD3_1_ENGINE=ENGINE=Spider
--source ../../include/init_spider.inc
eval INSERT INTO mysql.spider_link_mon_servers
(db_name, table_name, link_id, sid, server, scheme, host, port, socket,
username, password, ssl_ca, ssl_capath, ssl_cert, ssl_cipher, ssl_key,
ssl_verify_server_cert, default_file, default_group) VALUES
('%auto_test_local%', '%ta_l%', '%', $CHILD3_1_SERVER_ID, 's_3_1', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_2_SERVER_ID, 's_3_2', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_3_SERVER_ID, 's_3_3', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
let $CHILD3_1_CHECK_LINK_STATUS=
SELECT db_name, table_name, link_id, link_status FROM mysql.spider_tables
ORDER BY db_name, table_name, link_id;
let $CHILD3_1_CHECK_LINK_FAILED_LOG=
SELECT db_name, table_name, link_id FROM mysql.spider_link_failed_log;
let $CHILD3_1_SET_RECOVERY_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 2"';
let $CHILD3_1_SET_OK_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 1"';
let $CHILD3_1_SET_OK_STATUS_AS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2", lst "1 0"';
let $CHILD3_1_DROP_TABLES_HA_2_1=
DROP TABLE IF EXISTS ta_l;
if ($VERSION_COMPILE_OS_WIN)
{
let $CHILD3_1_CREATE_TABLES_HA_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_1_ENGINE $CHILD3_1_CHARSET
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $CHILD3_1_CREATE_TABLES_HA_AS_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_1_ENGINE $CHILD3_1_CHARSET
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
if (!$VERSION_COMPILE_OS_WIN)
{
let $CHILD3_1_CREATE_TABLES_HA_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_1_ENGINE $CHILD3_1_CHARSET
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $CHILD3_1_CREATE_TABLES_HA_AS_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_1_ENGINE $CHILD3_1_CHARSET
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
let $CHILD3_1_DROP_TABLES_HA_P_2_1=
DROP TABLE IF EXISTS ta_l2;
let $CHILD3_1_CREATE_TABLES_HA_P_2_1=
CREATE TABLE ta_l2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_1_ENGINE $CHILD3_1_CHARSET
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $CHILD3_1_CREATE_TABLES_HA_AS_P_2_1=
CREATE TABLE ta_l2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_1_ENGINE $CHILD3_1_CHARSET
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $CHILD3_1_SET_RECOVERY_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 2"'
);
let $CHILD3_1_SET_OK_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 1"'
);
let $CHILD3_1_SET_OK_STATUS_AS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "1 0"'
);
--let $CHILD3_2_ENGINE_TYPE=Spider
--let $CHILD3_2_ENGINE=ENGINE=Spider
--source ../../include/init_spider.inc
eval INSERT INTO mysql.spider_link_mon_servers
(db_name, table_name, link_id, sid, server, scheme, host, port, socket,
username, password, ssl_ca, ssl_capath, ssl_cert, ssl_cipher, ssl_key,
ssl_verify_server_cert, default_file, default_group) VALUES
('%auto_test_local%', '%ta_l%', '%', $CHILD3_1_SERVER_ID, 's_3_1', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_2_SERVER_ID, 's_3_2', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_3_SERVER_ID, 's_3_3', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
let $CHILD3_2_CHECK_LINK_STATUS=
SELECT db_name, table_name, link_id, link_status FROM mysql.spider_tables
ORDER BY db_name, table_name, link_id;
let $CHILD3_2_CHECK_LINK_FAILED_LOG=
SELECT db_name, table_name, link_id FROM mysql.spider_link_failed_log;
let $CHILD3_2_SET_RECOVERY_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 2"';
let $CHILD3_2_SET_OK_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 1"';
let $CHILD3_2_SET_OK_STATUS_AS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2", lst "1 0"';
let $CHILD3_2_DROP_TABLES_HA_2_1=
DROP TABLE IF EXISTS ta_l;
if ($VERSION_COMPILE_OS_WIN)
{
let $CHILD3_2_CREATE_TABLES_HA_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_2_ENGINE $CHILD3_2_CHARSET
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $CHILD3_2_CREATE_TABLES_HA_AS_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_2_ENGINE $CHILD3_2_CHARSET
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
if (!$VERSION_COMPILE_OS_WIN)
{
let $CHILD3_2_CREATE_TABLES_HA_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_2_ENGINE $CHILD3_2_CHARSET
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $CHILD3_2_CREATE_TABLES_HA_AS_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_2_ENGINE $CHILD3_2_CHARSET
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
let $CHILD3_2_DROP_TABLES_HA_P_2_1=
DROP TABLE IF EXISTS ta_l2;
let $CHILD3_2_CREATE_TABLES_HA_P_2_1=
CREATE TABLE ta_l2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_2_ENGINE $CHILD3_2_CHARSET
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $CHILD3_2_CREATE_TABLES_HA_AS_P_2_1=
CREATE TABLE ta_l2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_2_ENGINE $CHILD3_2_CHARSET
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $CHILD3_2_SET_RECOVERY_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 2"'
);
let $CHILD3_2_SET_OK_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 1"'
);
let $CHILD3_2_SET_OK_STATUS_AS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "1 0"'
);
--let $CHILD3_3_ENGINE_TYPE=Spider
--let $CHILD3_3_ENGINE=ENGINE=Spider
--source ../../include/init_spider.inc
eval INSERT INTO mysql.spider_link_mon_servers
(db_name, table_name, link_id, sid, server, scheme, host, port, socket,
username, password, ssl_ca, ssl_capath, ssl_cert, ssl_cipher, ssl_key,
ssl_verify_server_cert, default_file, default_group) VALUES
('%auto_test_local%', '%ta_l%', '%', $CHILD3_1_SERVER_ID, 's_3_1', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_2_SERVER_ID, 's_3_2', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_3_SERVER_ID, 's_3_3', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
let $CHILD3_3_CHECK_LINK_STATUS=
SELECT db_name, table_name, link_id, link_status FROM mysql.spider_tables
ORDER BY db_name, table_name, link_id;
let $CHILD3_3_CHECK_LINK_FAILED_LOG=
SELECT db_name, table_name, link_id FROM mysql.spider_link_failed_log;
let $CHILD3_3_SET_RECOVERY_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 2"';
let $CHILD3_3_SET_OK_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 1"';
let $CHILD3_3_SET_OK_STATUS_AS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2", lst "1 0"';
let $CHILD3_3_DROP_TABLES_HA_2_1=
DROP TABLE IF EXISTS ta_l;
if ($VERSION_COMPILE_OS_WIN)
{
let $CHILD3_3_CREATE_TABLES_HA_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_3_ENGINE $CHILD3_3_CHARSET
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $CHILD3_3_CREATE_TABLES_HA_AS_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_3_ENGINE $CHILD3_3_CHARSET
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
if (!$VERSION_COMPILE_OS_WIN)
{
let $CHILD3_3_CREATE_TABLES_HA_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_3_ENGINE $CHILD3_3_CHARSET
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $CHILD3_3_CREATE_TABLES_HA_AS_2_1=
CREATE TABLE ta_l (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_3_ENGINE $CHILD3_3_CHARSET
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
let $CHILD3_3_DROP_TABLES_HA_P_2_1=
DROP TABLE IF EXISTS ta_l2;
let $CHILD3_3_CREATE_TABLES_HA_P_2_1=
CREATE TABLE ta_l2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_3_ENGINE $CHILD3_3_CHARSET
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $CHILD3_3_CREATE_TABLES_HA_AS_P_2_1=
CREATE TABLE ta_l2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD3_3_ENGINE $CHILD3_3_CHARSET
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $CHILD3_3_SET_RECOVERY_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 2"'
);
let $CHILD3_3_SET_OK_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 1"'
);
let $CHILD3_3_SET_OK_STATUS_AS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "1 0"'
);
eval INSERT INTO mysql.spider_link_mon_servers
(db_name, table_name, link_id, sid, server, scheme, host, port, socket,
username, password, ssl_ca, ssl_capath, ssl_cert, ssl_cipher, ssl_key,
ssl_verify_server_cert, default_file, default_group) VALUES
('%auto_test_local%', '%ta_l%', '%', $CHILD3_1_SERVER_ID, 's_3_1', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_2_SERVER_ID, 's_3_2', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL),
('%auto_test_local%', '%ta_l%', '%', $CHILD3_3_SERVER_ID, 's_3_3', NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
let $MASTER_1_CHECK_LINK_STATUS=
SELECT db_name, table_name, link_id, link_status FROM mysql.spider_tables
ORDER BY db_name, table_name, link_id;
let $MASTER_1_CHECK_LINK_FAILED_LOG=
SELECT db_name, table_name, link_id FROM mysql.spider_link_failed_log;
let $MASTER_1_SET_RECOVERY_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 2"';
let $MASTER_1_SET_OK_STATUS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2", lst "0 1"';
let $MASTER_1_SET_OK_STATUS_AS_2_1=
ALTER TABLE ta_l
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2", lst "1 0"';
let $MASTER_1_COPY_TABLES_2_1=
SELECT spider_copy_tables('ta_l', '0', '1');
if ($VERSION_COMPILE_OS_WIN)
{
let $MASTER_1_COMMENT_HA_2_1=
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $MASTER_1_COMMENT_HA_AS_2_1=
COMMENT='port "$CHILD2_1_MYPORT $CHILD2_2_MYPORT", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
if (!$VERSION_COMPILE_OS_WIN)
{
let $MASTER_1_COMMENT_HA_2_1=
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2",
database "auto_test_remote auto_test_remote2"';
let $MASTER_1_COMMENT_HA_AS_2_1=
COMMENT='socket "$CHILD2_1_MYSOCK $CHILD2_2_MYSOCK", table "ta_r ta_r3"'
CONNECTION='host "localhost", user "root", password "",
msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1",
database "auto_test_remote auto_test_remote2"';
}
let $MASTER_1_COMMENT_HA_P_2_1=
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $MASTER_1_COMMENT_HA_AS_P_2_1=
COMMENT='msi "$CHILD3_1_SERVER_ID", mkd "2", alc "1"'
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001"'
);
let $MASTER_1_SET_RECOVERY_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 2"'
);
let $MASTER_1_SET_OK_STATUS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "0 1"'
);
let $MASTER_1_SET_OK_STATUS_AS_P_2_1=
ALTER TABLE ta_l2
PARTITION BY KEY(a) (
PARTITION pt1 COMMENT='srv "s_2_1 s_2_2", tbl "ta_r ta_r3",
priority "1000"',
PARTITION pt2 COMMENT='srv "s_2_1 s_2_3", tbl "ta_r2 ta_r4",
priority "1000001", lst "1 0"'
);
let $MASTER_1_COPY_TABLES_P_2_1=
SELECT spider_copy_tables('ta_l2#P#pt2', '0', '1');
let $MASTER_1_CHECK_HA_STATUS=
SHOW STATUS LIKE 'Spider_mon_table_cache_version%';
let $MASTER_1_CHANGE_HA_MON=
SELECT spider_flush_table_mon_cache();
let $CHILD2_1_HS_DROP_TABLES=
DROP TABLE IF EXISTS hs_r;
let $CHILD2_1_HS_CREATE_TABLES=
CREATE TABLE hs_r (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
d INT DEFAULT 11,
PRIMARY KEY(a)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_HS_SELECT_TABLES=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s'), d FROM hs_r ORDER BY a;
let $CHILD2_1_HS_DROP_TABLES2=
DROP TABLE IF EXISTS hs_r2;
let $CHILD2_1_HS_CREATE_TABLES2=
CREATE TABLE hs_r2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
d INT DEFAULT 11,
PRIMARY KEY(a)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_HS_SELECT_TABLES2=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s'), d FROM hs_r2 ORDER BY a;
let $CHILD2_2_HS_DROP_TABLES=
DROP TABLE IF EXISTS hs_r3;
let $CHILD2_2_HS_CREATE_TABLES=
CREATE TABLE hs_r3 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
d INT DEFAULT 11,
PRIMARY KEY(a)
) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
let $CHILD2_2_HS_SELECT_TABLES=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s'), d FROM hs_r3 ORDER BY a;
let $MASTER_1_HS_COMMENT_TMP=
COMMENT='';
let $MASTER_1_HS_COMMENT_2_1=
COMMENT='srv "s_2_1", table "hs_r", uhr "1", uhw "1", hrp "$CHILD2_1_HSRPORT", hwp "$CHILD2_1_HSWPORT", hwr "0"';
let $MASTER_1_HS_COMMENT_P_2_1=
COMMENT='uhr "1", uhw "1", hwr "0"'
PARTITION BY RANGE(a) (
PARTITION pt1 VALUES LESS THAN (4)
COMMENT='srv "s_2_1", table "hs_r2", hrp "$CHILD2_1_HSRPORT", hwp "$CHILD2_1_HSWPORT"',
PARTITION pt2 VALUES LESS THAN MAXVALUE
COMMENT='srv "s_2_2", table "hs_r3", hrp "$CHILD2_2_HSRPORT", hwp "$CHILD2_2_HSWPORT"'
);
let $CHILD2_1_DROP_TABLES=
DROP TABLE IF EXISTS ta_r;
let $CHILD2_1_CREATE_TABLES=
CREATE TABLE ta_r (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a),
KEY idx1(b)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TABLES=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a;
let $CHILD2_1_DROP_TABLES2=
DROP TABLE IF EXISTS ta_r2;
let $CHILD2_1_CREATE_TABLES2=
CREATE TABLE ta_r2 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TABLES2=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r2 ORDER BY a;
let $CHILD2_1_DROP_TABLES3=
DROP TABLE IF EXISTS ta_r_no_idx;
let $CHILD2_1_CREATE_TABLES3=
CREATE TABLE ta_r_no_idx (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10'
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TABLES3=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r_no_idx ORDER BY a;
let $CHILD2_1_DROP_TABLES4=
DROP TABLE IF EXISTS ta_r_auto_inc;
let $CHILD2_1_CREATE_TABLES4=
CREATE TABLE ta_r_auto_inc (
a INT AUTO_INCREMENT,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TABLES4=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r_auto_inc
ORDER BY a;
let $CHILD2_1_DROP_TABLES5=
DROP TABLE IF EXISTS ta_r_int;
let $CHILD2_1_CREATE_TABLES5=
CREATE TABLE ta_r_int (
a INT AUTO_INCREMENT,
b INT DEFAULT 10,
c INT DEFAULT 11,
PRIMARY KEY(a),
KEY idx1(b),
KEY idx2(c)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TABLES5=
SELECT a, b, c FROM ta_r_int ORDER BY a;
let $CHILD2_1_DROP_TABLES6=
DROP TABLE IF EXISTS ta_r_3;
let $CHILD2_1_CREATE_TABLES6=
CREATE TABLE ta_r_3 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10'
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TABLES6=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r_3 ORDER BY a;
let $CHILD2_1_DROP_FT_TABLES=
DROP TABLE IF EXISTS ft_r;
let $CHILD2_1_CREATE_FT_TABLES=
CREATE TABLE ft_r (
a INT DEFAULT 0,
b TEXT,
c TEXT,
d TEXT,
PRIMARY KEY(a),
FULLTEXT INDEX ft_idx1(b),
FULLTEXT INDEX ft_idx2(c)
) $CHILD2_1_FT_ENGINE $CHILD2_1_FT_CHARSET;
let $CHILD2_1_SELECT_FT_TABLES=
SELECT a, b, c, d FROM ft_r ORDER BY a;
let $CHILD2_1_DROP_FT_TABLES2=
DROP TABLE IF EXISTS ft_r2;
let $CHILD2_1_CREATE_FT_TABLES2=
CREATE TABLE ft_r2 (
a INT DEFAULT 0,
b TEXT,
c TEXT,
d TEXT,
PRIMARY KEY(a),
FULLTEXT INDEX ft_idx1(b),
FULLTEXT INDEX ft_idx2(c)
) $CHILD2_1_FT_ENGINE $CHILD2_1_FT_CHARSET;
let $CHILD2_1_SELECT_FT_TABLES2=
SELECT a, b, c, d FROM ft_r2 ORDER BY a;
let $CHILD2_1_DROP_GM_TABLES=
DROP TABLE IF EXISTS gm_r;
let $CHILD2_1_CREATE_GM_TABLES=
CREATE TABLE gm_r (
a INT DEFAULT 0,
b GEOMETRY NOT NULL,
c GEOMETRY NOT NULL,
PRIMARY KEY(a),
SPATIAL INDEX sp_idx1(b),
SPATIAL INDEX sp_idx2(c)
) $CHILD2_1_GM_ENGINE $CHILD2_1_GM_CHARSET;
let $CHILD2_1_SELECT_GM_TABLES=
SELECT a, b, c FROM gm_r ORDER BY a;
let $CHILD2_1_DROP_GM_TABLES2=
DROP TABLE IF EXISTS gm_r2;
let $CHILD2_1_CREATE_GM_TABLES2=
CREATE TABLE gm_r2 (
a INT DEFAULT 0,
b GEOMETRY NOT NULL,
c GEOMETRY NOT NULL,
PRIMARY KEY(a),
SPATIAL INDEX sp_idx1(b),
SPATIAL INDEX sp_idx2(c)
) $CHILD2_1_GM_ENGINE $CHILD2_1_GM_CHARSET;
let $CHILD2_1_SELECT_GM_TABLES2=
SELECT a, b, c FROM gm_r2 ORDER BY a;
let $CHILD2_1_DROP_LOCK_TABLES1=
DROP TABLE IF EXISTS t1_1;
let $CHILD2_1_CREATE_LOCK_TABLES1=
CREATE TABLE t1_1 (
id int(11) NOT NULL,
PRIMARY KEY (id)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_DROP_LOCK_TABLES2=
DROP TABLE IF EXISTS t2_2;
let $CHILD2_1_CREATE_LOCK_TABLES2=
CREATE TABLE t2_2 (
id int(11) NOT NULL,
PRIMARY KEY (id)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_DROP_INCREMENT_TABLES1=
DROP TABLE IF EXISTS t1_1;
let $CHILD2_1_CREATE_INCREMENT_TABLES1=
CREATE TABLE t1_1 (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_INCREMENT_TABLES1=
SELECT id FROM t1_1 ORDER BY id;
let $CHILD2_1_DROP_TEXT_PK_TABLES1=
DROP TABLE IF EXISTS t1;
let $CHILD2_1_CREATE_TEXT_PK_TABLES1=
CREATE TABLE t1 (
a VARCHAR(255),
PRIMARY KEY (a)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET2;
let $CHILD2_1_SELECT_TEXT_PK_TABLES1=
SELECT a FROM t1 ORDER BY a;
let $CHILD2_1_DROP_TEXT_KEY_TABLES1=
DROP TABLE IF EXISTS t1;
let $CHILD2_1_CREATE_TEXT_KEY_TABLES1=
CREATE TABLE t1 (
a VARCHAR(255),
b VARCHAR(255),
c VARCHAR(255),
KEY idx1(a,b),
KEY idx2(b),
PRIMARY KEY(c)
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
let $CHILD2_1_SELECT_TEXT_KEY_TABLES1=
SELECT a, b FROM t1 ORDER BY a, b;
let $CHILD2_1_AUTO_INCREMENT_INCREMENT1=
SET GLOBAL AUTO_INCREMENT_INCREMENT = 1;
let $CHILD2_1_AUTO_INCREMENT_INCREMENT2=
SET GLOBAL AUTO_INCREMENT_INCREMENT = 4;
let $CHILD2_1_AUTO_INCREMENT_OFFSET1=
SET GLOBAL AUTO_INCREMENT_OFFSET = 1;
let $CHILD2_1_AUTO_INCREMENT_OFFSET2=
SET GLOBAL AUTO_INCREMENT_OFFSET = 2;
let $CHILD2_2_DROP_TABLES=
DROP TABLE IF EXISTS ta_r3;
let $CHILD2_2_CREATE_TABLES=
CREATE TABLE ta_r3 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
let $CHILD2_2_DROP_TABLES5=
DROP TABLE IF EXISTS ta_r_int;
let $CHILD2_2_CREATE_TABLES5=
CREATE TABLE ta_r_int (
a INT AUTO_INCREMENT,
b INT DEFAULT 10,
c INT DEFAULT 11,
PRIMARY KEY(a),
KEY idx1(b),
KEY idx2(c)
) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
let $CHILD2_2_SELECT_TABLES=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r3 ORDER BY a;
let $CHILD2_2_DROP_FT_TABLES=
DROP TABLE IF EXISTS ft_r3;
let $CHILD2_2_CREATE_FT_TABLES=
CREATE TABLE ft_r3 (
a INT DEFAULT 0,
b TEXT,
c TEXT,
d TEXT,
PRIMARY KEY(a),
FULLTEXT INDEX ft_idx1(b),
FULLTEXT INDEX ft_idx2(c)
) $CHILD2_2_FT_ENGINE $CHILD2_2_FT_CHARSET;
let $CHILD2_2_SELECT_FT_TABLES=
SELECT a, b, c, d FROM ft_r3 ORDER BY a;
let $CHILD2_2_DROP_GM_TABLES=
DROP TABLE IF EXISTS gm_r3;
let $CHILD2_2_CREATE_GM_TABLES=
CREATE TABLE gm_r3 (
a INT DEFAULT 0,
b GEOMETRY NOT NULL,
c GEOMETRY NOT NULL,
PRIMARY KEY(a),
SPATIAL INDEX sp_idx1(b),
SPATIAL INDEX sp_idx2(c)
) $CHILD2_2_GM_ENGINE $CHILD2_2_GM_CHARSET;
let $CHILD2_2_SELECT_GM_TABLES=
SELECT a, b, c FROM gm_r3 ORDER BY a;
let $CHILD2_2_DROP_LOCK_TABLES1=
DROP TABLE IF EXISTS t1_2;
let $CHILD2_2_CREATE_LOCK_TABLES1=
CREATE TABLE t1_2 (
id int(11) NOT NULL,
PRIMARY KEY (id)
) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
let $CHILD2_2_DROP_LOCK_TABLES2=
DROP TABLE IF EXISTS t2_1;
let $CHILD2_2_CREATE_LOCK_TABLES2=
CREATE TABLE t2_1 (
id int(11) NOT NULL,
PRIMARY KEY (id)
) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
let $CHILD2_2_DROP_INCREMENT_TABLES1=
DROP TABLE IF EXISTS t1_2;
let $CHILD2_2_CREATE_INCREMENT_TABLES1=
CREATE TABLE t1_2 (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
let $CHILD2_2_SELECT_INCREMENT_TABLES1=
SELECT id FROM t1_2 ORDER BY id;
let $CHILD2_2_AUTO_INCREMENT_INCREMENT1=
SET GLOBAL AUTO_INCREMENT_INCREMENT = 1;
let $CHILD2_2_AUTO_INCREMENT_INCREMENT2=
SET GLOBAL AUTO_INCREMENT_INCREMENT = 4;
let $CHILD2_2_AUTO_INCREMENT_OFFSET1=
SET GLOBAL AUTO_INCREMENT_OFFSET = 1;
let $CHILD2_2_AUTO_INCREMENT_OFFSET2=
SET GLOBAL AUTO_INCREMENT_OFFSET = 3;
let $CHILD2_3_DROP_TABLES=
DROP TABLE IF EXISTS ta_r4;
let $CHILD2_3_CREATE_TABLES=
CREATE TABLE ta_r4 (
a INT DEFAULT 10,
b CHAR(1) DEFAULT 'c',
c DATETIME DEFAULT '1999-10-10 10:10:10',
PRIMARY KEY(a)
) $CHILD2_3_ENGINE $CHILD2_3_CHARSET;
let $CHILD2_3_SELECT_TABLES=
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r4 ORDER BY a;
This diff is collapsed.
let $SLAVE1_1_COMMENT_INCREMENT1_1=
COMMENT '';
let $SLAVE1_1_COMMENT_INCREMENT1_P_1=
COMMENT ''
PARTITION BY LIST(MOD(id, 2)) (
PARTITION pt1 VALUES IN (0)
COMMENT='',
PARTITION pt2 VALUES IN (1)
COMMENT=''
);
This diff is collapsed.
This diff is collapsed.
for master_1
for child2
child2_1
child2_2
child2_3
for child3
child3_1
child3_2
child3_3
drop and create databases
DROP DATABASE IF EXISTS auto_test_local;
CREATE DATABASE auto_test_local;
USE auto_test_local;
DROP DATABASE IF EXISTS auto_test_remote;
CREATE DATABASE auto_test_remote;
USE auto_test_remote;
DROP DATABASE IF EXISTS auto_test_remote2;
CREATE DATABASE auto_test_remote2;
USE auto_test_remote2;
test select 1
SELECT 1;
1
1
create table select test
DROP TABLE IF EXISTS ta_l;
CREATE TABLE ta_l (
a INT,
b CHAR(1),
c DATETIME,
PRIMARY KEY(a)
) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
INSERT INTO ta_l (a, b, c) VALUES
(1, 'a', '2008-08-01 10:21:39'),
(2, 'b', '2000-01-01 00:00:00'),
(3, 'e', '2007-06-04 20:03:11'),
(4, 'd', '2003-11-30 05:01:03'),
(5, 'c', '2001-12-31 23:59:59');
direct_aggregating test
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 0
SELECT COUNT(*) FROM ta_l;
COUNT(*)
5
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 1
SELECT MAX(a) FROM ta_l;
MAX(a)
5
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 1
SELECT MIN(a) FROM ta_l;
MIN(a)
1
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 1
SELECT MAX(a) FROM ta_l WHERE a < 5;
MAX(a)
4
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 1
SELECT MIN(a) FROM ta_l WHERE a > 1;
MIN(a)
2
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 1
with partition test
CREATE TABLE ta_l2 (
a INT,
b CHAR(1),
c DATETIME,
PRIMARY KEY(a)
) MASTER_1_ENGINE MASTER_1_COMMENT2_P_2_1
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 1
SELECT COUNT(*) FROM ta_l2;
COUNT(*)
5
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 3
SELECT MAX(a) FROM ta_l2;
MAX(a)
5
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 3
SELECT MIN(a) FROM ta_l2;
MIN(a)
1
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 3
SELECT MAX(a) FROM ta_l2 WHERE a < 5;
MAX(a)
4
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 3
SELECT MIN(a) FROM ta_l2 WHERE a > 1;
MIN(a)
2
SHOW STATUS LIKE 'Spider_direct_aggregate';
Variable_name Value
Spider_direct_aggregate 3
deinit
DROP DATABASE IF EXISTS auto_test_local;
DROP DATABASE IF EXISTS auto_test_remote;
DROP DATABASE IF EXISTS auto_test_remote2;
for master_1
for child2
child2_1
child2_2
child2_3
for child3
child3_1
child3_2
child3_3
end of test
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
package My::Suite::Spider;
@ISA = qw(My::Suite);
return "No Spider engine" unless $ENV{HA_SPIDER_SO};
return "Not run for embedded server" if $::opt_embedded_server;
bless { };
This diff is collapsed.
--connect (child2_1, localhost, root, , , $CHILD2_1_MYPORT, $CHILD2_1_MYSOCK)
--connect (child2_2, localhost, root, , , $CHILD2_2_MYPORT, $CHILD2_2_MYSOCK)
--connect (child2_3, localhost, root, , , $CHILD2_3_MYPORT, $CHILD2_3_MYSOCK)
--connect (child3_1, localhost, root, , , $CHILD3_1_MYPORT, $CHILD3_1_MYSOCK)
--connect (child3_2, localhost, root, , , $CHILD3_2_MYPORT, $CHILD3_2_MYSOCK)
--connect (child3_3, localhost, root, , , $CHILD3_3_MYPORT, $CHILD3_3_MYSOCK)
--connect (master_1, localhost, root, , , $MASTER_1_MYPORT, $MASTER_1_MYSOCK)
--connect (slave1_1, localhost, root, , , $SLAVE1_1_MYPORT, $SLAVE1_1_MYSOCK)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
if (!`SELECT count(*) FROM information_schema.engines WHERE
(support = 'YES' OR support = 'DEFAULT') AND
engine = '$TEST_ENGINE_TYPE'`)
{
SELECT engine, support FROM information_schema.engines;
--let $SKIP_REASON= "Need $TEST_ENGINE_TYPE engine"
}
if (!`SELECT count(*) FROM mysql.func WHERE name = '$TEST_FUNC_NAME'`)
{
SELECT name FROM mysql.func;
--let $SKIP_REASON= "Need $TEST_FUNC_NAME function"
}
let $HAVE_PARTITION= 0;
if (`SELECT count(*) FROM information_schema.plugins WHERE
plugin_status = 'ACTIVE' AND
plugin_name = 'partition'`)
{
let $HAVE_PARTITION= 1;
}
let $HAVE_TRIGGER= `SELECT COUNT(*) FROM information_schema.tables
WHERE TABLE_SCHEMA = 'information_schema' AND TABLE_NAME = 'TRIGGERS'`;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment