diff --git a/CMakeLists.txt b/CMakeLists.txt index 71ee749c7..eb3d471e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,7 @@ include_directories(server/modules/include) include_directories(${CMAKE_BINARY_DIR}/include) include_directories(${CURL_INCLUDE_DIRS}) include_directories(maxutils/maxbase/include) +include_directories(maxutils/maxsql/include) if (BUILD_CDC) include_directories(avro) diff --git a/include/maxscale/mysql_utils.h b/include/maxscale/mysql_utils.h index 082136c83..3a393819a 100644 --- a/include/maxscale/mysql_utils.h +++ b/include/maxscale/mysql_utils.h @@ -41,14 +41,6 @@ char* mxs_lestr_consume(uint8_t** c, size_t* size); */ MYSQL* mxs_mysql_real_connect(MYSQL* mysql, SERVER* server, const char* user, const char* passwd); -/** - * Check if the MYSQL error number is a connection error. - * - * @param Error code - * @return True if the MYSQL error number is a connection error - */ -bool mxs_mysql_is_net_error(unsigned int errcode); - /** * Execute a query using global query retry settings. * @@ -59,17 +51,6 @@ bool mxs_mysql_is_net_error(unsigned int errcode); */ int mxs_mysql_query(MYSQL* conn, const char* query); -/** - * Execute a query, manually defining retry limits. - * - * @param conn MySQL connection - * @param query Query to execute - * @param query_retries Maximum number of retries - * @param query_retry_timeout Maximum time to spend retrying, in seconds - * @return return value of mysql_query - */ -int mxs_mysql_query_ex(MYSQL* conn, const char* query, int query_retries, time_t query_retry_timeout); - /** * Trim MySQL quote characters surrounding a string. * @@ -142,19 +123,4 @@ mxs_mysql_name_kind_t mxs_mysql_name_to_pcre(char* pcre, */ void mxs_mysql_update_server_version(MYSQL* mysql, SERVER* server); -/** - * Enable/disable the logging of all SQL statements MaxScale sends to - * the servers. - * - * @param enable If true, enable, if false, disable. - */ -void mxs_mysql_set_log_statements(bool enable); - -/** - * Returns whether SQL statements sent to the servers are logged or not. - * - * @return True, if statements are logged, false otherwise. - */ -bool mxs_mysql_get_log_statements(); - MXS_END_DECLS diff --git a/maxutils/CMakeLists.txt b/maxutils/CMakeLists.txt index 911b44033..0ab8057e1 100644 --- a/maxutils/CMakeLists.txt +++ b/maxutils/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(maxbase) +add_subdirectory(maxsql) diff --git a/maxutils/maxsql/CMakeLists.txt b/maxutils/maxsql/CMakeLists.txt new file mode 100644 index 000000000..e0e9b8640 --- /dev/null +++ b/maxutils/maxsql/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) +add_subdirectory(include/maxsql) +add_subdirectory(src) diff --git a/maxutils/maxsql/include/maxsql/CMakeLists.txt b/maxutils/maxsql/include/maxsql/CMakeLists.txt new file mode 100644 index 000000000..b0d8c60eb --- /dev/null +++ b/maxutils/maxsql/include/maxsql/CMakeLists.txt @@ -0,0 +1,3 @@ +install_header(mariadb.hh devel) +install_header(ccdefs.hh devel) + diff --git a/maxutils/maxsql/include/maxsql/ccdefs.hh b/maxutils/maxsql/include/maxsql/ccdefs.hh new file mode 100644 index 000000000..f8fedff68 --- /dev/null +++ b/maxutils/maxsql/include/maxsql/ccdefs.hh @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2022-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ + +#pragma once + +/** + * @file ccdefs.hh + * + * This file should be included first by all maxsql headers. + */ + +#if !defined (__cplusplus) +#error This file is only to be included by C++ code. +#endif + +#include + +/** + * All classes of MaxSql are defined in the namespace @c maxsql. + */ +namespace maxsql +{ +} + +/** + * Shorthand for the @c maxsql namespace. + */ +namespace mxq = maxsql; diff --git a/maxutils/maxsql/include/maxsql/mariadb.hh b/maxutils/maxsql/include/maxsql/mariadb.hh new file mode 100644 index 000000000..daadd5bd2 --- /dev/null +++ b/maxutils/maxsql/include/maxsql/mariadb.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2022-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ +#pragma once + +#include +#include +#include + +namespace maxsql +{ +/** + * Execute a query, manually defining retry limits. + * + * @param conn MySQL connection + * @param query Query to execute + * @param query_retries Maximum number of retries + * @param query_retry_timeout Maximum time to spend retrying, in seconds + * @return return value of mysql_query + */ +int mysql_query_ex(MYSQL* conn, const std::string& query, int query_retries, time_t query_retry_timeout); + +/** + * Check if the MYSQL error number is a connection error. + * + * @param Error code + * @return True if the MYSQL error number is a connection error + */ +bool mysql_is_net_error(unsigned int errcode); + +/** + * Enable/disable the logging of all SQL statements MaxScale sends to + * the servers. + * + * @param enable If true, enable, if false, disable. + */ +void mysql_set_log_statements(bool enable); + +/** + * Returns whether SQL statements sent to the servers are logged or not. + * + * @return True, if statements are logged, false otherwise. + */ +bool mysql_get_log_statements(); +} diff --git a/maxutils/maxsql/src/CMakeLists.txt b/maxutils/maxsql/src/CMakeLists.txt new file mode 100644 index 000000000..40720ed72 --- /dev/null +++ b/maxutils/maxsql/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(maxsql STATIC + mariadb.cc + ) + +target_link_libraries(maxsql maxbase ${MARIADB_CONNECTOR_LIBRARIES}) +set_target_properties(maxsql PROPERTIES VERSION "1.0.0" LINK_FLAGS -Wl,-z,defs) + diff --git a/maxutils/maxsql/src/mariadb.cc b/maxutils/maxsql/src/mariadb.cc new file mode 100644 index 000000000..e6a66dcad --- /dev/null +++ b/maxutils/maxsql/src/mariadb.cc @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2022-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ +#include +#include +#include +#include + + +namespace +{ +struct THIS_UNIT +{ + bool log_statements; // Should all statements sent to server be logged? +}; + +static THIS_UNIT this_unit = +{ + false +}; +} + +namespace maxsql +{ + +int mysql_query_ex(MYSQL* conn, const std::string& query, int query_retries, time_t query_retry_timeout) +{ + const char* query_cstr = query.c_str(); + time_t start = time(NULL); + int rc = mysql_query(conn, query_cstr); + + for (int n = 0; rc != 0 && n < query_retries && mysql_is_net_error(mysql_errno(conn)) + && time(NULL) - start < query_retry_timeout; n++) + { + rc = mysql_query(conn, query_cstr); + } + + if (this_unit.log_statements) + { + const char* host = "0.0.0.0"; + unsigned int port = 0; + MXB_AT_DEBUG(int rc1 = ) mariadb_get_info(conn, MARIADB_CONNECTION_HOST, &host); + MXB_AT_DEBUG(int rc2 = ) mariadb_get_info(conn, MARIADB_CONNECTION_PORT, &port); + mxb_assert(!rc1 && !rc2); + MXB_NOTICE("SQL([%s]:%u): %d, \"%s\"", host, port, rc, query_cstr); + } + + return rc; +} + +bool mysql_is_net_error(unsigned int errcode) +{ + switch (errcode) + { + case CR_SOCKET_CREATE_ERROR: + case CR_CONNECTION_ERROR: + case CR_CONN_HOST_ERROR: + case CR_IPSOCK_ERROR: + case CR_SERVER_GONE_ERROR: + case CR_TCP_CONNECTION: + case CR_SERVER_LOST: + return true; + + default: + return false; + } +} + +void mysql_set_log_statements(bool enable) +{ + this_unit.log_statements = enable; +} + +bool mysql_get_log_statements() +{ + return this_unit.log_statements; +} +} diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index 1e0a6218a..588b824e4 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -51,6 +51,7 @@ add_library(maxscale-common SHARED target_link_libraries(maxscale-common maxbase + maxsql ${MARIADB_CONNECTOR_LIBRARIES} ${LZMA_LINK_FLAGS} ${PCRE2_LIBRARIES} diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 28b052931..980bd5d1e 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -3165,12 +3166,12 @@ static void disable_module_unloading(const char* arg) static void enable_statement_logging(const char* arg) { - mxs_mysql_set_log_statements(true); + maxsql::mysql_set_log_statements(true); } static void disable_statement_logging(const char* arg) { - mxs_mysql_set_log_statements(false); + maxsql::mysql_set_log_statements(false); } static void redirect_output_to_file(const char* arg) diff --git a/server/core/mysql_utils.cc b/server/core/mysql_utils.cc index eea72b506..df7b4b338 100644 --- a/server/core/mysql_utils.cc +++ b/server/core/mysql_utils.cc @@ -27,25 +27,12 @@ #include #include +#include #include #include #include #include -namespace -{ - -struct THIS_UNIT -{ - bool log_statements; // Should all statements sent to server be logged? -}; - -static THIS_UNIT this_unit = -{ - false -}; -} - /** * @brief Calculate the length of a length-encoded integer in bytes * @@ -224,53 +211,10 @@ MYSQL* mxs_mysql_real_connect(MYSQL* con, SERVER* server, const char* user, cons return mysql; } -bool mxs_mysql_is_net_error(unsigned int errcode) -{ - switch (errcode) - { - case CR_SOCKET_CREATE_ERROR: - case CR_CONNECTION_ERROR: - case CR_CONN_HOST_ERROR: - case CR_IPSOCK_ERROR: - case CR_SERVER_GONE_ERROR: - case CR_TCP_CONNECTION: - case CR_SERVER_LOST: - return true; - - default: - return false; - } -} - -int mxs_mysql_query_ex(MYSQL* conn, const char* query, int query_retries, time_t query_retry_timeout) -{ - time_t start = time(NULL); - int rc = mysql_query(conn, query); - - for (int n = 0; rc != 0 && n < query_retries - && mxs_mysql_is_net_error(mysql_errno(conn)) - && time(NULL) - start < query_retry_timeout; n++) - { - rc = mysql_query(conn, query); - } - - if (this_unit.log_statements) - { - const char* host = "0.0.0.0"; - unsigned int port = 0; - MXB_AT_DEBUG(int rc1 = ) mariadb_get_info(conn, MARIADB_CONNECTION_HOST, &host); - MXB_AT_DEBUG(int rc2 = ) mariadb_get_info(conn, MARIADB_CONNECTION_PORT, &port); - mxb_assert(!rc1 && !rc2); - MXS_NOTICE("SQL([%s]:%u): %d, \"%s\"", host, port, rc, query); - } - - return rc; -} - int mxs_mysql_query(MYSQL* conn, const char* query) { MXS_CONFIG* cnf = config_get_global_options(); - return mxs_mysql_query_ex(conn, query, cnf->query_retries, cnf->query_retry_timeout); + return maxsql::mysql_query_ex(conn, query, cnf->query_retries, cnf->query_retry_timeout); } const char* mxs_mysql_get_value(MYSQL_RES* result, MYSQL_ROW row, const char* key) @@ -415,13 +359,3 @@ void mxs_mysql_update_server_version(MYSQL* mysql, SERVER* server) mxb_assert(version_string != NULL && version_num != 0); server_set_version(server, version_string, version_num); } - -void mxs_mysql_set_log_statements(bool enable) -{ - this_unit.log_statements = enable; -} - -bool mxs_mysql_get_log_statements() -{ - return this_unit.log_statements; -} diff --git a/server/modules/monitor/mariadbmon/mariadbserver.cc b/server/modules/monitor/mariadbmon/mariadbserver.cc index 53abece7f..7cbef9813 100644 --- a/server/modules/monitor/mariadbmon/mariadbserver.cc +++ b/server/modules/monitor/mariadbmon/mariadbserver.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -114,7 +115,7 @@ bool MariaDBServer::execute_cmd_ex(const string& cmd, QueryRetryMode mode, } else { - query_success = (mxs_mysql_query_ex(conn, cmd.c_str(), 0, 0) == 0); + query_success = (maxsql::mysql_query_ex(conn, cmd, 0, 0) == 0); } bool rval = false; @@ -207,7 +208,7 @@ bool MariaDBServer::execute_cmd_time_limit(const std::string& cmd, maxbase::Dura Duration time_remaining = time_limit - timer.split(); keep_trying = (time_remaining.secs() > 0) // either a connector-c timeout - && (mxs_mysql_is_net_error(errornum) + && (maxsql::mysql_is_net_error(errornum) // or query was interrupted by max_statement_time. || (!cmd_prefix.empty() && errornum == ER_STATEMENT_TIMEOUT)); if (!cmd_success)