1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00

Merge remote-tracking branch 'origin/master' into cio

Conflicts:
	CMakeLists.txt
	include/mysql/client_plugin.h
	libmariadb/client_plugin.c.in
	libmariadb/libmariadb.c
	libmariadb/ma_secure.c
	libmariadb/my_malloc.c
	libmariadb/net.c
	plugins/io/CMakeLists.txt
	unittest/libmariadb/misc.c
This commit is contained in:
Georg Richter
2015-10-02 12:28:54 +02:00
20 changed files with 499 additions and 71 deletions

View File

@@ -4,8 +4,8 @@
# This is the LGPL libmariadb project.
PROJECT(mariadb-connector-c C)
SET(CPACK_PACKAGE_VERSION_MAJOR 3)
SET(CPACK_PACKAGE_VERSION_MINOR 0)
SET(CPACK_PACKAGE_VERSION_MAJOR 2)
SET(CPACK_PACKAGE_VERSION_MINOR 2)
SET(CPACK_PACKAGE_VERSION_PATCH 0)
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -26,6 +26,7 @@ ELSE()
OPTION(WITH_SIGNCODE "digitally sign files" OFF)
OPTION(WITH_RTC "enables run time checks for debug builds" OFF)
ENDIF()
OPTION(WITH_REMOTEIO "enables remote io support (requires libcurl)" OFF)
OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF)
###############
@@ -204,15 +205,18 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include)
IF(WIN32)
SET(SYSTEM_LIBS ws2_32 advapi32 kernel32)
ELSE()
SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM} ${LIBICONV})
SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM})
IF(ICONV_EXTERNAL)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ICONV_LIBRARIES})
ENDIF()
ENDIF()
IF(WITH_SSL)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES})
ENDIF()
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(plugins)
ADD_SUBDIRECTORY(libmariadb)
ADD_SUBDIRECTORY(plugins)
IF(NOT WIN32)
ADD_SUBDIRECTORY(mariadb_config)
ENDIF()
@@ -246,35 +250,29 @@ INCLUDE(cmake/ConnectorName.cmake)
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-src")
SET(CPACK_SOURCE_IGNORE_FILES
.bzr/
.bzrignore
CMakeCache.txt
cmake_dist.cmake
CPackSourceConfig.cmake
CPackConfig.cmake
mariadb_config/mariadb_config.c$
.build/
\\\\.git/
\\\\.gitignore
CMakeCache\\\\.txt
cmake_dist\\\\.cmake
CPackConfig\\\\.cmake
mariadb_config/mariadb_config\\\\.c$
\\\\.build/
html/
unittest
/cmake_install.cmake
/CTestTestfile.cmake
/CPackSourceConfig.cmake
/CMakeFiles/
/version_resources/
/_CPack_Packages/
.*gz$
.*zip$
.*so$
.*so.*$
.*dll$
.*a$
.*pdb$
\\\\.gz$
\\\\.zip$
mariadb_config/mariadb_config
/CMakeFiles/
/version_resources/
/_CPack_Packages/
Makefile$
include/my_config.h$
/autom4te.cache/
errmsg.sys$
include/my_config\\\\.h$
)
IF(WIN32)

View File

@@ -19,6 +19,7 @@ IF(APPLE)
/opt/local/lib/
/usr/lib/
NO_CMAKE_SYSTEM_PATH)
SET(ICONV_EXTERNAL TRUE)
ELSE()
find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2)
IF(ICONV_LIBRARIES)

30
cmake/symlink.cmake Normal file
View File

