diff --git a/CMakeLists.txt b/CMakeLists.txt index 4627a3e43..6780205fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ configure_file(${CMAKE_SOURCE_DIR}/etc/postinst.in ${CMAKE_BINARY_DIR}/postinst configure_file(${CMAKE_SOURCE_DIR}/etc/postrm.in ${CMAKE_BINARY_DIR}/postrm @ONLY) configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.cnf ${CMAKE_BINARY_DIR}/maxscale.cnf @ONLY) -set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -fPIC" CACHE STRING "Compilation flags") +set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags") set(DEBUG_FLAGS "-ggdb -pthread -pipe -Wformat -fstack-protector --param=ssp-buffer-size=4" CACHE STRING "Debug compilation flags") if(CMAKE_VERSION VERSION_GREATER 2.6) @@ -184,13 +184,13 @@ execute_process(COMMAND perl ${CMAKE_SOURCE_DIR}/Documentation/format.pl ${CMAKE_SOURCE_DIR}/Documentation/Release-Notes/MaxScale-1.2.0-Release-Notes.md ${CMAKE_BINARY_DIR}/ReleaseNotes.txt) execute_process(COMMAND perl ${CMAKE_SOURCE_DIR}/Documentation/format.pl -${CMAKE_SOURCE_DIR}/Documentation/Upgrading/Upgrading-To-MaxScale-1.2.0.md - ${CMAKE_BINARY_DIR}/UpgradingToMaxScale120.txt) +${CMAKE_SOURCE_DIR}/Documentation/Upgrading/Upgrading-To-MaxScale-1.2.md + ${CMAKE_BINARY_DIR}/UpgradingToMaxScale12.txt) install(FILES ${CMAKE_BINARY_DIR}/Changelog.txt DESTINATION ${MAXSCALE_SHAREDIR}) install(FILES ${CMAKE_BINARY_DIR}/ReleaseNotes.txt DESTINATION ${MAXSCALE_SHAREDIR}) -install(FILES ${CMAKE_BINARY_DIR}/UpgradingToMaxScale120.txt DESTINATION ${MAXSCALE_SHAREDIR}) +install(FILES ${CMAKE_BINARY_DIR}/UpgradingToMaxScale12.txt DESTINATION ${MAXSCALE_SHAREDIR}) install(FILES server/maxscale_template.cnf DESTINATION ${MAXSCALE_SHAREDIR}) if(WITH_MAXSCALE_CNF) install(FILES server/maxscale_template.cnf DESTINATION ${MAXSCALE_CONFDIR} RENAME maxscale.cnf.template) @@ -262,7 +262,11 @@ if(PACKAGE) set(CPACK_PACKAGE_VERSION_MINOR "${MAXSCALE_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${MAXSCALE_VERSION_PATCH}") set(CPACK_PACKAGE_CONTACT "MariaDB Corporation Ab") - set(CPACK_PACKAGE_FILE_NAME "maxscale-${MAXSCALE_VERSION}-${CPACK_PACKAGE_ARCHITECTURE}-${DISTRIB_SUFFIX}") + if(DISTRIB_SUFFIX) + set(CPACK_PACKAGE_FILE_NAME "maxscale-${MAXSCALE_VERSION}-${MAXSCALE_BUILD_NUMBER}.${DISTRIB_SUFFIX}.${CPACK_PACKAGE_ARCHITECTURE}") + else() + set(CPACK_PACKAGE_FILE_NAME "maxscale-${MAXSCALE_VERSION}-${MAXSCALE_BUILD_NUMBER}.${CPACK_PACKAGE_ARCHITECTURE}") + endif() set(CPACK_PACKAGE_NAME "maxscale") set(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab") set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/etc/DESCRIPTION) diff --git a/Documentation/About/Limitations.md b/Documentation/About/Limitations.md index 4677640a9..ec0d7f357 100644 --- a/Documentation/About/Limitations.md +++ b/Documentation/About/Limitations.md @@ -10,8 +10,6 @@ This section describes the limitations that are common to all configuration of p Compression is not included in MySQL server handshake -## Limitations with MySQL Master/Slave Replication monitoring - ## Limitations with Galera Cluster Monitoring Master selection is based only on MIN(wsrep_local_index), no other server parameter. @@ -35,7 +33,9 @@ In master-slave replication cluster also read-only queries are routed to master * statement includes a stored procedure, or an UDF call ### Limitations in client session handling + Some of the queries that client sends are routed to all backends instead of sending them just to one of server. These queries include `USE ` and `SET autocommit=0` among many others. Readwritesplit sends a copy of these queries to each backend server and forwards the master's reply to the client. Below is a list of MySQL commands which are classified as session commands : + ``` COM_INIT_DB (USE creates this) @@ -90,4 +90,4 @@ Most imaginable reasons are related to replication lag but it could be possible ## Authentication Related Limitations -MySQL old passwords are not supported +MySQL old style passwords are not supported. MySQL versions 4.1 and newer use a new authentication protocol which does not support pre-4.1 style passwords. diff --git a/Documentation/Documentation-Contents.md b/Documentation/Documentation-Contents.md index ddfd54ba4..14248e222 100644 --- a/Documentation/Documentation-Contents.md +++ b/Documentation/Documentation-Contents.md @@ -20,7 +20,7 @@ ## Upgrading MaxScale -- [Upgrading MaxScale from 1.1.1 to 1.2.0](Upgrading/Upgrading-To-MaxScale-1.2.0.md) +- [Upgrading MaxScale from 1.1.1 to 1.2](Upgrading/Upgrading-To-MaxScale-1.2.md) - [Upgrading MaxScale from 1.0.5 to 1.1.0](Upgrading/Upgrading-To-MaxScale-1.1.0.md) ## Reference diff --git a/Documentation/Routers/ReadWriteSplit.md b/Documentation/Routers/ReadWriteSplit.md index f75a5873b..ec89db65f 100644 --- a/Documentation/Routers/ReadWriteSplit.md +++ b/Documentation/Routers/ReadWriteSplit.md @@ -73,9 +73,12 @@ When value all is used, queries reading session variables can be routed to any a In above-mentioned case the user-defined variable would only be updated in the master where query would be routed due to `INSERT` statement. -**`max_sescmd_history`** sets a limit on how many session commands each session can execute before the connection is closed. The default is an unlimited number of session commands. +**`max_sescmd_history`** sets a limit on how many session commands each session can execute before the session command history is disabled. The default is an unlimited number of session commands. - max_sescmd_history=1500 +``` +# Set a limit on the session command history +max_sescmd_history=1500 +``` When a limitation is set, it effectively creates a cap on the session's memory consumption. This might be useful if connection pooling is used and the sessions use large amounts of session commands. @@ -86,13 +89,6 @@ When a limitation is set, it effectively creates a cap on the session's memory c disable_sescmd_history=true ``` -**`disable_slave_recovery`** disables the recovery and replacement of slave servers. If this option is enabled and a connection to a slave server in use is lost, no replacement slave will be taken. This allows the safe use of session state modifying statements when the session command history is disabled. This is mostly intended to be used with the `disable_sescmd_history` option enabled. - -``` -# Disable the session command history -disable_slave_recovery=true -``` - **`master_accept_reads`** allows the master server to be used for reads. This is a useful option to enable if you are using a small number of servers and wish to use the master for reads as well. ``` diff --git a/Documentation/Upgrading/Upgrading-To-MaxScale-1.2.0.md b/Documentation/Upgrading/Upgrading-To-MaxScale-1.2.md similarity index 100% rename from Documentation/Upgrading/Upgrading-To-MaxScale-1.2.0.md rename to Documentation/Upgrading/Upgrading-To-MaxScale-1.2.md diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index 0f0b00884..c2de0c854 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -23,12 +23,12 @@ endif() target_link_libraries(maxscale ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ${CURL_LIBRARIES} log_manager utils ssl aio pthread crypt dl crypto inih z rt m stdc++) install(TARGETS maxscale DESTINATION ${MAXSCALE_BINDIR}) -add_executable(maxkeys maxkeys.c secrets.c utils.c gwdirs.c spinlock.c random_jkiss.c) -target_link_libraries(maxkeys log_manager utils pthread crypt crypto) +add_executable(maxkeys maxkeys.c spinlock.c secrets.c utils.c gwdirs.c random_jkiss.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc) +target_link_libraries(maxkeys utils pthread crypt crypto) install(TARGETS maxkeys DESTINATION ${MAXSCALE_BINDIR}) -add_executable(maxpasswd maxpasswd.c secrets.c utils.c gwdirs.c spinlock.c random_jkiss.c) -target_link_libraries(maxpasswd log_manager utils pthread crypt crypto) +add_executable(maxpasswd maxpasswd.c spinlock.c secrets.c utils.c gwdirs.c random_jkiss.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc) +target_link_libraries(maxpasswd utils pthread crypt crypto) install(TARGETS maxpasswd DESTINATION ${MAXSCALE_BINDIR}) if(BUILD_TESTS) diff --git a/server/core/adminusers.c b/server/core/adminusers.c index 8af593506..81df4bf4f 100644 --- a/server/core/adminusers.c +++ b/server/core/adminusers.c @@ -29,7 +29,7 @@ #include #include #include - +#include /** Defined in log_manager.cc */ extern int lm_enabled_logfiles_bitmask; extern size_t log_ses_count[]; @@ -154,6 +154,11 @@ FILE *fp; char fname[1024], *home, *cpasswd; initialise(); + + if(access(get_datadir(), F_OK) != 0) + if(mkdir(get_datadir(), S_IRWXU) != 0 && errno != EEXIST) + return ADMIN_ERR_PWDFILEOPEN; + snprintf(fname,1023, "%s/passwd", get_datadir()); fname[1023] = '\0'; if (users == NULL) diff --git a/server/core/config.c b/server/core/config.c index 1a963d562..463122138 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -2334,6 +2334,7 @@ static char *InternalRouters[] = { "cli", "maxinfo", "binlogrouter", + "testroute", NULL }; diff --git a/server/core/gateway.c b/server/core/gateway.c index 0907d6365..f0744cfd1 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -1670,7 +1670,7 @@ int main(int argc, char **argv) if(!daemon_mode) { strncat(errorbuffer, "\n", STRING_BUFFER_SIZE); - fprintf(stderr, errorbuffer); + fprintf(stderr, "%s", errorbuffer); } rc = MAXSCALE_BADCONFIG; diff --git a/server/core/test/testadminusers.c b/server/core/test/testadminusers.c index f9c34e500..cfa9be6ba 100644 --- a/server/core/test/testadminusers.c +++ b/server/core/test/testadminusers.c @@ -270,7 +270,7 @@ char *home, buf[1024]; /* Unlink any existing password file before running this test */ - sprintf(buf, "%s/passwd", default_cachedir); + sprintf(buf, "%s/passwd", get_datadir()); if(!is_valid_posix_path(buf)) exit(1); if (strcmp(buf, "/etc/passwd") != 0) diff --git a/server/core/test/testbuffer.c b/server/core/test/testbuffer.c index 73d71dc27..179300be3 100644 --- a/server/core/test/testbuffer.c +++ b/server/core/test/testbuffer.c @@ -27,6 +27,13 @@ * @endverbatim */ +// To ensure that ss_info_assert asserts also when builing in non-debug mode. +#if !defined(SS_DEBUG) +#define SS_DEBUG +#endif +#if defined(NDEBUG) +#undef NDEBUG +#endif #include #include #include diff --git a/server/core/test/testdcb.c b/server/core/test/testdcb.c index 1eb8a1a88..9668d8a23 100644 --- a/server/core/test/testdcb.c +++ b/server/core/test/testdcb.c @@ -60,8 +60,8 @@ int buflen; ss_info_dassert(true, "Something is true"); ss_dfprintf(stderr, "\t..done\n"); dcb_close(dcb); - ss_dfprintf(stderr, "Closed original dcb"); - ss_info_dassert(!dcb_isvalid(dcb), "Closed DCB must not be valid"); + ss_dfprintf(stderr, "Freed original dcb"); + ss_info_dassert(!dcb_isvalid(dcb), "Freed DCB must not be valid"); ss_dfprintf(stderr, "\t..done\nMake clone DCB a zombie"); clone->state = DCB_STATE_NOPOLLING; dcb_close(clone); diff --git a/server/core/test/testfeedback.c b/server/core/test/testfeedback.c index 2947b0975..c1d53b9cc 100644 --- a/server/core/test/testfeedback.c +++ b/server/core/test/testfeedback.c @@ -41,6 +41,7 @@ #include #include #include +#include static char* server_options[] = { "MariaDB Corporation MaxScale", @@ -65,6 +66,7 @@ static char* server_groups[] = { }; int config_load(char *); +void config_enable_feedback_task(void); int module_create_feedback_report(GWBUF **buffer, MODULES *modules, FEEDBACK_CONF *cfg); int do_http_post(GWBUF *buffer, void *cfg); @@ -78,7 +80,8 @@ int main(int argc, char** argv) hkinit(); - cnf = strdup("/etc/MaxScale.cnf"); + cnf = malloc(sizeof(char) * (strlen(TEST_DIR) + strlen("/maxscale.cnf") + 1)); + sprintf(cnf, "%s/maxscale.cnf", TEST_DIR); printf("Config: %s\n",cnf); @@ -89,7 +92,7 @@ int main(int argc, char** argv) } config_load(cnf); - + config_enable_feedback_task(); if ((fc = config_get_feedback_data()) == NULL) { FAILTEST("Configuration for Feedback was NULL."); diff --git a/server/core/test/testmemlog.c b/server/core/test/testmemlog.c index 1523ec8ec..d1cad08ae 100644 --- a/server/core/test/testmemlog.c +++ b/server/core/test/testmemlog.c @@ -67,7 +67,7 @@ int main() { MEMLOG *log, *log2; -int i; +long int i; long j; long long k; int failures = 0; diff --git a/server/core/test/testmodutil.c b/server/core/test/testmodutil.c index f8fe7ef24..39632ab6d 100644 --- a/server/core/test/testmodutil.c +++ b/server/core/test/testmodutil.c @@ -70,10 +70,11 @@ int test2() { GWBUF *buffer; -char len = 128; +unsigned int len = 128; char query[129]; - buffer = gwbuf_alloc(132); + /** Allocate space for the COM_QUERY header and payload */ + buffer = gwbuf_alloc(5 + 128); ss_info_dassert((buffer != NULL),"Buffer should not be null"); memset(query,';',128); diff --git a/server/core/test/testservice.c b/server/core/test/testservice.c index f45fd2afc..5fa7e0436 100644 --- a/server/core/test/testservice.c +++ b/server/core/test/testservice.c @@ -27,6 +27,13 @@ * @endverbatim */ +// To ensure that ss_info_assert asserts also when builing in non-debug mode. +#if !defined(SS_DEBUG) +#define SS_DEBUG +#endif +#if defined(NDEBUG) +#undef NDEBUG +#endif #include #include #include @@ -34,15 +41,6 @@ #include #include - -static bool success = false; - -int hup(DCB* dcb) -{ - success = true; - return 1; -} - /** * test1 Allocate a service and do lots of other things * @@ -57,17 +55,6 @@ int result; int argc = 3; init_test_env(NULL); -/* char* argv[] = */ -/* { */ -/* "log_manager", */ -/* "-j", */ -/* TEST_LOG_DIR, */ -/* NULL */ -/* }; */ - -/* skygw_logmanager_init(argc,argv); */ -/* poll_init(); */ -/* hkinit(); */ /* Service tests */ ss_dfprintf(stderr, @@ -91,9 +78,9 @@ init_test_env(NULL); result = serviceStart(service); skygw_log_sync_all(); ss_info_dassert(0 != result, "Start should succeed"); - result = serviceStop(service); + serviceStop(service); skygw_log_sync_all(); - ss_info_dassert(0 != result, "Stop should succeed"); + ss_info_dassert(service->state == SERVICE_STATE_STOPPED, "Stop should succeed"); result = serviceStartAll(); skygw_log_sync_all(); ss_info_dassert(0 != result, "Start all should succeed"); @@ -104,35 +91,26 @@ init_test_env(NULL); result = serviceStart(service); skygw_log_sync_all(); ss_info_dassert(0 != result, "Start should succeed"); - result = serviceStop(service); + serviceStop(service); skygw_log_sync_all(); - ss_info_dassert(0 != result, "Stop should succeed"); + ss_info_dassert(service->state == SERVICE_STATE_STOPPED, "Stop should succeed"); - if((dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER)) == NULL) - return 1; + if((dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER)) == NULL) + return 1; ss_info_dassert(dcb != NULL, "DCB allocation failed"); session = session_alloc(service,dcb); ss_info_dassert(session != NULL, "Session allocation failed"); - session->client->state = DCB_STATE_POLLING; - session->client->func.hangup = hup; + dcb->state = DCB_STATE_POLLING; sleep(15); - ss_info_dassert(success, "Session timeout failed"); + ss_info_dassert(dcb->state != DCB_STATE_POLLING, "Session timeout failed"); ss_dfprintf(stderr, "\t..done\nStopping Service."); - ss_info_dassert(0 != serviceStop(service), "Stop should succeed"); + serviceStop(service); + ss_info_dassert(service->state == SERVICE_STATE_STOPPED, "Stop should succeed"); ss_dfprintf(stderr, "\t..done\n"); - /** This is never used in MaxScale and will always fail due to service's - * stats.n_current value never being decremented */ -/* - - ss_dfprintf(stderr, "\t..done\nFreeing Service."); - ss_info_dassert(0 != service_free(service), "Free should succeed"); - ss_dfprintf(stderr, "\t..done\n"); - -*/ return 0; } diff --git a/server/core/test/testspinlock.c b/server/core/test/testspinlock.c index 14501cea5..ed8fa7214 100644 --- a/server/core/test/testspinlock.c +++ b/server/core/test/testspinlock.c @@ -151,11 +151,14 @@ test3_helper(void *data) // SPINLOCK *lck = (SPINLOCK *)data; int i; int n = *(int *)data; -struct timespec sleeptime; time_t rawtime; +#if defined(ADD_SOME_NANOSLEEP) +struct timespec sleeptime; + sleeptime.tv_sec = 0; sleeptime.tv_nsec = 1; +#endif while (1) { if (spinlock_acquire_nowait(&lck)) { @@ -185,7 +188,9 @@ time_t rawtime; active = 0; spinlock_release(&lck); for (i=0; i<(4*PROCESS_LOOP); i++); - // nanosleep(&sleeptime, NULL); +#if defined(ADD_SOME_NANOSLEEP) + nanosleep(&sleeptime, NULL); +#endif } spinlock_release(&lck); } @@ -199,11 +204,6 @@ int i; int tnum[THREADS]; time_t rawtime; -struct timespec sleeptime; - - sleeptime.tv_sec = 20; - sleeptime.tv_nsec = NANOTIME; - times_run = 0; active = 0; failures = 0; diff --git a/server/core/test/testusers.c b/server/core/test/testusers.c index d947075a0..4385d74eb 100644 --- a/server/core/test/testusers.c +++ b/server/core/test/testusers.c @@ -27,6 +27,13 @@ * @endverbatim */ +// To ensure that ss_info_assert asserts also when builing in non-debug mode. +#if !defined(SS_DEBUG) +#define SS_DEBUG +#endif +#if defined(NDEBUG) +#undef NDEBUG +#endif #include #include #include diff --git a/server/modules/filter/dbfwfilter.c b/server/modules/filter/dbfwfilter.c index e3850f841..8f64139c8 100644 --- a/server/modules/filter/dbfwfilter.c +++ b/server/modules/filter/dbfwfilter.c @@ -472,73 +472,55 @@ bool check_time(char* str) #endif #define IS_RVRS_TIME(tr) (mktime(&tr->end) < mktime(&tr->start)) + /** - * Parses a null-terminated string into two tm_t structs that mark a timerange + * Parses a null-terminated string into a timerange defined by two ISO-8601 compliant + * times separated by a single dash. The times are interpreted at one second precision + * and follow the extended format by separating the hours, minutes and seconds with + * semicolons. * @param str String to parse * @param instance FW_FILTER instance * @return If successful returns a pointer to the new TIMERANGE instance. If errors occurred or * the timerange was invalid, a NULL pointer is returned. */ -TIMERANGE* parse_time(char* str, FW_INSTANCE* instance) +static TIMERANGE* parse_time(const char* str) { + assert(str != NULL); - TIMERANGE* tr = NULL; - int intbuffer[3]; - int* idest = intbuffer; - char strbuffer[3]; - char *ptr,*sdest; - struct tm* tmptr; + char strbuf[strlen(str) + 1]; + char *separator; + struct tm start, end; + TIMERANGE* tr = NULL; - assert(str != NULL && instance != NULL); - - tr = (TIMERANGE*)calloc(1,sizeof(TIMERANGE)); + strcpy(strbuf, str); - if(tr == NULL){ - skygw_log_write(LOGFILE_ERROR, "dbfwfilter: malloc returned NULL."); - return NULL; - } + if ((separator = strchr(strbuf, '-'))) + { + *separator++ = '\0'; + if (strptime(strbuf, "%H:%M:%S", &start) && + strptime(separator, "%H:%M:%S", &end)) + { + /** The time string was valid */ + CHK_TIMES((&start)); + CHK_TIMES((&end)); - memset(&tr->start,0,sizeof(struct tm)); - memset(&tr->end,0,sizeof(struct tm)); - ptr = str; - sdest = strbuffer; - tmptr = &tr->start; + tr = (TIMERANGE*) malloc(sizeof(TIMERANGE)); - while(ptr - str < 19){ - if(isdigit(*ptr)){ - *sdest = *ptr; - }else if(*ptr == ':' ||*ptr == '-' || *ptr == '\0' || *ptr == ' '){ - *sdest = '\0'; - *idest++ = atoi(strbuffer); - sdest = strbuffer; - - if(*ptr == '-' || *ptr == '\0'){ - - tmptr->tm_hour = intbuffer[0]; - tmptr->tm_min = intbuffer[1]; - tmptr->tm_sec = intbuffer[2]; - - CHK_TIMES(tmptr); - - if(*ptr == '\0' || *ptr == ' '){ - return tr; - } - - idest = intbuffer; - tmptr = &tr->end; - } - ptr++; - continue; - } - ptr++; - sdest++; - } - - free(tr); - return NULL; + if (tr) + { + tr->start = start; + tr->end = end; + tr->next = NULL; + } + else + { + skygw_log_write(LOGFILE_ERROR, "dbfwfilter: malloc returned NULL."); + } + } + } + return tr; } - /** * Splits the reversed timerange into two. *@param tr A reversed timerange @@ -1020,7 +1002,7 @@ bool parse_rule(char* rule, FW_INSTANCE* instance) goto retblock; } - TIMERANGE *tmp = parse_time(tok,instance); + TIMERANGE *tmp = parse_time(tok); if(tmp == NULL) { diff --git a/server/modules/include/readwritesplit.h b/server/modules/include/readwritesplit.h index c78cde5b4..9f9866e5d 100644 --- a/server/modules/include/readwritesplit.h +++ b/server/modules/include/readwritesplit.h @@ -242,19 +242,17 @@ typedef struct backend_ref_st { #endif } backend_ref_t; - -typedef struct rwsplit_config_st { - int rw_max_slave_conn_percent; - int rw_max_slave_conn_count; - select_criteria_t rw_slave_select_criteria; - int rw_max_slave_replication_lag; - target_t rw_use_sql_variables_in; - int rw_max_sescmd_history_size; - bool disable_sescmd_hist; - bool disable_slave_recovery; - bool master_reads; /*< Use master for reads */ +typedef struct rwsplit_config_st +{ + int rw_max_slave_conn_percent; + int rw_max_slave_conn_count; + select_criteria_t rw_slave_select_criteria; + int rw_max_slave_replication_lag; + target_t rw_use_sql_variables_in; + int rw_max_sescmd_history_size; + bool rw_disable_sescmd_hist; + bool rw_master_reads; /*< Use master for reads */ } rwsplit_config_t; - #if defined(PREP_STMT_CACHING) diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index f0d96d171..3587eb8fb 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -1831,8 +1831,8 @@ static int gw_error_client_event( } #if defined(SS_DEBUG) - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, + LOGIF(LD, (skygw_log_write_flush( + LOGFILE_DEBUG, "Client error event handling."))); #endif dcb_close(dcb); diff --git a/server/modules/protocol/mysql_common.c b/server/modules/protocol/mysql_common.c index b3dfc37be..354820d4a 100644 --- a/server/modules/protocol/mysql_common.c +++ b/server/modules/protocol/mysql_common.c @@ -2261,7 +2261,7 @@ char *create_auth_fail_str( } else if(errcode == MYSQL_FAILED_AUTH_SSL) { - sprintf(errstr, ferrstr); + sprintf(errstr, "%s", ferrstr); } else { diff --git a/server/modules/routing/binlog/CMakeLists.txt b/server/modules/routing/binlog/CMakeLists.txt index 801252103..232edb289 100644 --- a/server/modules/routing/binlog/CMakeLists.txt +++ b/server/modules/routing/binlog/CMakeLists.txt @@ -16,8 +16,10 @@ add_executable(maxbinlogcheck maxbinlogcheck.c blr_file.c blr_cache.c blr_master ${CMAKE_SOURCE_DIR}/server/core/resultset.c ${CMAKE_SOURCE_DIR}/server/core/load_utils.c ${CMAKE_SOURCE_DIR}/server/core/monitor.c ${CMAKE_SOURCE_DIR}/server/core/gw_utils.c ${CMAKE_SOURCE_DIR}/server/core/thread.c ${CMAKE_SOURCE_DIR}/server/core/secrets.c - ${CMAKE_SOURCE_DIR}/server/core/random_jkiss.c) + ${CMAKE_SOURCE_DIR}/server/core/random_jkiss.c + ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc) -target_link_libraries(maxbinlogcheck utils ssl pthread log_manager ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} aio rt crypt dl crypto inih z m stdc++ ${CURL_LIBRARIES}) + +target_link_libraries(maxbinlogcheck utils ssl pthread ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} aio rt crypt dl crypto inih z m stdc++ ${CURL_LIBRARIES}) install(TARGETS maxbinlogcheck DESTINATION bin) diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index 074b40475..92332d8ec 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -705,7 +705,7 @@ createInstance(SERVICE *service, char **options) } /** These options cancel each other out */ - if(router->rwsplit_config.disable_sescmd_hist && router->rwsplit_config.rw_max_sescmd_history_size > 0) + if(router->rwsplit_config.rw_disable_sescmd_hist && router->rwsplit_config.rw_max_sescmd_history_size > 0) { router->rwsplit_config.rw_max_sescmd_history_size = 0; } @@ -1249,7 +1249,7 @@ static bool get_dcb( (max_rlag == MAX_RLAG_UNDEFINED || (b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE && b->backend_server->rlag <= max_rlag)) && - !rses->rses_config.master_reads) + !rses->rses_config.rw_master_reads) { /** found slave */ candidate_bref = &backend_ref[i]; @@ -2025,6 +2025,9 @@ static int routeQuery( } else { + /** route_single_stmt expects the buffer to be contiguous. */ + querybuf = gwbuf_make_contiguous(querybuf); + succp = route_single_stmt(inst, router_cli_ses, querybuf); } } @@ -2056,6 +2059,9 @@ static int routeQuery( } else { + /** route_single_stmt expects the buffer to be contiguous. */ + querybuf = gwbuf_make_contiguous(querybuf); + succp = route_single_stmt(inst, router_cli_ses, querybuf); } @@ -2111,6 +2117,7 @@ static bool route_single_stmt( int rlag_max = MAX_RLAG_UNDEFINED; backend_type_t btype; /*< target backend type */ + ss_dassert(querybuf->next == NULL); // The buffer must be contiguous. ss_dassert(!GWBUF_IS_TYPE_UNDEFINED(querybuf)); /** @@ -2133,12 +2140,6 @@ static bool route_single_stmt( succp = false; goto retblock; } - - /** If buffer is not contiguous, make it such */ - if (querybuf->next != NULL) - { - querybuf = gwbuf_make_contiguous(querybuf); - } packet = GWBUF_DATA(querybuf); packet_len = gw_mysql_get_byte3(packet); @@ -2899,7 +2900,7 @@ static void clientReply ( bool rconn = false; writebuf = sescmd_cursor_process_replies(writebuf, bref, &rconn); - if(rconn && !router_inst->rwsplit_config.disable_slave_recovery) + if(rconn && !router_inst->rwsplit_config.rw_disable_sescmd_hist) { select_connect_backend_servers(&router_cli_ses->rses_master_ref, router_cli_ses->rses_backend_ref, @@ -4543,21 +4544,17 @@ static bool route_session_write( goto return_succp; } - if(router_cli_ses->rses_config.rw_max_sescmd_history_size > 0 && - router_cli_ses->rses_nsescmd >= router_cli_ses->rses_config.rw_max_sescmd_history_size) - { - LOGIF(LT, (skygw_log_write( - LOGFILE_TRACE, - "Router session exceeded session command history limit. " - "Closing router session. <"))); - gwbuf_free(querybuf); - rses_end_locked_router_action(router_cli_ses); - router_cli_ses->client_dcb->func.hangup(router_cli_ses->client_dcb); - - goto return_succp; - } + if (router_cli_ses->rses_config.rw_max_sescmd_history_size > 0 && + router_cli_ses->rses_nsescmd >= router_cli_ses->rses_config.rw_max_sescmd_history_size) + { + skygw_log_write(LE, "Warning: Router session exceeded session command history limit. " + "Slave recovery is disabled and only slave servers with consistent session state are used " + "for the duration of the session."); + router_cli_ses->rses_config.rw_disable_sescmd_hist = true; + router_cli_ses->rses_config.rw_max_sescmd_history_size = 0; + } - if(router_cli_ses->rses_config.disable_sescmd_hist) + if(router_cli_ses->rses_config.rw_disable_sescmd_hist) { rses_property_t *prop, *tmp; backend_ref_t* bref; @@ -4786,15 +4783,11 @@ static void rwsplit_process_router_options( } else if(strcmp(options[i],"disable_sescmd_history") == 0) { - router->rwsplit_config.disable_sescmd_hist = config_truth_value(value); - } - else if(strcmp(options[i],"disable_slave_recovery") == 0) - { - router->rwsplit_config.disable_slave_recovery = config_truth_value(value); + router->rwsplit_config.rw_disable_sescmd_hist = config_truth_value(value); } else if(strcmp(options[i],"master_accept_reads") == 0) { - router->rwsplit_config.master_reads = config_truth_value(value); + router->rwsplit_config.rw_master_reads = config_truth_value(value); } } } /*< for */ @@ -5058,7 +5051,7 @@ static bool handle_error_new_connection( * Try to get replacement slave or at least the minimum * number of slave connections for router session. */ - if(inst->rwsplit_config.disable_slave_recovery) + if(inst->rwsplit_config.rw_disable_sescmd_hist) { succp = have_enough_servers(&myrses,1,router_nservers,inst) ? true : false; } diff --git a/server/modules/routing/readwritesplit/test/test_hints/rwsplit_hints.sh b/server/modules/routing/readwritesplit/test/test_hints/rwsplit_hints.sh index 67de5d4f6..46241d4c3 100755 --- a/server/modules/routing/readwritesplit/test/test_hints/rwsplit_hints.sh +++ b/server/modules/routing/readwritesplit/test/test_hints/rwsplit_hints.sh @@ -26,7 +26,7 @@ else TDIR=. fi -RUNCMD=mysql\ --host=$THOST\ -P$TPORT\ -u$TUSER\ -p$TPWD\ --unbuffered=true\ --disable-reconnect\ --silent\ --comment +RUNCMD="mysql --host=$THOST -P$TPORT -u$TUSER -p$TPWD --unbuffered=true --disable-reconnect --silent -c" i=0 while read -r LINE