@@ -0,0 +1,30 @@
MACRO(create_symlink symlink_name target install_path)
# According to cmake documentation symlinks work on unix systems only
IF(UNIX)
# Get target components
GET_TARGET_PROPERTY(target_location ${target} LOCATION)
GET_FILENAME_COMPONENT(target_path ${target_location} PATH)
GET_FILENAME_COMPONENT(target_name ${target_location} NAME)
ADD_CUSTOM_COMMAND(
OUTPUT ${target_path}/${symlink_name}
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${target_path}/${symlink_name}
COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink ${target_name} ${symlink_name}
WORKING_DIRECTORY ${target_path}
DEPENDS ${target}
)
ADD_CUSTOM_TARGET(SYM_${symlink_name}
ALL
DEPENDS ${target_path}/${symlink_name})
SET_TARGET_PROPERTIES(SYM_${symlink_name} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
IF(CMAKE_GENERATOR MATCHES "Xcode")
# For Xcode, replace project config with install config
STRING(REPLACE "${CMAKE_CFG_INTDIR}"
"\${CMAKE_INSTALL_CONFIG_NAME}" output ${target_path}/${symlink_name})
ENDIF()
INSTALL(FILES ${target_path}/${symlink_name} DESTINATION ${install_path})
ENDIF()
ENDMACRO()

View File

@@ -18,6 +18,7 @@
#ifndef _ma_io_h_
#define _ma_io_h_
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
@@ -34,6 +35,7 @@ typedef struct
void *ptr;
} MA_FILE;
#ifdef HAVE_REMOTEIO
struct st_rio_methods {
MA_FILE *(*open)(const char *url, const char *mode);
int (*close)(MA_FILE *ptr);
@@ -41,6 +43,7 @@ struct st_rio_methods {
size_t (*read)(void *ptr, size_t size, size_t nmemb, MA_FILE *file);
char * (*gets)(char *ptr, size_t size, MA_FILE *file);
};
#endif
/* function prototypes */
MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql);

View File

@@ -454,7 +454,7 @@ typedef SOCKET_SIZE_TYPE size_socket;
#ifdef _WIN32
#define NO_DIR_LIBRARY /* Not standar dir-library */
#define USE_MY_STAT_STRUCT /* For my_lib */
#ifdef _SIZE_T_DEFINED
#ifdef _MSC_VER
typedef SSIZE_T ssize_t;
#endif
#endif

View File

@@ -144,6 +144,7 @@ typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
int type, const char *prompt, char *buf, int buf_len);
/********************** remote IO plugin **********************/
#ifdef HAVE_REMOTEIO
#include <mariadb/ma_io.h>
/* Remote IO plugin */
@@ -152,6 +153,7 @@ struct st_mysql_client_plugin_REMOTEIO
MYSQL_CLIENT_PLUGIN_HEADER
struct st_rio_methods *methods;
};
#endif
/******** using plugins ************/

View File

@@ -224,6 +224,12 @@ IF(WITH_SSL)
SET(EXPORTS ${EXPORTS} mariadb_deinitialize_ssl)
ENDIF()
# some gcc versions fail to compile asm parts of my_context.c,
# if build type is "Release" (see CONC-133), so we need to add -g flag
IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_BUILD_TYPE MATCHES "Release")
SET_SOURCE_FILES_PROPERTIES(my_context.c PROPERTIES COMPILE_FLAGS -g)
ENDIF()
IF(WIN32)
SET(EXPORT_CONTENT "EXPORTS\n")
FOREACH(SYMBOL ${EXPORT_SYMBOLS})
@@ -366,10 +372,17 @@ IF(UNIX)
SET_TARGET_PROPERTIES(mariadb_obj PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
ENDIF()
ADD_LIBRARY(mariadbclient STATIC $<TARGET_OBJECTS:mariadb_obj> ${EXPORT_LINK})
# Xcode doesn't support targets that have only object files,
# so let's add an empty file to keep Xcode happy
IF(CMAKE_GENERATOR MATCHES Xcode)
FILE(WRITE ${CMAKE_SOURCE_DIR}/libmariadb/empty.c "")
SET(EMPTY_FILE ${CMAKE_SOURCE_DIR}/libmariadb/empty.c)
ENDIF()
ADD_LIBRARY(mariadbclient STATIC $<TARGET_OBJECTS:mariadb_obj> ${EMPTY_FILE} ${EXPORT_LINK})
TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS})
ADD_LIBRARY(libmariadb SHARED $<TARGET_OBJECTS:mariadb_obj> ${EXPORT_LINK})
ADD_LIBRARY(libmariadb SHARED $<TARGET_OBJECTS:mariadb_obj> ${EMPTY_FILE} ${EXPORT_LINK})
TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS})
IF(UNIX)
SET_TARGET_PROPERTIES(libmariadb PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
@@ -391,33 +404,18 @@ SET_TARGET_PROPERTIES(libmariadb PROPERTIES VERSION
#
# Installation
#
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/symlink.cmake)
# There are still several projects which don't make use
# of the config program. To make sure these programs can
# use mariadb client library we provide libmysql symlinks
IF(NOT WIN32 AND WITH_MYSQLCOMPAT)
ADD_CUSTOM_COMMAND(OUTPUT "libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}"
"libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}"
"libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}"
"libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}"
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadb${CMAKE_SHARED_LIBRARY_SUFFIX} libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadb${CMAKE_SHARED_LIBRARY_SUFFIX} libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadb${CMAKE_SHARED_LIBRARY_SUFFIX} libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadbclient${CMAKE_STATIC_LIBRARY_SUFFIX} libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/libmariadb
DEPENDS libmariadb mariadbclient)
ADD_CUSTOM_TARGET(LIBMYSQL_SYMLINKS
ALL
DEPENDS "libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}"
"libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}"
"libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}"
"libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}"
VERBATIM)
SET(INSTALL_PATH ${LIB_INSTALL_DIR}/${SUFFIX_INSTALL_DIR})
create_symlink(libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX} libmariadb ${INSTALL_PATH})
create_symlink(libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX} libmariadb ${INSTALL_PATH})
create_symlink(libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_PATH})
create_symlink(libmysqlclient_r${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_PATH})
ENDIF()
@@ -427,14 +425,6 @@ INSTALL(TARGETS
LIBRARY DESTINATION "${LIB_INSTALL_DIR}/${SUFFIX_INSTALL_DIR}"
ARCHIVE DESTINATION "${LIB_INSTALL_DIR}/${SUFFIX_INSTALL_DIR}")
IF(NOT WIN32 AND WITH_MYSQLCOMPAT)
INSTALL(FILES "${CMAKE_BINARY_DIR}/libmariadb/libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}"
"${CMAKE_BINARY_DIR}/libmariadb/libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}"
"${CMAKE_BINARY_DIR}/libmariadb/libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}"
"${CMAKE_BINARY_DIR}/libmariadb/libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}"
DESTINATION ${LIB_INSTALL_DIR}/mariadb)
ENDIF()
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/
DESTINATION ${INCLUDE_INSTALL_DIR}/${SUFFIX_INSTALL_DIR})
INSTALL(FILES

View File

@@ -58,6 +58,7 @@ static MEM_ROOT mem_root;
#define plugin_declarations_sym "_mysql_client_plugin_declaration_"
static uint valid_plugins[][2]= {
{MYSQL_CLIENT_AUTHENTICATION_PLUGIN, MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_CIO_PLUGIN, MARIADB_CLIENT_CIO_PLUGIN_INTERFACE_VERSION},
@@ -138,7 +139,6 @@ static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
int plugin_nr= get_plugin_nr(type);
DBUG_ASSERT(initialized);
DBUG_ASSERT(plugin_nr != -1);
if (plugin_nr == -1)
return 0;
@@ -472,7 +472,7 @@ struct st_mysql_client_plugin * STDCALL
mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
{
struct st_mysql_client_plugin *p;
int plugin_nr= find_plugin(name, type);
int plugin_nr= get_plugin_nr(type);
if (is_not_initialized(mysql, name))
return NULL;

View File

@@ -1380,8 +1380,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
unix_socket=mysql->options.unix_socket;
/* Since 5.0.3 reconnect is not enabled by default!!
mysql->reconnect=1; */
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;

View File

@@ -23,10 +23,13 @@
#include <errmsg.h>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <mariadb/ma_io.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_REMOTEIO
struct st_mysql_client_plugin_REMOTEIO *rio_plugin= NULL;
#endif
/* {{{ ma_open */
MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql)
@@ -37,9 +40,10 @@ MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql)
if (!location || !location[0])
return NULL;
#ifdef HAVE_REMOTEIO
if (strstr(location, "://"))
goto remote;
#endif
#ifdef _WIN32
if (mysql && mysql->charset)
@@ -118,6 +122,7 @@ MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql)
ma_file->ptr= (void *)fp;
}
return ma_file;
#ifdef HAVE_REMOTEIO
remote:
/* check if plugin for remote io is available and try
* to open location */
@@ -128,6 +133,7 @@ remote:
return rio_plugin->methods->open(location, mode);
return NULL;
}
#endif
}
/* }}} */
@@ -143,9 +149,11 @@ int ma_close(MA_FILE *file)
rc= fclose((FILE *)file->ptr);
my_free(file);
break;
#ifdef HAVE_REMOTEIO
case MA_FILE_REMOTE:
rc= rio_plugin->methods->close(file);
break;
#endif
default:
return -1;
}
@@ -163,9 +171,11 @@ int ma_feof(MA_FILE *file)
case MA_FILE_LOCAL:
return feof((FILE *)file->ptr);
break;
#ifdef HAVE_REMOTEIO
case MA_FILE_REMOTE:
return rio_plugin->methods->feof(file);
break;
#endif
default:
return -1;
}
@@ -184,9 +194,11 @@ size_t ma_read(void *ptr, size_t size, size_t nmemb, MA_FILE *file)
s= fread(ptr, size, nmemb, (FILE *)file->ptr);
return s;
break;
#ifdef HAVE_REMOTEIO
case MA_FILE_REMOTE:
return rio_plugin->methods->read(ptr, size, nmemb, file);
break;
#endif
default:
return -1;
}
@@ -203,9 +215,11 @@ char *ma_gets(char *ptr, size_t size, MA_FILE *file)
case MA_FILE_LOCAL:
return fgets(ptr, size, (FILE *)file->ptr);
break;
#ifdef HAVE_REMOTEIO
case MA_FILE_REMOTE:
return rio_plugin->methods->gets(ptr, size, file);
break;
#endif
default:
return NULL;
}

View File

@@ -79,12 +79,10 @@ my_string my_strdup(const char *from, myf MyFlags)
gptr ptr;
uint length;
if (MyFlags & MY_ALLOW_ZERO_PTR)
if (!from)
if ((MyFlags & MY_ALLOW_ZERO_PTR) && !from)
return NULL;
length=(uint) strlen(from)+1;
if ((ptr=my_malloc(length,MyFlags)) != 0)
memcpy((unsigned char*) ptr, (unsigned char*) from,(size_t) length);
return((my_string) ptr);

View File

@@ -1887,6 +1887,7 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
if (mysql_next_result(stmt->mysql))
{
stmt->state= MYSQL_STMT_FETCH_DONE;
SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate,
stmt->mysql->net.last_error);
DBUG_RETURN(1);

View File

@@ -825,7 +825,7 @@ mysql_close_start(MYSQL *sock)
int res;
/* It is legitimate to have NULL sock argument, which will do nothing. */
if (sock)
if (sock && sock->net.cio)
{
res= mysql_close_slow_part_start(sock);
/* If we need to block, return now and do the rest in mysql_close_cont(). */

View File

@@ -0,0 +1,19 @@
IF(WIN32)
SET(EXPORT_FILE "../plugin.def")
ENDIF()
SET(CMAKE_SHARED_LIBRARY_PREFIX "")
IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1)
ADD_LIBRARY(replication SHARED replication.c ${EXPORT_FILE})
SET(INSTALL_LIBS replication)
ENDIF()
IF(INSTALL_LIBS)
INSTALL(TARGETS
${INSTALL_LIBS}
RUNTIME DESTINATION "${PLUGIN_INSTALL_DIR}"
LIBRARY DESTINATION "${PLUGIN_INSTALL_DIR}"
ARCHIVE DESTINATION "${PLUGIN_INSTALL_DIR}")
ENDIF()

View File

@@ -0,0 +1,325 @@
/************************************************************************************
Copyright (C) 2015 MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
Part of this code includes code from the PHP project which
is freely available from http://www.php.net
*************************************************************************************/
/* MariaDB Connection plugin for load balancing */
#include <my_global.h>
#include <my_sys.h>
#include <errmsg.h>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <string.h>
#include <m_string.h>
#include <sys/time.h>
/* function prototypes */
MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
void repl_close(MYSQL *mysql);
int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg);
int repl_set_options(MYSQL *msql, enum mysql_option option, void *arg);
#ifdef HAVE_REPLICATION_DYNAMIC
#undef my_free
#define my_malloc(a,b) malloc(a)
#define my_free(a) free(a)
#endif
#define MARIADB_MASTER 0
#define MARIADB_SLAVE 1
#ifndef HAVE_REPLICATION_DYNAMIC
MARIADB_CONNECTION_PLUGIN connection_replication_plugin =
#else
MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
#endif
{
MARIADB_CLIENT_CONNECTION_PLUGIN,
MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION,
"replication",
"Georg Richter",
"MariaDB connection plugin for load balancing",
{1, 0, 0},
"LGPL",
NULL,
NULL,
repl_connect,
repl_close,
repl_set_options,
repl_command
};
typedef struct st_conn_repl {
MARIADB_CIO *cio[2];
MYSQL *slave_mysql;
my_bool read_only;
my_bool round_robin;
char *url;
char *host[2];
int port[2];
} REPL_DATA;
#define SET_SLAVE(mysql, data) mysql->net.cio= data->cio[MARIADB_SLAVE]
#define SET_MASTER(mysql, data) mysql->net.cio= data->cio[MARIADB_MASTER]
/* parse url
* Url has the following format:
* master[:port],slave1[:port],slave2[:port],..,slaven[:port]
*
*/
my_bool repl_parse_url(const char *url, REPL_DATA *data)
{
char *p;
char *slaves[64];
int port[64], i,num_slaves= 0;
if (!url || url[0] == 0)
return 1;
bzero(slaves, 64 * sizeof(char *));
bzero(&port, 64 * sizeof(int));
memset(data->host, 0, 2 * sizeof(char *));
memset(data->port, 0, 2 * sizeof(int));
if (data->url)
my_free(data->url);
data->url= my_strdup(url, MYF(0));
data->host[MARIADB_MASTER]= p= data->url;
/* get slaves */
while((p && (p= strchr(p, ','))))
{
*p= '\0';
p++;
if (*p)
{
slaves[num_slaves]= p;
num_slaves++;
}
}
if (!num_slaves)
return 0;
if (num_slaves == 1)
data->host[MARIADB_SLAVE]= slaves[0];
else
{
struct timeval tp;
int random_nr;
gettimeofday(&tp,NULL);
srand(tp.tv_usec / 1000 + tp.tv_sec * 1000);
random_nr= rand() % num_slaves;
data->host[MARIADB_SLAVE]= slaves[random_nr];
}
/* check ports */
for (i=0; i < 2 && data->host[i]; i++)
{
/* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
hostnames have to be enclosed in square brackets if a port is given */
if (data->host[i][0]= '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']')))
{
/* ignore first square bracket */
data->host[i]++;
*p= 0;
p++;
}
else
p= data->host[i];
if (p && (p= strchr(p, ':')))
{
*p= '\0';
p++;
data->port[i]= atoi(p);
}
}
return 0;
}
MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag)
{
REPL_DATA *data= NULL;
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
if (!(data= calloc(1, sizeof(REPL_DATA))))
{
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return NULL;
}
memset(data->cio, 0, 2 * sizeof(MARIADB_CIO *));
if (repl_parse_url(host, data))
goto error;
/* try to connect to master */
if (!(mysql->methods->db_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db,
data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag)))
goto error;
data->cio[MARIADB_MASTER]= mysql->net.cio;
hdlr->data= data;
/* to allow immediate access without connection delay, we will start
* connecting to slave(s) in background */
/* if slave connection will fail, we will not return error but use master instead */
if (!(data->slave_mysql= mysql_init(NULL)) ||
!(mysql->methods->db_connect(data->slave_mysql, data->host[MARIADB_SLAVE], user, passwd, db,
data->port[MARIADB_SLAVE] ? data->port[MARIADB_SLAVE] : port, unix_socket, clientflag)))
{
if (data->slave_mysql)
mysql_close(data->slave_mysql);
data->cio[MARIADB_SLAVE]= NULL;
}
else
{
data->cio[MARIADB_SLAVE]= data->slave_mysql->net.cio;
data->slave_mysql->net.cio->mysql= mysql;
}
return mysql;
error:
if (data)
{
if (data->url)
my_free(data->url);
my_free(data);
}
return NULL;
}
void repl_close(MYSQL *mysql)
{
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
REPL_DATA *data= (REPL_DATA *)hdlr->data;
/* restore master */
SET_MASTER(mysql, data);
/* free slave information and close connection */
if (data->cio[MARIADB_SLAVE])
{
/* restore mysql */
data->cio[MARIADB_SLAVE]->mysql= data->slave_mysql;
mysql_close(data->slave_mysql);
data->cio[MARIADB_SLAVE]= NULL;
data->slave_mysql= NULL;
}
/* free masrwe information and close connection */
my_free(data->url);
my_free(data);
mysql->net.conn_hdlr->data= NULL;
return mysql_close(mysql);
}
static my_bool is_slave_command(const char *buffer, size_t buffer_len)
{
const char *buffer_end= buffer + buffer_len;
for (; buffer < buffer_end; ++buffer)
{
char c;
if (isalpha(c=*buffer))
{
if (tolower(c) == 's')
return 1;
return 0;
}
}
return 0;
}
static my_bool is_slave_stmt(MYSQL *mysql, const char *buffer)
{
unsigned long stmt_id= uint4korr(buffer);
LIST *stmt_list= mysql->stmts;
for (; stmt_list; stmt_list= stmt_list->next)
{
MYSQL_STMT *stmt= (MYSQL_STMT *)stmt_list->data;
if (stmt->stmt_id == stmt_id)
return 1;
}
return 0;
}
int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg)
{
REPL_DATA *data= (REPL_DATA *)mysql->net.conn_hdlr->data;
/* if we don't have slave or slave became unavailable root traffic to master */
if (!data->cio[MARIADB_SLAVE] || !data->read_only)
{
SET_MASTER(mysql, data);
return 0;
}
switch(command) {
case MYSQL_COM_QUERY:
case MYSQL_COM_STMT_PREPARE:
if (is_slave_command(arg, length))
SET_SLAVE(mysql, data);
else
SET_MASTER(mysql,data);
break;
case MYSQL_COM_STMT_EXECUTE:
case MYSQL_COM_STMT_FETCH:
if (data->cio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->cio[MARIADB_SLAVE]->mysql, arg))
SET_SLAVE(mysql, data);
else
SET_MASTER(mysql,data);
break;
default:
SET_MASTER(mysql,data);
break;
}
return 0;
}
int repl_set_options(MYSQL *mysql, enum mysql_option option, void *arg)
{
REPL_DATA *data= (REPL_DATA *)mysql->net.conn_hdlr->data;
switch(option) {
case MARIADB_OPT_CONNECTION_READ_ONLY:
data->read_only= *(my_bool *)arg;
return 0;
/*
case MARIADB_OPT_CONNECTION_ROUND_ROBIN:
data->round_robin= *(my_bool *)arg;
return 0; */
default:
return -1;
}
}

View File

@@ -200,10 +200,17 @@ static int test_conc131(MYSQL *my)
return OK;
}
static int test_conc129(MYSQL *my)
{
MYSQL *mysql= mysql_init(NULL);
FAIL_IF(mysql_close_start(mysql), "No error expected");
}
struct my_tests_st my_tests[] = {
{"async1", async1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc131", test_conc131, TEST_CONNECTION_NONE, 0, NULL, NULL},
{"test_conc129", test_conc129, TEST_CONNECTION_NONE, 0, NULL, NULL},
{NULL, NULL, 0, 0, NULL, NULL}
};

View File

@@ -57,7 +57,7 @@ static int test_conc66(MYSQL *my)
diag("Error: %s", mysql_error(mysql));
return FAIL;
}
rc= mysql_query(my, "DROP USER conc66@%");
rc= mysql_query(my, "DROP USER conc66@localhost");
check_mysql_rc(rc, my);
mysql_close(mysql);

View File

@@ -26,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <mysql/client_plugin.h>
void *remote_plugin;
/*
Bug#28075 "COM_DEBUG crashes mysqld"
@@ -974,6 +973,8 @@ static int test_conc117(MYSQL *mysql)
return OK;
}
#ifdef HAVE_REMOTEIO
void *remote_plugin;
static int test_remote1(MYSQL *mysql)
{
int rc;
@@ -1019,11 +1020,14 @@ static int test_remote2(MYSQL *my)
mysql_close(mysql);
return OK;
}
#endif
struct my_tests_st my_tests[] = {
#ifdef HAVE_REMOTEIO
{"test_remote1", test_remote1, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_conc117", test_conc117, TEST_CONNECTION_NEW, 0, NULL, NULL},
#endif
{"test_conc117", test_conc117, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc_114", test_conc_114, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_connect_attrs", test_connect_attrs, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc49", test_conc49, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},

View File

@@ -3868,7 +3868,45 @@ static int test_conc_5(MYSQL *mysql)
return OK;
}
static int test_conc141(MYSQL *mysql)
{
int rc;
char *query= "CALL p_conc141";
MYSQL_STMT *stmt= mysql_stmt_init(mysql);
rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc141");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "CREATE TABLE conc141 (KeyVal int not null primary key)");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "INSERT INTO conc141 VALUES(1)");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p_conc141");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "CREATE PROCEDURE p_conc141()\n"
"BEGIN\n"
"select * from conc141;\n"
"insert into conc141(KeyVal) VALUES(1);\n"
"END");
check_mysql_rc(rc, mysql);
rc= mysql_stmt_prepare(stmt, query, strlen(query));
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
/* skip first result */
rc= mysql_stmt_next_result(stmt);
FAIL_IF(rc==-1, "No more results and error expected");
mysql_stmt_free_result(stmt);
FAIL_IF(mysql_stmt_errno(stmt), "No Error expected");
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
mysql_stmt_close(stmt);
return OK;
}
struct my_tests_st my_tests[] = {
{"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL},
{"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
{"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
{"test_bug1115", test_bug1115, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},