diff --git a/Documentation/Routers/ReadWriteSplit.md b/Documentation/Routers/ReadWriteSplit.md index c6e5f456f..18a7aa3d4 100644 --- a/Documentation/Routers/ReadWriteSplit.md +++ b/Documentation/Routers/ReadWriteSplit.md @@ -52,7 +52,7 @@ passwd= ### `max_slave_connections` -**`max_slave_connections`** sets the maximum number of slaves a router session uses at any moment. Default value is `1`. +**`max_slave_connections`** sets the maximum number of slaves a router session uses at any moment. The default is to use all available slaves. max_slave_connections= diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake index 43aec0bfa..4010c8e20 100644 --- a/cmake/FindMySQL.cmake +++ b/cmake/FindMySQL.cmake @@ -15,9 +15,9 @@ endif() file(READ ${MYSQL_VERSION_H} MYSQL_VERSION_CONTENTS) string(REGEX REPLACE ".*MYSQL_SERVER_VERSION[^0-9.]+([0-9.]+).*" "\\1" MYSQL_VERSION ${MYSQL_VERSION_CONTENTS}) -string(REGEX REPLACE ".*MYSQL_COMPILATION_COMMENT.+\"(.+)\".*" "\\1" MYSQL_PROVIDER ${MYSQL_VERSION_CONTENTS}) +string(REGEX REPLACE ".*MYSQL_COMPILATION_COMMENT[[:space:]]+\"(.+)\".*" "\\1" MYSQL_PROVIDER ${MYSQL_VERSION_CONTENTS}) string(TOLOWER ${MYSQL_PROVIDER} MYSQL_PROVIDER) -if(MYSQL_PROVIDER MATCHES "mariadb") +if(MYSQL_PROVIDER MATCHES "[mM]aria[dD][bB]") set(MYSQL_PROVIDER "MariaDB" CACHE INTERNAL "The MySQL provider") elseif(MYSQL_PROVIDER MATCHES "mysql") set(MYSQL_PROVIDER "MySQL" CACHE INTERNAL "The MySQL provider") @@ -36,6 +36,17 @@ if(MYSQL_VERSION VERSION_LESS 5.5.41) message(WARNING "MySQL version is ${MYSQL_VERSION}. Minimum supported version is 5.5.41.") endif() +if(NOT (MYSQL_VERSION VERSION_LESS 10.1)) + + # 10.1 needs lzma + find_library(HAVE_LIBLZMA NAMES lzma) + if(NOT HAVE_LIBLZMA) + message(FATAL_ERROR "Could not find liblzma") + endif() + set(LZMA_LINK_FLAGS "lzma" CACHE STRING "liblzma link flags") +endif() + + if (DEFINED EMBEDDED_LIB) if( NOT (IS_DIRECTORY ${EMBEDDED_LIB}) ) debugmsg("EMBEDDED_LIB is not a directory: ${EMBEDDED_LIB}") diff --git a/log_manager/log_manager.cc b/log_manager/log_manager.cc index 81b386d66..01a17178d 100644 --- a/log_manager/log_manager.cc +++ b/log_manager/log_manager.cc @@ -2208,13 +2208,11 @@ static bool thr_flush_file(logmanager_t *lm, filewriter_t *fwr) if (!succ) { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Error : Log rotation failed. " - "Creating replacement file %s " - "failed. Continuing " - "logging to existing file.", - lf->lf_full_file_name))); + MXS_ERROR("Log rotation failed. " + "Creating replacement file %s " + "failed. Continuing " + "logging to existing file.", + lf->lf_full_file_name); } return true; } diff --git a/log_manager/log_manager.h b/log_manager/log_manager.h index 2047d8462..751ad8647 100644 --- a/log_manager/log_manager.h +++ b/log_manager/log_manager.h @@ -96,15 +96,6 @@ extern __thread log_info_t tls_log_info; // TODO: Add this at a later stage. #define MXS_LOG_PRIORITY_IS_ENABLED(priority) false -/** - * Execute the given command if specified log is enabled in general or - * if the log is enabled for the current session. - */ -#define LOGIF(id,cmd) if (LOG_IS_ENABLED(id)) \ - { \ - cmd; \ - } - /** * LOG_AUGMENT_WITH_FUNCTION Each logged line is suffixed with [function-name]. */ @@ -130,23 +121,15 @@ void mxs_log_set_augmentation(int bits); int mxs_log_message(int priority, const char* file, int line, const char* function, const char* format, ...) __attribute__((format(printf, 5, 6))); - -inline int mxs_log_id_to_priority(logfile_id_t id) -{ - if (id & LOGFILE_ERROR) return LOG_ERR; - if (id & LOGFILE_MESSAGE) return LOG_NOTICE; - if (id & LOGFILE_TRACE) return LOG_INFO; - if (id & LOGFILE_DEBUG) return LOG_DEBUG; - return LOG_ERR; -} - -#define skygw_log_write(id, format, ...)\ - mxs_log_message(mxs_log_id_to_priority(id), __FILE__, __LINE__, __func__, format, ##__VA_ARGS__) - -#define skygw_log_write_flush(id, format, ...) skygw_log_write(id, format, ##__VA_ARGS__) - /** - * Helper, not to be called directly. + * Log an error, warning, notice, info, or debug message. + * + * @param priority One of the syslog constants (LOG_ERR, LOG_WARNING, ...) + * @param format The printf format of the message. + * @param ... Arguments, depending on the format. + * + * NOTE: Should typically not be called directly. Use some of the + * MXS_ERROR, MXS_WARNING, etc. macros instead. */ #define MXS_LOG_MESSAGE(priority, format, ...)\ mxs_log_message(priority, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__) diff --git a/log_manager/test/testlog.c b/log_manager/test/testlog.c index 6983067ea..c2d907d89 100644 --- a/log_manager/test/testlog.c +++ b/log_manager/test/testlog.c @@ -161,28 +161,27 @@ int main(int argc, char* argv[]) ss_dassert(succp); t = time(NULL); - tm = *(localtime(&t)); - err = skygw_log_write_flush(LOGFILE_ERROR, - "%04d %02d/%02d %02d.%02d.%02d", - tm.tm_year+1900, - tm.tm_mon+1, - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec); + localtime_r(&t, &tm); + err = MXS_ERROR("%04d %02d/%02d %02d.%02d.%02d", + tm.tm_year+1900, + tm.tm_mon+1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("First write with flush."); - err = skygw_log_write_flush(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); logstr = ("Second write with flush."); - err = skygw_log_write_flush(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); logstr = ("Third write, no flush."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); logstr = ("Fourth write, no flush. Next flush only."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); err = mxs_log_flush(); @@ -190,57 +189,57 @@ int main(int argc, char* argv[]) #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif - err = skygw_log_write(LOGFILE_TRACE, logstr, "TraceyTracey", 3, 7); + err = MXS_INFO(logstr, "TraceyTracey", 3, 7); mxs_log_flush(); #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif logstr = "My name is Tracey Tracey 47 years and 7 months."; - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif logstr = "My name is Stacey %s"; - err = skygw_log_write_flush(LOGFILE_TRACE, logstr, " "); + err = MXS_INFO(logstr, " "); mxs_log_finish(); #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif logstr = "My name is Philip"; - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif logstr = "Philip."; - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif logstr = "Ph%dlip."; - err = skygw_log_write(LOGFILE_TRACE, logstr, 1); + err = MXS_INFO(logstr, 1); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("A terrible error has occurred!"); - err = skygw_log_write_flush(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); logstr = ("Hi, how are you?"); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); logstr = ("I'm doing fine!"); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); logstr = ("Rather more surprising, at least at first sight, is the fact that a reference to " "a[i] can also be written as *(a+i). In evaluating a[i], C converts it to *(a+i) " "immediately; the two forms are equivalent. Applying the operators & to both parts " "of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the " "address of the i-th element beyond a."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); logstr = ("I was wondering, you know, it has been such a lovely weather whole morning and I " "thought that would you like to come to my place and have a little piece of cheese " "with us. Just me and my mom - and you, of course. Then, if you wish, we could " "listen to the radio and keep company for our little Steven, my mom's cat, you know."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); mxs_log_finish(); #if defined(TEST1) @@ -369,60 +368,60 @@ int main(int argc, char* argv[]) ss_dassert(succp); logstr = ("\tTEST 3 - test enabling and disabling logs."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); skygw_log_disable(LOGFILE_TRACE); logstr = ("1.\tWrite once to ERROR and twice to MESSAGE log."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); skygw_log_enable(LOGFILE_TRACE); logstr = ("2.\tWrite to once to ERROR, twice to MESSAGE and " "three times to TRACE log."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); skygw_log_disable(LOGFILE_ERROR); logstr = ("3.\tWrite to once to MESSAGE and twice to TRACE log."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); skygw_log_disable(LOGFILE_MESSAGE); skygw_log_disable(LOGFILE_TRACE); logstr = ("4.\tWrite to none."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); skygw_log_enable(LOGFILE_ERROR); skygw_log_enable(LOGFILE_MESSAGE); logstr = ("4.\tWrite once to ERROR and twice to MESSAGE log."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); mxs_log_finish(); @@ -436,32 +435,32 @@ int main(int argc, char* argv[]) skygw_log_enable(LOGFILE_TRACE); #endif logstr = ("\tTEST 4 - test spreading logs down to other logs."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); logstr = ("1.\tWrite to ERROR and thus also to MESSAGE and TRACE logs."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); logstr = ("2.\tWrite to MESSAGE and thus to TRACE logs."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); skygw_log_enable(LOGFILE_TRACE); logstr = ("3.\tWrite to TRACE log only."); - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); skygw_log_disable(LOGFILE_MESSAGE); logstr = ("4.\tWrite to ERROR and thus also to TRACE log. " "MESSAGE is disabled."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); logstr = ("5.\tThis should not appear anywhere since MESSAGE " "is disabled."); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); mxs_log_finish(); @@ -472,51 +471,48 @@ int main(int argc, char* argv[]) skygw_log_enable(LOGFILE_TRACE); #endif logstr = ("6.\tWrite to ERROR and thus also to MESSAGE and TRACE logs."); - err = skygw_log_write_flush(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); logstr = ("7.\tWrite to MESSAGE and thus to TRACE logs."); - err = skygw_log_write_flush(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); logstr = ("8.\tWrite to TRACE log only."); skygw_log_enable(LOGFILE_TRACE); - err = skygw_log_write_flush(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); ss_dassert(err == 0); skygw_log_disable(LOGFILE_MESSAGE); logstr = ("9.\tWrite to ERROR and thus also to TRACE log. " "MESSAGE is disabled"); - err = skygw_log_write_flush(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); ss_dassert(err == 0); logstr = ("10.\tThis should not appear anywhere since MESSAGE is " "disabled."); - err = skygw_log_write_flush(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); ss_dassert(err == 0); skygw_log_enable(LOGFILE_MESSAGE); - err = skygw_log_write(LOGFILE_ERROR, - "11.\tWrite to all logs some formattings : " - "%d %s %d", - (int)3, - "foo", - (int)3); - err = skygw_log_write(LOGFILE_MESSAGE, - "12.\tWrite to MESSAGE and TRACE log some " - "formattings " - ": %d %s %d", - (int)3, - "foo", - (int)3); - err = skygw_log_write(LOGFILE_TRACE, - "13.\tWrite to TRACE log some formattings " - ": %d %s %d", - (int)3, - "foo", - (int)3); + err = MXS_ERROR("11.\tWrite to all logs some formattings : " + "%d %s %d", + (int)3, + "foo", + (int)3); + err = MXS_ERROR("12.\tWrite to MESSAGE and TRACE log some " + "formattings " + ": %d %s %d", + (int)3, + "foo", + (int)3); + err = MXS_ERROR("13.\tWrite to TRACE log some formattings " + ": %d %s %d", + (int)3, + "foo", + (int)3); ss_dassert(err == 0); @@ -542,7 +538,7 @@ static void* thr_run(void* data) mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); mxs_log_flush(); logstr = ("Hi, how are you?"); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); if (err != 0) { @@ -561,10 +557,10 @@ static void* thr_run(void* data) TEST_ERROR("Error, log write failed."); } ss_dassert(err == 0); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("Testing. One, two, three\n"); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -578,7 +574,7 @@ static void* thr_run(void* data) #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -591,7 +587,7 @@ static void* thr_run(void* data) "immediately; the two forms are equivalent. Applying the operatos & to both parts " "of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the " "address of the i-th element beyond a."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -603,7 +599,7 @@ static void* thr_run(void* data) mxs_log_finish(); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("..and you?"); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -615,7 +611,7 @@ static void* thr_run(void* data) #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -627,7 +623,7 @@ static void* thr_run(void* data) "immediately; the two forms are equivalent. Applying the operatos & to both parts " "of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the " "address of the i-th element beyond a."); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -635,7 +631,7 @@ static void* thr_run(void* data) ss_dassert(err == 0); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("..... and you too?"); - err = skygw_log_write(LOGFILE_MESSAGE, "%s", logstr); + err = MXS_NOTICE("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -651,7 +647,7 @@ static void* thr_run(void* data) #if !defined(SS_DEBUG) skygw_log_enable(LOGFILE_TRACE); #endif - err = skygw_log_write(LOGFILE_TRACE, "%s", logstr); + err = MXS_INFO("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -660,7 +656,7 @@ static void* thr_run(void* data) mxs_log_finish(); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("Testing. One, two, three, four\n"); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -669,7 +665,7 @@ static void* thr_run(void* data) mxs_log_finish(); mxs_log_init(NULL, "/tmp", LOG_TARGET_FS); logstr = ("Testing. One, two, three, .. where was I?\n"); - err = skygw_log_write(LOGFILE_ERROR, "%s", logstr); + err = MXS_ERROR("%s", logstr); if (err != 0) { TEST_ERROR("Error, log write failed."); @@ -726,7 +722,7 @@ static void* thr_run_morelog(void* data) for (i = 0; i < NITER; i++) { char* str = logs[rand() % nmsg]; - err = skygw_log_write((logfile_id_t)(rand()%(LOGFILE_LAST+1)), + err = MXS_LOG_MESSAGE((int)(rand() % (LOG_DEBUG+1)), "%s - iteration # %d", str, i); diff --git a/log_manager/test/testorder.c b/log_manager/test/testorder.c index 4bb23074e..7c757f9e7 100644 --- a/log_manager/test/testorder.c +++ b/log_manager/test/testorder.c @@ -124,11 +124,11 @@ int main(int argc, char** argv) memset(message + block_size - 1, '\0', 1); if (interval > 0 && i % interval == 0) { - err = skygw_log_write_flush(LOGFILE_ERROR, "%s", message); + err = MXS_ERROR("%s", message); } else { - err = skygw_log_write(LOGFILE_ERROR, "%s", message); + err = MXS_ERROR("%s", message); } if (err) { diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index 8cefd370d..b4301c519 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -352,7 +352,7 @@ static bool create_parse_tree( failp = TRUE; goto return_here; } - mysql_reset_thd_for_next_command(thd); + thd->reset_for_next_command(); /** * Set some database to thd so that parsing won't fail because of @@ -804,7 +804,7 @@ static bool skygw_stmt_causes_implicit_commit( switch (lex->sql_command) { case SQLCOM_DROP_TABLE: - succp = !(lex->drop_temporary); + succp = !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE); break; case SQLCOM_ALTER_TABLE: case SQLCOM_CREATE_TABLE: diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index 9687ee699..53004c811 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -5,7 +5,7 @@ if(BUILD_TESTS OR BUILD_TOOLS) elseif(WITH_TCMALLOC) target_link_libraries(fullcore ${TCMALLOC_LIBRARIES}) endif() - target_link_libraries(fullcore ${CURL_LIBRARIES} utils log_manager pthread ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ssl aio rt crypt dl crypto inih z m stdc++) + target_link_libraries(fullcore ${CURL_LIBRARIES} utils log_manager pthread ${LZMA_LINK_FLAGS} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ssl aio rt crypt dl crypto inih z m stdc++) add_dependencies(fullcore pcre2) endif() @@ -22,7 +22,7 @@ elseif(WITH_TCMALLOC) target_link_libraries(maxscale ${TCMALLOC_LIBRARIES}) 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++) +target_link_libraries(maxscale ${LZMA_LINK_FLAGS} ${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 spinlock.c secrets.c utils.c gwdirs.c random_jkiss.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc) diff --git a/server/core/config.c b/server/core/config.c index bbde33d69..b68c6733d 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -146,7 +146,7 @@ char* config_clean_string_list(char* str) int re_err; size_t err_offset; - if ((re = pcre2_compile((PCRE2_SPTR) "[[:space:],]*([^,]+)\\b[[:space:],]*", PCRE2_ZERO_TERMINATED, 0, + if ((re = pcre2_compile((PCRE2_SPTR) "[[:space:],]*([^,]*[^[:space:],])[[:space:],]*", PCRE2_ZERO_TERMINATED, 0, &re_err, &err_offset, NULL)) == NULL || (data = pcre2_match_data_create_from_pattern(re, NULL)) == NULL) { @@ -279,6 +279,7 @@ handler(void *userdata, const char *section, const char *name, const char *value param->name = strdup(name); param->value = strdup(value); param->next = ptr->parameters; + param->qfd_param_type = UNDEFINED_TYPE; ptr->parameters = param; return 1; diff --git a/server/core/dcb.c b/server/core/dcb.c index b4a35012a..10e436aaa 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -1986,9 +1986,9 @@ dprintOneDCB(DCB *pdcb, DCB *dcb) if (dcb->persistentstart) { char buff[20]; - struct tm * timeinfo; - timeinfo = localtime (&dcb->persistentstart); - strftime(buff, sizeof(buff), "%b %d %H:%M:%S", timeinfo); + struct tm timeinfo; + localtime_r(&dcb->persistentstart, &timeinfo); + strftime(buff, sizeof(buff), "%b %d %H:%M:%S", &timeinfo); dcb_printf(pdcb, "\t\tAdded to persistent pool: %s\n", buff); } } @@ -2160,9 +2160,9 @@ dprintDCB(DCB *pdcb, DCB *dcb) if (dcb->persistentstart) { char buff[20]; - struct tm * timeinfo; - timeinfo = localtime (&dcb->persistentstart); - strftime(buff, sizeof(buff), "%b %d %H:%M:%S", timeinfo); + struct tm timeinfo; + localtime_r(&dcb->persistentstart, &timeinfo); + strftime(buff, sizeof(buff), "%b %d %H:%M:%S", &timeinfo); dcb_printf(pdcb, "\t\tAdded to persistent pool: %s\n", buff); } } diff --git a/server/core/gateway.c b/server/core/gateway.c index 4bc1cbe48..27d6ae0e0 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -516,6 +516,8 @@ static bool file_write_footer( return succp; } +// Documentation says 26 bytes is enough, but 32 is a nice round number. +#define ASCTIME_BUF_LEN 32 static bool file_write_header( FILE* outfile) { @@ -524,10 +526,10 @@ static bool file_write_header( size_t len2; size_t len3; const char* header_buf1; - char* header_buf2 = NULL; + char header_buf2[ASCTIME_BUF_LEN]; const char* header_buf3; - time_t* t = NULL; - struct tm* tm = NULL; + time_t t; + struct tm tm; #if defined(LAPTOP_TEST) struct timespec ts1; ts1.tv_sec = 0; @@ -538,23 +540,10 @@ static bool file_write_header( return true; #endif - if ((t = (time_t *)malloc(sizeof(time_t))) == NULL) { - goto return_succp; - } - - if ((tm = (struct tm *)malloc(sizeof(struct tm))) == NULL) { - goto return_succp; - } - - *t = time(NULL); - *tm = *localtime(t); + localtime_r(&t, &tm); header_buf1 = "\n\nMariaDB Corporation MaxScale " MAXSCALE_VERSION "\t"; - header_buf2 = strdup(asctime(tm)); - - if (header_buf2 == NULL) { - goto return_succp; - } + asctime_r(&tm, header_buf2); header_buf3 = "------------------------------------------------------\n"; len1 = strlen(header_buf1); @@ -570,16 +559,6 @@ static bool file_write_header( succp = true; -return_succp: - if (tm != NULL) { - free(tm); - } - if (t != NULL) { - free(t); - } - if (header_buf2 != NULL) { - free(header_buf2); - } return succp; } @@ -1828,10 +1807,11 @@ int main(int argc, char **argv) if (!config_load(cnf_file_path)) { - char* fprerr = "Failed to load MaxScale configuration " + char* fprerr = + "Failed to open, read or process the MaxScale configuration " "file. Exiting. See the error log for details."; print_log_n_stderr(false, !daemon_mode, fprerr, fprerr, 0); - MXS_ERROR("Failed to load MaxScale configuration file %s. " + MXS_ERROR("Failed to open, read or process the MaxScale configuration file %s. " "Exiting.", cnf_file_path); rc = MAXSCALE_BADCONFIG; diff --git a/server/core/load_utils.c b/server/core/load_utils.c index 3f0259776..39e2db952 100644 --- a/server/core/load_utils.c +++ b/server/core/load_utils.c @@ -530,7 +530,8 @@ module_feedback_send(void* data) { int http_send = 0; now = time(NULL); - now_tm = localtime(&now); + struct tm now_result; + now_tm = localtime_r(&now, &now_result); hour = now_tm->tm_hour; FEEDBACK_CONF *feedback_config = (FEEDBACK_CONF *) data; diff --git a/server/core/service.c b/server/core/service.c index 89c5f21ec..a5ae6e8f9 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -1113,7 +1113,7 @@ serviceSetFilters(SERVICE *service, char *filters) } else { - MXS_WARNING("Unable to find filter '%s' for service '%s'\n", + MXS_ERROR("Unable to find filter '%s' for service '%s'\n", filter_name, service->name); rval = false; break; diff --git a/server/core/test/testusers.c b/server/core/test/testusers.c index fcc933b1a..efb0a9c87 100644 --- a/server/core/test/testusers.c +++ b/server/core/test/testusers.c @@ -59,7 +59,7 @@ int result, count; "testusers : Initialise the user table."); users = users_alloc(); mxs_log_flush_sync(); - ss_info_dassert(NULL != users, "Allocating user table should not return NULL.") + ss_info_dassert(NULL != users, "Allocating user table should not return NULL."); ss_dfprintf(stderr, "\t..done\nAdd a user"); count = users_add(users, "username", "authorisation"); mxs_log_flush_sync(); diff --git a/server/modules/filter/dbfwfilter.c b/server/modules/filter/dbfwfilter.c index 6fee69669..8a35813ad 100644 --- a/server/modules/filter/dbfwfilter.c +++ b/server/modules/filter/dbfwfilter.c @@ -1653,15 +1653,15 @@ GWBUF* gen_dummy_error(FW_SESSION* session, char* msg) bool inside_timerange(TIMERANGE* comp) { - struct tm* tm_now; + struct tm tm_now; struct tm tm_before, tm_after; time_t before, after, now, time_now; double to_before, to_after; time(&time_now); - tm_now = localtime(&time_now); - memcpy(&tm_before, tm_now, sizeof(struct tm)); - memcpy(&tm_after, tm_now, sizeof(struct tm)); + localtime_r(&time_now, &tm_now); + memcpy(&tm_before, &tm_now, sizeof(struct tm)); + memcpy(&tm_after, &tm_now, sizeof(struct tm)); tm_before.tm_sec = comp->start.tm_sec; @@ -1674,7 +1674,7 @@ bool inside_timerange(TIMERANGE* comp) before = mktime(&tm_before); after = mktime(&tm_after); - now = mktime(tm_now); + now = mktime(&tm_now); to_before = difftime(now, before); to_after = difftime(now, after); @@ -1730,10 +1730,10 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue QUERYSPEED* queryspeed = NULL; QUERYSPEED* rule_qs = NULL; time_t time_now; - struct tm* tm_now; + struct tm tm_now; time(&time_now); - tm_now = localtime(&time_now); + localtime_r(&time_now, &tm_now); matches = false; is_sql = modutil_is_SQL(queue) || modutil_is_SQL_prepare(queue); @@ -1781,7 +1781,9 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue { matches = true; msg = strdup("Permission denied at this time."); - MXS_INFO("dbfwfilter: rule '%s': query denied at: %s", rulelist->rule->name, asctime(tm_now)); + char buffer[32]; // asctime documentation requires 26 + asctime_r(&tm_now, buffer); + MXS_INFO("dbfwfilter: rule '%s': query denied at: %s", rulelist->rule->name, buffer); goto queryresolved; } else diff --git a/server/modules/filter/mqfilter.c b/server/modules/filter/mqfilter.c index 1587240bd..eace7fcb8 100644 --- a/server/modules/filter/mqfilter.c +++ b/server/modules/filter/mqfilter.c @@ -18,7 +18,7 @@ /** * @file mqfilter.c - * MQ Filter - AMQP Filter. + * MQ Filter - AMQP Filter. * A filter that logs and publishes canonized queries on to a RabbitMQ server. * * The filter reads the routed query, forms a canonized version of it and publishes the @@ -28,7 +28,7 @@ * * The filter makes no attempt to deal with queries that do not fit * in a single GWBUF or result sets that span multiple GWBUFs. - * + * * To use a SSL connection the CA certificate, the client certificate and the client public key must be provided. * By default this filter uses a TCP connection. *@verbatim @@ -49,7 +49,7 @@ * ssl_CA_cert Path to the CA certificate in PEM format * ssl_client_cert Path to the client cerificate in PEM format * ssl_client_key Path to the client public key in PEM format - * + * * The logging trigger levels are: * all Log everything * source Trigger on statements originating from a particular source (database user and host combination) @@ -80,11 +80,12 @@ #include #include -MODULE_INFO info = { - MODULE_API_FILTER, - MODULE_ALPHA_RELEASE, - FILTER_VERSION, - "A RabbitMQ query logging filter" +MODULE_INFO info = +{ + MODULE_API_FILTER, + MODULE_ALPHA_RELEASE, + FILTER_VERSION, + "A RabbitMQ query logging filter" }; static char *version_str = "V1.0.2"; @@ -93,46 +94,49 @@ static int hktask_id = 0; /* * The filter entry points */ -static FILTER *createInstance(char **options, FILTER_PARAMETER **); -static void *newSession(FILTER *instance, SESSION *session); -static void closeSession(FILTER *instance, void *session); -static void freeSession(FILTER *instance, void *session); -static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); -static void setUpstream(FILTER *instance, void *fsession, UPSTREAM *upstream); -static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); -static int clientReply(FILTER *instance, void *fsession, GWBUF *queue); -static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); +static FILTER *createInstance(char **options, FILTER_PARAMETER **); +static void *newSession(FILTER *instance, SESSION *session); +static void closeSession(FILTER *instance, void *session); +static void freeSession(FILTER *instance, void *session); +static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); +static void setUpstream(FILTER *instance, void *fsession, UPSTREAM *upstream); +static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); +static int clientReply(FILTER *instance, void *fsession, GWBUF *queue); +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); -static FILTER_OBJECT MyObject = { - createInstance, - newSession, - closeSession, - freeSession, - setDownstream, - setUpstream, - routeQuery, - clientReply, - diagnostic, +static FILTER_OBJECT MyObject = +{ + createInstance, + newSession, + closeSession, + freeSession, + setDownstream, + setUpstream, + routeQuery, + clientReply, + diagnostic, }; /** *Structure used to store messages and their properties. */ -typedef struct mqmessage_t { - amqp_basic_properties_t *prop; - char *msg; - struct mqmessage_t *next; -}mqmessage; +typedef struct mqmessage_t +{ + amqp_basic_properties_t *prop; + char *msg; + struct mqmessage_t *next; +} mqmessage; /** *Logging trigger levels */ -enum log_trigger_t{ - TRG_ALL = 0x00, - TRG_SOURCE = 0x01, - TRG_SCHEMA = 0x02, - TRG_OBJECT = 0x04 +enum log_trigger_t +{ + TRG_ALL = 0x00, + TRG_SOURCE = 0x01, + TRG_SCHEMA = 0x02, + TRG_OBJECT = 0x04 }; /** @@ -146,92 +150,94 @@ enum log_trigger_t{ * logging_source_host Comma-separated list of hostnames to log * @endverbatim */ -typedef struct source_trigger_t{ - char** user; - int usize; - char** host; - int hsize; -}SRC_TRIG; +typedef struct source_trigger_t +{ + char** user; + int usize; + char** host; + int hsize; +} SRC_TRIG; /** * Schema logging trigger * * Log only those queries that target a specific database. - * + * * Trigger options: * logging_schema Comma-separated list of databases */ -typedef struct schema_trigger_t{ - char** objects; - int size; -}SHM_TRIG; - +typedef struct schema_trigger_t +{ + char** objects; + int size; +} SHM_TRIG; /** * Database object logging trigger * * Log only those queries that target specific database objects. - *@verbatim + *@verbatim * Trigger options: * logging_object Comma-separated list of database objects *@endverbatim */ -typedef struct object_trigger_t{ - char** objects; - int size; -}OBJ_TRIG; +typedef struct object_trigger_t +{ + char** objects; + int size; +} OBJ_TRIG; /** * Statistics for the mqfilter. */ -typedef struct mqstats_t{ +typedef struct mqstats_t +{ int n_msg; /*< Total number of messages */ int n_sent; /*< Number of sent messages */ int n_queued; /*< Number of unsent messages */ - -}MQSTATS; - +} MQSTATS; /** * A instance structure, containing the hostname, login credentials, * virtual host location and the names of the exchange and the key. * Also contains the paths to the CA certificate and client certificate and key. - * + * * Default values assume that a local RabbitMQ server is running on port 5672 with the default * user 'guest' and the password 'guest' using a default exchange named 'default_exchange' with a - * routing key named 'key'. Type of the exchange is 'direct' by default and all queries are logged. - * + * routing key named 'key'. Type of the exchange is 'direct' by default and all queries are logged. + * */ -typedef struct { - int port; - char *hostname; - char *username; - char *password; - char *vhost; - char *exchange; - char *exchange_type; - char *key; - char *queue; - bool use_ssl; - bool log_all; - bool strict_logging; - char *ssl_CA_cert; - char *ssl_client_cert; - char *ssl_client_key; - amqp_connection_state_t conn; /**The connection object*/ - amqp_socket_t* sock; /**The currently active socket*/ - amqp_channel_t channel; /**The current channel in use*/ - int conn_stat; /**state of the connection to the server*/ - int rconn_intv; /**delay for reconnects, in seconds*/ - time_t last_rconn; /**last reconnect attempt*/ - SPINLOCK rconn_lock; - SPINLOCK msg_lock; - mqmessage* messages; - enum log_trigger_t trgtype; - SRC_TRIG* src_trg; - SHM_TRIG* shm_trg; - OBJ_TRIG* obj_trg; - MQSTATS stats; +typedef struct +{ + int port; + char *hostname; + char *username; + char *password; + char *vhost; + char *exchange; + char *exchange_type; + char *key; + char *queue; + bool use_ssl; + bool log_all; + bool strict_logging; + char *ssl_CA_cert; + char *ssl_client_cert; + char *ssl_client_key; + amqp_connection_state_t conn; /**The connection object*/ + amqp_socket_t* sock; /**The currently active socket*/ + amqp_channel_t channel; /**The current channel in use*/ + int conn_stat; /**state of the connection to the server*/ + int rconn_intv; /**delay for reconnects, in seconds*/ + time_t last_rconn; /**last reconnect attempt*/ + SPINLOCK rconn_lock; + SPINLOCK msg_lock; + mqmessage* messages; + enum log_trigger_t trgtype; + SRC_TRIG* src_trg; + SHM_TRIG* shm_trg; + OBJ_TRIG* obj_trg; + MQSTATS stats; } MQ_INSTANCE; /** @@ -243,18 +249,18 @@ typedef struct { * Also holds the necessary session connection information. * */ -typedef struct { - char* uid; /**Unique identifier used to tag messages*/ - char* db; /**The currently active database*/ - DOWNSTREAM down; - UPSTREAM up; - SESSION* session; - bool was_query; /**True if the previous routeQuery call had valid content*/ +typedef struct +{ + char* uid; /**Unique identifier used to tag messages*/ + char* db; /**The currently active database*/ + DOWNSTREAM down; + UPSTREAM up; + SESSION* session; + bool was_query; /**True if the previous routeQuery call had valid content*/ } MQ_SESSION; void sendMessage(void* data); - /** * Implementation of the mandatory version entry point * @@ -263,7 +269,7 @@ void sendMessage(void* data); char * version() { - return version_str; + return version_str; } /** @@ -286,134 +292,154 @@ ModuleInit() FILTER_OBJECT * GetModuleObject() { - return &MyObject; + return &MyObject; } /** - * Internal function used to initialize the connection to + * Internal function used to initialize the connection to * the RabbitMQ server. Also used to reconnect to the server * in case the connection fails and to redeclare exchanges * and queues if they are lost - * + * */ -static int +static int init_conn(MQ_INSTANCE *my_instance) -{ - int rval = 0; - int amqp_ok = AMQP_STATUS_OK; +{ + int rval = 0; + int amqp_ok = AMQP_STATUS_OK; - if(my_instance->use_ssl){ + if (my_instance->use_ssl) + { - if((my_instance->sock = amqp_ssl_socket_new(my_instance->conn)) != NULL){ + if ((my_instance->sock = amqp_ssl_socket_new(my_instance->conn)) != NULL) + { - if((amqp_ok = amqp_ssl_socket_set_cacert(my_instance->sock,my_instance->ssl_CA_cert)) != AMQP_STATUS_OK){ - MXS_ERROR("Failed to set CA certificate: %s", amqp_error_string2(amqp_ok)); - goto cleanup; - } - if((amqp_ok = amqp_ssl_socket_set_key(my_instance->sock, - my_instance->ssl_client_cert, - my_instance->ssl_client_key)) != AMQP_STATUS_OK){ - MXS_ERROR("Failed to set client certificate and key: %s", amqp_error_string2(amqp_ok)); - goto cleanup; - } - }else{ + if ((amqp_ok = amqp_ssl_socket_set_cacert(my_instance->sock, my_instance->ssl_CA_cert)) != AMQP_STATUS_OK) + { + MXS_ERROR("Failed to set CA certificate: %s", amqp_error_string2(amqp_ok)); + goto cleanup; + } + if ((amqp_ok = amqp_ssl_socket_set_key(my_instance->sock, + my_instance->ssl_client_cert, + my_instance->ssl_client_key)) != AMQP_STATUS_OK) + { + MXS_ERROR("Failed to set client certificate and key: %s", amqp_error_string2(amqp_ok)); + goto cleanup; + } + } + else + { + + amqp_ok = AMQP_STATUS_SSL_CONNECTION_FAILED; + MXS_ERROR("SSL socket creation failed."); + goto cleanup; + } + + /**SSL is not used, falling back to TCP*/ + } + else if ((my_instance->sock = amqp_tcp_socket_new(my_instance->conn)) == NULL) + { + MXS_ERROR("TCP socket creation failed."); + goto cleanup; - amqp_ok = AMQP_STATUS_SSL_CONNECTION_FAILED; - MXS_ERROR("SSL socket creation failed."); - goto cleanup; } - /**SSL is not used, falling back to TCP*/ - }else if((my_instance->sock = amqp_tcp_socket_new(my_instance->conn)) == NULL){ - MXS_ERROR("TCP socket creation failed."); - goto cleanup; - - } - - /**Socket creation was successful, trying to open the socket*/ - if((amqp_ok = amqp_socket_open(my_instance->sock,my_instance->hostname,my_instance->port)) != AMQP_STATUS_OK){ - MXS_ERROR("Failed to open socket: %s", amqp_error_string2(amqp_ok)); - goto cleanup; - } - amqp_rpc_reply_t reply; - reply = amqp_login(my_instance->conn,my_instance->vhost,0,AMQP_DEFAULT_FRAME_SIZE,0,AMQP_SASL_METHOD_PLAIN,my_instance->username,my_instance->password); - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - MXS_ERROR("Login to RabbitMQ server failed."); - goto cleanup; - } - amqp_channel_open(my_instance->conn,my_instance->channel); - reply = amqp_get_rpc_reply(my_instance->conn); - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - MXS_ERROR("Channel creation failed."); - goto cleanup; - } - - amqp_exchange_declare(my_instance->conn,my_instance->channel, - amqp_cstring_bytes(my_instance->exchange), - amqp_cstring_bytes(my_instance->exchange_type), - 0, 1, - amqp_empty_table); - - reply = amqp_get_rpc_reply(my_instance->conn); - - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - MXS_ERROR("Exchange declaration failed,trying to redeclare the exchange."); - if(reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION){ - if(reply.reply.id == AMQP_CHANNEL_CLOSE_METHOD){ - amqp_send_method(my_instance->conn,my_instance->channel,AMQP_CHANNEL_CLOSE_OK_METHOD,NULL); - }else if(reply.reply.id == AMQP_CONNECTION_CLOSE_METHOD){ - amqp_send_method(my_instance->conn,my_instance->channel,AMQP_CONNECTION_CLOSE_OK_METHOD,NULL); - } - - my_instance->channel++; - amqp_channel_open(my_instance->conn,my_instance->channel); - - amqp_exchange_delete(my_instance->conn,my_instance->channel,amqp_cstring_bytes(my_instance->exchange),0); - amqp_exchange_declare(my_instance->conn,my_instance->channel, - amqp_cstring_bytes(my_instance->exchange), - amqp_cstring_bytes(my_instance->exchange_type), - 0, 1, - amqp_empty_table); - reply = amqp_get_rpc_reply(my_instance->conn); - } - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - MXS_ERROR("Exchange redeclaration failed."); + /**Socket creation was successful, trying to open the socket*/ + if ((amqp_ok = amqp_socket_open(my_instance->sock, my_instance->hostname, my_instance->port)) != AMQP_STATUS_OK) + { + MXS_ERROR("Failed to open socket: %s", amqp_error_string2(amqp_ok)); goto cleanup; } - } - - if(my_instance->queue){ - - - - amqp_queue_declare(my_instance->conn,my_instance->channel, - amqp_cstring_bytes(my_instance->queue), - 0, 1, 0, 0, - amqp_empty_table); - reply = amqp_get_rpc_reply(my_instance->conn); - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - MXS_ERROR("Queue declaration failed."); + amqp_rpc_reply_t reply; + reply = amqp_login(my_instance->conn, my_instance->vhost, 0, AMQP_DEFAULT_FRAME_SIZE, 0, AMQP_SASL_METHOD_PLAIN, my_instance->username, my_instance->password); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + MXS_ERROR("Login to RabbitMQ server failed."); + goto cleanup; + } + amqp_channel_open(my_instance->conn, my_instance->channel); + reply = amqp_get_rpc_reply(my_instance->conn); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + MXS_ERROR("Channel creation failed."); goto cleanup; } - - amqp_queue_bind(my_instance->conn,my_instance->channel, - amqp_cstring_bytes(my_instance->queue), - amqp_cstring_bytes(my_instance->exchange), - amqp_cstring_bytes(my_instance->key), - amqp_empty_table); - reply = amqp_get_rpc_reply(my_instance->conn); - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - MXS_ERROR("Failed to bind queue to exchange."); - goto cleanup; + amqp_exchange_declare(my_instance->conn, my_instance->channel, + amqp_cstring_bytes(my_instance->exchange), + amqp_cstring_bytes(my_instance->exchange_type), + 0, 1, + amqp_empty_table); + + reply = amqp_get_rpc_reply(my_instance->conn); + + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + MXS_ERROR("Exchange declaration failed,trying to redeclare the exchange."); + if (reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION) + { + if (reply.reply.id == AMQP_CHANNEL_CLOSE_METHOD) + { + amqp_send_method(my_instance->conn, my_instance->channel, AMQP_CHANNEL_CLOSE_OK_METHOD, NULL); + } + else if (reply.reply.id == AMQP_CONNECTION_CLOSE_METHOD) + { + amqp_send_method(my_instance->conn, my_instance->channel, AMQP_CONNECTION_CLOSE_OK_METHOD, NULL); + } + + my_instance->channel++; + amqp_channel_open(my_instance->conn, my_instance->channel); + + amqp_exchange_delete(my_instance->conn, my_instance->channel, amqp_cstring_bytes(my_instance->exchange), 0); + amqp_exchange_declare(my_instance->conn, my_instance->channel, + amqp_cstring_bytes(my_instance->exchange), + amqp_cstring_bytes(my_instance->exchange_type), + 0, 1, + amqp_empty_table); + reply = amqp_get_rpc_reply(my_instance->conn); + } + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + MXS_ERROR("Exchange redeclaration failed."); + goto cleanup; + } } - } - rval = 1; - cleanup: + if (my_instance->queue) + { + + + + amqp_queue_declare(my_instance->conn, my_instance->channel, + amqp_cstring_bytes(my_instance->queue), + 0, 1, 0, 0, + amqp_empty_table); + reply = amqp_get_rpc_reply(my_instance->conn); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + MXS_ERROR("Queue declaration failed."); + goto cleanup; + } + + + amqp_queue_bind(my_instance->conn, my_instance->channel, + amqp_cstring_bytes(my_instance->queue), + amqp_cstring_bytes(my_instance->exchange), + amqp_cstring_bytes(my_instance->key), + amqp_empty_table); + reply = amqp_get_rpc_reply(my_instance->conn); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + MXS_ERROR("Failed to bind queue to exchange."); + goto cleanup; + } + } + rval = 1; + +cleanup: + + return rval; - return rval; - } /** @@ -427,264 +453,329 @@ init_conn(MQ_INSTANCE *my_instance) */ char** parse_optstr(char* str, char* tok, int* szstore) { - char *lasts, *tk = str; - char **arr; - int i = 0, size = 1; - - - while((tk = strpbrk(tk + 1,tok))){ - size++; - } + char *lasts, *tk = str; + char **arr; + int i = 0, size = 1; - arr = malloc(sizeof(char*)*size); - if(arr == NULL){ - MXS_ERROR("Cannot allocate enough memory."); - *szstore = 0; - return NULL; - } - - *szstore = size; - tk = strtok_r(str,tok, &lasts); - while(tk && i < size){ - arr[i++] = strdup(tk); - tk = strtok_r(NULL,tok,&lasts); - } - return arr; + while ((tk = strpbrk(tk + 1, tok))) + { + size++; + } + + arr = malloc(sizeof(char*)*size); + + if (arr == NULL) + { + MXS_ERROR("Cannot allocate enough memory."); + *szstore = 0; + return NULL; + } + + *szstore = size; + tk = strtok_r(str, tok, &lasts); + while (tk && i < size) + { + arr[i++] = strdup(tk); + tk = strtok_r(NULL, tok, &lasts); + } + return arr; } /** * Create an instance of the filter for a particular service * within MaxScale. - * + * * @param options The options for this filter * * @return The instance data for this new instance */ -static FILTER * +static FILTER * createInstance(char **options, FILTER_PARAMETER **params) { - MQ_INSTANCE *my_instance; - int paramcount = 0, parammax = 64, i = 0, x = 0, arrsize = 0; - FILTER_PARAMETER** paramlist; - char** arr; - char taskname[512]; - - if ((my_instance = calloc(1, sizeof(MQ_INSTANCE)))) + MQ_INSTANCE *my_instance; + int paramcount = 0, parammax = 64, i = 0, x = 0, arrsize = 0; + FILTER_PARAMETER** paramlist; + char** arr; + char taskname[512]; + + if ((my_instance = calloc(1, sizeof(MQ_INSTANCE)))) { - spinlock_init(&my_instance->rconn_lock); - spinlock_init(&my_instance->msg_lock); - uid_gen = 0; - paramlist = malloc(sizeof(FILTER_PARAMETER*)*64); + spinlock_init(&my_instance->rconn_lock); + spinlock_init(&my_instance->msg_lock); + uid_gen = 0; + paramlist = malloc(sizeof(FILTER_PARAMETER*)*64); - if((my_instance->conn = amqp_new_connection()) == NULL){ + if ((my_instance->conn = amqp_new_connection()) == NULL) + { + return NULL; + } + my_instance->channel = 1; + my_instance->last_rconn = time(NULL); + my_instance->conn_stat = AMQP_STATUS_OK; + my_instance->rconn_intv = 1; + my_instance->port = 5672; + my_instance->trgtype = TRG_ALL; + my_instance->log_all = false; + my_instance->strict_logging = true; + + for (i = 0; params[i]; i++) + { + if (!strcmp(params[i]->name, "hostname")) + { + my_instance->hostname = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "username")) + { + my_instance->username = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "password")) + { + my_instance->password = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "vhost")) + { + my_instance->vhost = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "port")) + { + my_instance->port = atoi(params[i]->value); + } + else if (!strcmp(params[i]->name, "exchange")) + { + my_instance->exchange = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "key")) + { + my_instance->key = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "queue")) + { + my_instance->queue = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "ssl_client_certificate")) + { + + my_instance->ssl_client_cert = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "ssl_client_key")) + { + + my_instance->ssl_client_key = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "ssl_CA_cert")) + { + + my_instance->ssl_CA_cert = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "exchange_type")) + { + + my_instance->exchange_type = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "logging_trigger")) + { + + arr = parse_optstr(params[i]->value, ",", &arrsize); + + for (x = 0; x < arrsize; x++) + { + if (!strcmp(arr[x], "source")) + { + my_instance->trgtype |= TRG_SOURCE; + } + else if (!strcmp(arr[x], "schema")) + { + my_instance->trgtype |= TRG_SCHEMA; + } + else if (!strcmp(arr[x], "object")) + { + my_instance->trgtype |= TRG_OBJECT; + } + else if (!strcmp(arr[x], "all")) + { + my_instance->trgtype = TRG_ALL; + } + else + { + MXS_ERROR("Unknown option for 'logging_trigger':%s.", arr[x]); + } + } + + if (arrsize > 0) + { + free(arr); + } + arrsize = 0; - return NULL; - } - my_instance->channel = 1; - my_instance->last_rconn = time(NULL); - my_instance->conn_stat = AMQP_STATUS_OK; - my_instance->rconn_intv = 1; - my_instance->port = 5672; - my_instance->trgtype = TRG_ALL; - my_instance->log_all = false; - my_instance->strict_logging = true; - for(i = 0;params[i];i++){ - if(!strcmp(params[i]->name,"hostname")){ - my_instance->hostname = strdup(params[i]->value); - }else if(!strcmp(params[i]->name,"username")){ - my_instance->username = strdup(params[i]->value); - }else if(!strcmp(params[i]->name,"password")){ - my_instance->password = strdup(params[i]->value); - }else if(!strcmp(params[i]->name,"vhost")){ - my_instance->vhost = strdup(params[i]->value); - }else if(!strcmp(params[i]->name,"port")){ - my_instance->port = atoi(params[i]->value); - }else if(!strcmp(params[i]->name,"exchange")){ - my_instance->exchange = strdup(params[i]->value); - }else if(!strcmp(params[i]->name,"key")){ - my_instance->key = strdup(params[i]->value); - }else if(!strcmp(params[i]->name,"queue")){ - my_instance->queue = strdup(params[i]->value); - } - else if(!strcmp(params[i]->name,"ssl_client_certificate")){ + } + else if (strstr(params[i]->name, "logging_")) + { - my_instance->ssl_client_cert = strdup(params[i]->value); - - }else if(!strcmp(params[i]->name,"ssl_client_key")){ + if (paramcount < parammax) + { + paramlist[paramcount] = malloc(sizeof(FILTER_PARAMETER)); + paramlist[paramcount]->name = strdup(params[i]->name); + paramlist[paramcount]->value = strdup(params[i]->value); + paramcount++; + } + } + } - my_instance->ssl_client_key = strdup(params[i]->value); - - }else if(!strcmp(params[i]->name,"ssl_CA_cert")){ + if (my_instance->trgtype & TRG_SOURCE) + { - my_instance->ssl_CA_cert = strdup(params[i]->value); + my_instance->src_trg = (SRC_TRIG*) malloc(sizeof(SRC_TRIG)); + my_instance->src_trg->user = NULL; + my_instance->src_trg->host = NULL; + my_instance->src_trg->usize = 0; + my_instance->src_trg->hsize = 0; - }else if(!strcmp(params[i]->name,"exchange_type")){ + } - my_instance->exchange_type = strdup(params[i]->value); + if (my_instance->trgtype & TRG_SCHEMA) + { - }else if(!strcmp(params[i]->name,"logging_trigger")){ - - arr = parse_optstr(params[i]->value,",",&arrsize); + my_instance->shm_trg = (SHM_TRIG*) malloc(sizeof(SHM_TRIG)); + my_instance->shm_trg->objects = NULL; + my_instance->shm_trg->size = 0; - for(x = 0;xtrgtype |= TRG_SOURCE; - }else if(!strcmp(arr[x],"schema")){ - my_instance->trgtype |= TRG_SCHEMA; - }else if(!strcmp(arr[x],"object")){ - my_instance->trgtype |= TRG_OBJECT; - }else if(!strcmp(arr[x],"all")){ - my_instance->trgtype = TRG_ALL; - }else{ - MXS_ERROR("Unknown option for 'logging_trigger':%s.",arr[x]); - } - } + } - if(arrsize > 0){ - free(arr); - } - arrsize = 0; - + if (my_instance->trgtype & TRG_OBJECT) + { + my_instance->obj_trg = (OBJ_TRIG*) malloc(sizeof(OBJ_TRIG)); + my_instance->obj_trg->objects = NULL; + my_instance->obj_trg->size = 0; - }else if(strstr(params[i]->name,"logging_")){ + } - if(paramcount < parammax){ - paramlist[paramcount] = malloc(sizeof(FILTER_PARAMETER)); - paramlist[paramcount]->name = strdup(params[i]->name); - paramlist[paramcount]->value = strdup(params[i]->value); - paramcount++; - } - - } + for (i = 0; i < paramcount; i++) + { - } + if (!strcmp(paramlist[i]->name, "logging_source_user")) + { - if(my_instance->trgtype & TRG_SOURCE){ + if (my_instance->src_trg) + { + my_instance->src_trg->user = parse_optstr(paramlist[i]->value, ",", &arrsize); + my_instance->src_trg->usize = arrsize; + arrsize = 0; + } - my_instance->src_trg = (SRC_TRIG*)malloc(sizeof(SRC_TRIG)); - my_instance->src_trg->user = NULL; - my_instance->src_trg->host = NULL; - my_instance->src_trg->usize = 0; - my_instance->src_trg->hsize = 0; + } + else if (!strcmp(paramlist[i]->name, "logging_source_host")) + { - } + if (my_instance->src_trg) + { + my_instance->src_trg->host = parse_optstr(paramlist[i]->value, ",", &arrsize); + my_instance->src_trg->hsize = arrsize; + arrsize = 0; + } - if(my_instance->trgtype & TRG_SCHEMA){ + } + else if (!strcmp(paramlist[i]->name, "logging_schema")) + { - my_instance->shm_trg = (SHM_TRIG*)malloc(sizeof(SHM_TRIG)); - my_instance->shm_trg->objects = NULL; - my_instance->shm_trg->size = 0; + if (my_instance->shm_trg) + { + my_instance->shm_trg->objects = parse_optstr(paramlist[i]->value, ",", &arrsize); + my_instance->shm_trg->size = arrsize; + arrsize = 0; + } - } + } + else if (!strcmp(paramlist[i]->name, "logging_object")) + { - if(my_instance->trgtype & TRG_OBJECT){ + if (my_instance->obj_trg) + { + my_instance->obj_trg->objects = parse_optstr(paramlist[i]->value, ",", &arrsize); + my_instance->obj_trg->size = arrsize; + arrsize = 0; + } - my_instance->obj_trg = (OBJ_TRIG*)malloc(sizeof(OBJ_TRIG)); - my_instance->obj_trg->objects = NULL; - my_instance->obj_trg->size = 0; + } + else if (!strcmp(paramlist[i]->name, "logging_log_all")) + { + if (config_truth_value(paramlist[i]->value)) + { + my_instance->log_all = true; + } + } + else if (!strcmp(paramlist[i]->name, "logging_strict")) + { + if (!config_truth_value(paramlist[i]->value)) + { + my_instance->strict_logging = false; + } + } + free(paramlist[i]->name); + free(paramlist[i]->value); + free(paramlist[i]); + } - } + free(paramlist); - for(i = 0;ihostname == NULL) + { + my_instance->hostname = strdup("localhost"); + } + if (my_instance->username == NULL) + { + my_instance->username = strdup("guest"); + } + if (my_instance->password == NULL) + { + my_instance->password = strdup("guest"); + } + if (my_instance->vhost == NULL) + { + my_instance->vhost = strdup("/"); + } + if (my_instance->exchange == NULL) + { + my_instance->exchange = strdup("default_exchange"); + } + if (my_instance->key == NULL) + { + my_instance->key = strdup("key"); + } + if (my_instance->exchange_type == NULL) + { + my_instance->exchange_type = strdup("direct"); + } - if(!strcmp(paramlist[i]->name,"logging_source_user")){ - - if(my_instance->src_trg){ - my_instance->src_trg->user = parse_optstr(paramlist[i]->value,",",&arrsize); - my_instance->src_trg->usize = arrsize; - arrsize = 0; - } + if (my_instance->ssl_client_cert != NULL && + my_instance->ssl_client_key != NULL && + my_instance->ssl_CA_cert != NULL) + { + my_instance->use_ssl = true; + } + else + { + my_instance->use_ssl = false; + } - }else if(!strcmp(paramlist[i]->name,"logging_source_host")){ - - if(my_instance->src_trg){ - my_instance->src_trg->host = parse_optstr(paramlist[i]->value,",",&arrsize); - my_instance->src_trg->hsize = arrsize; - arrsize = 0; - } + if (my_instance->use_ssl) + { + amqp_set_initialize_ssl_library(0); /**Assume the underlying SSL library is already initialized*/ + } - }else if(!strcmp(paramlist[i]->name,"logging_schema")){ - - if(my_instance->shm_trg){ - my_instance->shm_trg->objects = parse_optstr(paramlist[i]->value,",",&arrsize); - my_instance->shm_trg->size = arrsize; - arrsize = 0; - } + /**Connect to the server*/ + init_conn(my_instance); - }else if(!strcmp(paramlist[i]->name,"logging_object")){ - - if(my_instance->obj_trg){ - my_instance->obj_trg->objects = parse_optstr(paramlist[i]->value,",",&arrsize); - my_instance->obj_trg->size = arrsize; - arrsize = 0; - } - - }else if(!strcmp(paramlist[i]->name,"logging_log_all")){ - if(config_truth_value(paramlist[i]->value)){ - my_instance->log_all = true; - } - }else if(!strcmp(paramlist[i]->name,"logging_strict")){ - if(!config_truth_value(paramlist[i]->value)){ - my_instance->strict_logging = false; - } - } - free(paramlist[i]->name); - free(paramlist[i]->value); - free(paramlist[i]); - } - - free(paramlist); - - if(my_instance->hostname == NULL){ - my_instance->hostname = strdup("localhost"); - } - if(my_instance->username == NULL){ - my_instance->username = strdup("guest"); - } - if(my_instance->password == NULL){ - my_instance->password = strdup("guest"); - } - if(my_instance->vhost == NULL){ - my_instance->vhost = strdup("/"); - } - if(my_instance->exchange == NULL){ - my_instance->exchange = strdup("default_exchange"); - } - if(my_instance->key == NULL){ - my_instance->key = strdup("key"); - } - if(my_instance->exchange_type == NULL){ - my_instance->exchange_type = strdup("direct"); - } - - if(my_instance->ssl_client_cert != NULL && - my_instance->ssl_client_key != NULL && - my_instance->ssl_CA_cert != NULL){ - my_instance->use_ssl = true; - }else{ - my_instance->use_ssl = false; - } - - if(my_instance->use_ssl){ - amqp_set_initialize_ssl_library(0);/**Assume the underlying SSL library is already initialized*/ - } - - /**Connect to the server*/ - init_conn(my_instance); - - snprintf(taskname,511,"mqtask%d",atomic_add(&hktask_id,1)); - hktask_add(taskname,sendMessage,(void*)my_instance,5); + snprintf(taskname, 511, "mqtask%d", atomic_add(&hktask_id, 1)); + hktask_add(taskname, sendMessage, (void*) my_instance, 5); } - return (FILTER *)my_instance; + return(FILTER *) my_instance; } - - /** * Declares a persistent, non-exclusive and non-passive queue that * auto-deletes after all the messages have been consumed. @@ -692,38 +783,39 @@ createInstance(char **options, FILTER_PARAMETER **params) * @param qname Name of the queue to be declared * @return Returns 0 if an error occurred, 1 if successful */ -int declareQueue(MQ_INSTANCE *my_instance, MQ_SESSION* my_session, char* qname) +int declareQueue(MQ_INSTANCE *my_instance, MQ_SESSION* my_session, char* qname) { - int success = 1; - amqp_rpc_reply_t reply; + int success = 1; + amqp_rpc_reply_t reply; - spinlock_acquire(&my_instance->rconn_lock); + spinlock_acquire(&my_instance->rconn_lock); - amqp_queue_declare(my_instance->conn,my_instance->channel, - amqp_cstring_bytes(qname), - 0, 1, 0, 1, - amqp_empty_table); - reply = amqp_get_rpc_reply(my_instance->conn); - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - success = 0; - MXS_ERROR("Queue declaration failed."); - - } + amqp_queue_declare(my_instance->conn, my_instance->channel, + amqp_cstring_bytes(qname), + 0, 1, 0, 1, + amqp_empty_table); + reply = amqp_get_rpc_reply(my_instance->conn); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + success = 0; + MXS_ERROR("Queue declaration failed."); - - amqp_queue_bind(my_instance->conn,my_instance->channel, - amqp_cstring_bytes(qname), - amqp_cstring_bytes(my_instance->exchange), - amqp_cstring_bytes(my_session->uid), - amqp_empty_table); - reply = amqp_get_rpc_reply(my_instance->conn); - if(reply.reply_type != AMQP_RESPONSE_NORMAL){ - success = 0; - MXS_ERROR("Failed to bind queue to exchange."); - - } - spinlock_release(&my_instance->rconn_lock); - return success; + } + + amqp_queue_bind(my_instance->conn, my_instance->channel, + amqp_cstring_bytes(qname), + amqp_cstring_bytes(my_instance->exchange), + amqp_cstring_bytes(my_session->uid), + amqp_empty_table); + reply = amqp_get_rpc_reply(my_instance->conn); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + success = 0; + MXS_ERROR("Failed to bind queue to exchange."); + + } + spinlock_release(&my_instance->rconn_lock); + return success; } /** @@ -734,93 +826,93 @@ int declareQueue(MQ_INSTANCE *my_instance, MQ_SESSION* my_session, char* qname) */ void sendMessage(void* data) { - MQ_INSTANCE *instance = (MQ_INSTANCE*)data; - mqmessage *tmp; - int err_num; - - spinlock_acquire(&instance->rconn_lock); - if(instance->conn_stat != AMQP_STATUS_OK){ - - if(difftime(time(NULL),instance->last_rconn) > instance->rconn_intv){ - - instance->last_rconn = time(NULL); - - if(init_conn(instance)){ - instance->rconn_intv = 1.0; - instance->conn_stat = AMQP_STATUS_OK; - - }else{ - instance->rconn_intv += 5.0; - MXS_ERROR("Failed to reconnect to the MQRabbit server "); - } - } - err_num = instance->conn_stat; - } - spinlock_release(&instance->rconn_lock); - - if(err_num != AMQP_STATUS_OK) - { - /** No connection to the broker */ - return; - } - - spinlock_acquire(&instance->msg_lock); - tmp = instance->messages; - - if(tmp == NULL) - { - spinlock_release(&instance->msg_lock); - return; - } - - instance->messages = instance->messages->next; - spinlock_release(&instance->msg_lock); - - while(tmp){ - - err_num = amqp_basic_publish(instance->conn,instance->channel, - amqp_cstring_bytes(instance->exchange), - amqp_cstring_bytes(instance->key), - 0,0,tmp->prop,amqp_cstring_bytes(tmp->msg)); + MQ_INSTANCE *instance = (MQ_INSTANCE*) data; + mqmessage *tmp; + int err_num; spinlock_acquire(&instance->rconn_lock); - instance->conn_stat = err_num; - spinlock_release(&instance->rconn_lock); - - if(err_num == AMQP_STATUS_OK){ - /**Message was sent successfully*/ - free(tmp->prop); - free(tmp->msg); - free(tmp); - - atomic_add(&instance->stats.n_sent,1); - atomic_add(&instance->stats.n_queued,-1); - spinlock_acquire(&instance->msg_lock); - tmp = instance->messages; - - if(tmp == NULL) - { - spinlock_release(&instance->msg_lock); - return; - } - - instance->messages = instance->messages->next; - spinlock_release(&instance->msg_lock); - } - else + if (instance->conn_stat != AMQP_STATUS_OK) { - spinlock_acquire(&instance->msg_lock); - tmp->next = instance->messages; - instance->messages = tmp; - spinlock_release(&instance->msg_lock); - return; + if (difftime(time(NULL), instance->last_rconn) > instance->rconn_intv) + { + instance->last_rconn = time(NULL); + + if (init_conn(instance)) + { + instance->rconn_intv = 1.0; + instance->conn_stat = AMQP_STATUS_OK; + } + else + { + instance->rconn_intv += 5.0; + MXS_ERROR("Failed to reconnect to the MQRabbit server "); + } + } + err_num = instance->conn_stat; } - - } + spinlock_release(&instance->rconn_lock); + if (err_num != AMQP_STATUS_OK) + { + /** No connection to the broker */ + return; + } + + spinlock_acquire(&instance->msg_lock); + tmp = instance->messages; + + if (tmp == NULL) + { + spinlock_release(&instance->msg_lock); + return; + } + + instance->messages = instance->messages->next; + spinlock_release(&instance->msg_lock); + + while (tmp) + { + err_num = amqp_basic_publish(instance->conn, instance->channel, + amqp_cstring_bytes(instance->exchange), + amqp_cstring_bytes(instance->key), + 0, 0, tmp->prop, amqp_cstring_bytes(tmp->msg)); + + spinlock_acquire(&instance->rconn_lock); + instance->conn_stat = err_num; + spinlock_release(&instance->rconn_lock); + + if (err_num == AMQP_STATUS_OK) + { + /**Message was sent successfully*/ + free(tmp->prop); + free(tmp->msg); + free(tmp); + + atomic_add(&instance->stats.n_sent, 1); + atomic_add(&instance->stats.n_queued, -1); + spinlock_acquire(&instance->msg_lock); + tmp = instance->messages; + + if (tmp == NULL) + { + spinlock_release(&instance->msg_lock); + return; + } + + instance->messages = instance->messages->next; + spinlock_release(&instance->msg_lock); + } + else + { + spinlock_acquire(&instance->msg_lock); + tmp->next = instance->messages; + instance->messages = tmp; + spinlock_release(&instance->msg_lock); + return; + } + } } - /** * Push a new message on the stack to be broadcasted later. * The message assumes ownership of the memory allocated to the message content and properties. @@ -829,33 +921,32 @@ void sendMessage(void* data) */ void pushMessage(MQ_INSTANCE *instance, amqp_basic_properties_t* prop, char* msg) { - - mqmessage* newmsg = calloc(1,sizeof(mqmessage)); - if(newmsg){ - - newmsg->msg = msg; - newmsg->prop = prop; - - }else{ - MXS_ERROR("Cannot allocate enough memory."); - free(prop); - free(msg); - return; - } - spinlock_acquire(&instance->msg_lock); - - newmsg->next = instance->messages; - instance->messages = newmsg; + mqmessage* newmsg = calloc(1, sizeof(mqmessage)); + if (newmsg) + { + newmsg->msg = msg; + newmsg->prop = prop; + } + else + { + MXS_ERROR("Cannot allocate enough memory."); + free(prop); + free(msg); + return; + } - spinlock_release(&instance->msg_lock); - - atomic_add(&instance->stats.n_msg,1); - atomic_add(&instance->stats.n_queued,1); + spinlock_acquire(&instance->msg_lock); + + newmsg->next = instance->messages; + instance->messages = newmsg; + + spinlock_release(&instance->msg_lock); + + atomic_add(&instance->stats.n_msg, 1); + atomic_add(&instance->stats.n_queued, 1); } - - /** * Associate a new session with this instance of the filter and opens * a connection to the server and prepares the exchange and the queue for use. @@ -865,31 +956,31 @@ void pushMessage(MQ_INSTANCE *instance, amqp_basic_properties_t* prop, char* msg * @param session The session itself * @return Session specific data for this session */ -static void * +static void * newSession(FILTER *instance, SESSION *session) { - MQ_SESSION *my_session; - MYSQL_session* sessauth; + MQ_SESSION *my_session; + MYSQL_session* sessauth; - if ((my_session = calloc(1, sizeof(MQ_SESSION))) != NULL){ - - my_session->was_query = false; - my_session->uid = NULL; - my_session->session = session; - sessauth = my_session->session->data; - if(sessauth->db && strnlen(sessauth->db,128)>0){ - my_session->db = strdup(sessauth->db); - }else{ - my_session->db = NULL; + if ((my_session = calloc(1, sizeof(MQ_SESSION))) != NULL) + { + my_session->was_query = false; + my_session->uid = NULL; + my_session->session = session; + sessauth = my_session->session->data; + if (sessauth->db && strnlen(sessauth->db, 128) > 0) + { + my_session->db = strdup(sessauth->db); + } + else + { + my_session->db = NULL; + } } - - } - return my_session; + return my_session; } - - /** * Close a session with the filter, this is the mechanism * by which a filter may cleanup data structure etc. @@ -898,10 +989,8 @@ newSession(FILTER *instance, SESSION *session) * @param instance The filter instance data * @param session The session being closed */ -static void -closeSession(FILTER *instance, void *session) -{ -} +static void +closeSession(FILTER *instance, void *session){ } /** * Free the memory associated with the session @@ -912,11 +1001,11 @@ closeSession(FILTER *instance, void *session) static void freeSession(FILTER *instance, void *session) { - MQ_SESSION *my_session = (MQ_SESSION *)session; - free(my_session->uid); - free(my_session->db); - free(my_session); - return; + MQ_SESSION *my_session = (MQ_SESSION *) session; + free(my_session->uid); + free(my_session->db); + free(my_session); + return; } /** @@ -924,23 +1013,22 @@ freeSession(FILTER *instance, void *session) * passed from this filter. * * @param instance The filter instance data - * @param session The filter session + * @param session The filter session * @param downstream The downstream filter or router. */ static void setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) { - MQ_SESSION *my_session = (MQ_SESSION *)session; - my_session->down = *downstream; + MQ_SESSION *my_session = (MQ_SESSION *) session; + my_session->down = *downstream; } -static void setUpstream(FILTER *instance, void *session, UPSTREAM *upstream) +static void setUpstream(FILTER *instance, void *session, UPSTREAM *upstream) { - MQ_SESSION *my_session = (MQ_SESSION *)session; - my_session->up = *upstream; + MQ_SESSION *my_session = (MQ_SESSION *) session; + my_session->up = *upstream; } - /** * Generates a unique key using a number of unique unsigned integers. * @param array The array that is used @@ -948,11 +1036,12 @@ static void setUpstream(FILTER *instance, void *session, UPSTREAM *upstream) */ void genkey(char* array, int size) { - int i = 0; - for(i = 0;istart + 4)) == 0x02){ - if(my_session->db){ - free(my_session->db); - } - plen = pktlen(queue->start); - my_session->db = calloc(plen,sizeof(char)); - memcpy(my_session->db,queue->start + 5,plen - 1); - } - - if(modutil_is_SQL(queue)){ - - /**Parse the query*/ - - if (!query_is_parsed(queue)){ - success = parse_query(queue); + /**The user is changing databases*/ + if (*((char*) (queue->start + 4)) == 0x02) + { + if (my_session->db) + { + free(my_session->db); + } + plen = pktlen(queue->start); + my_session->db = calloc(plen, sizeof(char)); + memcpy(my_session->db, queue->start + 5, plen - 1); } - if(!success){ - MXS_ERROR("Parsing query failed."); - goto send_downstream; - } + if (modutil_is_SQL(queue)) + { - if(!my_instance->log_all){ - if(!skygw_is_real_query(queue)){ - goto send_downstream; - } - } + /**Parse the query*/ - if(my_instance->trgtype == TRG_ALL){ - MXS_INFO("Trigger is TRG_ALL"); - schema_ok = true; - src_ok = true; - obj_ok = true; - goto validate_triggers; - } - - if(my_instance->trgtype & TRG_SOURCE && my_instance->src_trg){ - - if(session_isvalid(my_session->session)){ - - sessusr = session_getUser(my_session->session); - sesshost = session_get_remote(my_session->session); - - /**Username was configured*/ - if(my_instance->src_trg->usize > 0){ - for(i = 0;isrc_trg->usize;i++){ + if (!query_is_parsed(queue)) + { + success = parse_query(queue); + } - if(strcmp(my_instance->src_trg->user[i],sessusr) == 0) - { - MXS_INFO("Trigger is TRG_SOURCE: user: %s = %s",my_instance->src_trg->user[i],sessusr); + if (!success) + { + MXS_ERROR("Parsing query failed."); + goto send_downstream; + } + + if (!my_instance->log_all) + { + if (!skygw_is_real_query(queue)) + { + goto send_downstream; + } + } + + if (my_instance->trgtype == TRG_ALL) + { + MXS_INFO("Trigger is TRG_ALL"); + schema_ok = true; + src_ok = true; + obj_ok = true; + goto validate_triggers; + } + + if (my_instance->trgtype & TRG_SOURCE && my_instance->src_trg) + { + if (session_isvalid(my_session->session)) + { + sessusr = session_getUser(my_session->session); + sesshost = session_get_remote(my_session->session); + + /**Username was configured*/ + if (my_instance->src_trg->usize > 0) + { + for (i = 0; i < my_instance->src_trg->usize; i++) + { + if (strcmp(my_instance->src_trg->user[i], sessusr) == 0) + { + MXS_INFO("Trigger is TRG_SOURCE: user: %s = %s", my_instance->src_trg->user[i], sessusr); + src_ok = true; + break; + } + } + } + + /**If username was not matched, try to match hostname*/ + + if (!src_ok && my_instance->src_trg->hsize > 0) + { + + for (i = 0; i < my_instance->src_trg->hsize; i++) + { + + if (strcmp(my_instance->src_trg->host[i], sesshost) == 0) + { + MXS_INFO("Trigger is TRG_SOURCE: host: %s = %s", my_instance->src_trg->host[i], sesshost); + src_ok = true; + break; + } + } + } + } + + if (src_ok && !my_instance->strict_logging) + { + schema_ok = true; + obj_ok = true; + goto validate_triggers; + } + } + else + { + src_ok = true; + } + + if (my_instance->trgtype & TRG_SCHEMA && my_instance->shm_trg) + { + int tbsz = 0, z; + char** tblnames = skygw_get_table_names(queue, &tbsz, true); + char* tmp; + bool all_remotes = true; + + for (z = 0; z < tbsz; z++) + { + if ((tmp = strchr(tblnames[z], '.')) != NULL) + { + char *lasts; + tmp = strtok_r(tblnames[z], ".", &lasts); + for (i = 0; i < my_instance->shm_trg->size; i++) + { + + if (strcmp(tmp, my_instance->shm_trg->objects[i]) == 0) + { + + MXS_INFO("Trigger is TRG_SCHEMA: %s = %s", tmp, my_instance->shm_trg->objects[i]); + + schema_ok = true; + break; + } + } + } + else + { + all_remotes = false; + } + free(tblnames[z]); + } + free(tblnames); + + if (!schema_ok && !all_remotes && my_session->db && strlen(my_session->db) > 0) + { + + for (i = 0; i < my_instance->shm_trg->size; i++) + { + + if (strcmp(my_session->db, my_instance->shm_trg->objects[i]) == 0) + { + + MXS_INFO("Trigger is TRG_SCHEMA: %s = %s", my_session->db, my_instance->shm_trg->objects[i]); + + schema_ok = true; + break; + } + } + } + + if (schema_ok && !my_instance->strict_logging) + { src_ok = true; - break; - } - - } + obj_ok = true; + goto validate_triggers; + } - - } + } + else + { + schema_ok = true; + } - /**If username was not matched, try to match hostname*/ - if(!src_ok && my_instance->src_trg->hsize > 0){ + if (my_instance->trgtype & TRG_OBJECT && my_instance->obj_trg) + { - for(i = 0;isrc_trg->hsize;i++){ - - if(strcmp(my_instance->src_trg->host[i],sesshost) == 0) - { - MXS_INFO("Trigger is TRG_SOURCE: host: %s = %s",my_instance->src_trg->host[i],sesshost); - src_ok = true; - break; - } - - } + sesstbls = skygw_get_table_names(queue, &dbcount, false); - } + for (j = 0; j < dbcount; j++) + { + char* tbnm = NULL; - } + if ((strchr(sesstbls[j], '.')) != NULL) + { + char *lasts; + tbnm = strtok_r(sesstbls[j], ".", &lasts); + tbnm = strtok_r(NULL, ".", &lasts); + } + else + { + tbnm = sesstbls[j]; + } - if(src_ok && !my_instance->strict_logging){ - schema_ok = true; - obj_ok = true; - goto validate_triggers; - } - }else{ - src_ok = true; + for (i = 0; i < my_instance->obj_trg->size; i++) + { + + + if (!strcmp(tbnm, my_instance->obj_trg->objects[i])) + { + obj_ok = true; + MXS_INFO("Trigger is TRG_OBJECT: %s = %s", my_instance->obj_trg->objects[i], sesstbls[j]); + break; + } + + } + + } + if (dbcount > 0) + { + for (j = 0; j < dbcount; j++) + { + free(sesstbls[j]); + } + free(sesstbls); + dbcount = 0; + } + + if (obj_ok && !my_instance->strict_logging) + { + src_ok = true; + schema_ok = true; + goto validate_triggers; + } + + } + else + { + obj_ok = true; + } + + +validate_triggers: + + if (src_ok && schema_ok && obj_ok) + { + + /** + * Something matched the trigger, log the query + */ + + MXS_INFO("Routing message to: %s:%d %s as %s/%s, exchange: %s<%s> key:%s queue:%s", + my_instance->hostname, my_instance->port, + my_instance->vhost, my_instance->username, + my_instance->password, my_instance->exchange, + my_instance->exchange_type, my_instance->key, + my_instance->queue); + + if (my_session->uid == NULL) + { + + my_session->uid = calloc(33, sizeof(char)); + + if (!my_session->uid) + { + MXS_ERROR("Out of memory."); + } + else + { + genkey(my_session->uid, 32); + } + + } + + if (queue->next != NULL) + { + queue = gwbuf_make_contiguous(queue); + } + + if (modutil_extract_SQL(queue, &ptr, &length)) + { + + my_session->was_query = true; + + if ((prop = malloc(sizeof(amqp_basic_properties_t)))) + { + prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG | + AMQP_BASIC_DELIVERY_MODE_FLAG | + AMQP_BASIC_MESSAGE_ID_FLAG | + AMQP_BASIC_CORRELATION_ID_FLAG; + prop->content_type = amqp_cstring_bytes("text/plain"); + prop->delivery_mode = AMQP_DELIVERY_PERSISTENT; + prop->correlation_id = amqp_cstring_bytes(my_session->uid); + prop->message_id = amqp_cstring_bytes("query"); + } + + + + if (success) + { + + /**Try to convert to a canonical form and use the plain query if unsuccessful*/ + if ((canon_q = skygw_get_canonical(queue)) == NULL) + { + MXS_ERROR("Cannot form canonical query."); + } + + } + + memset(t_buf, 0, 128); + sprintf(t_buf, "%lu|", (unsigned long) time(NULL)); + + int qlen = strnlen(canon_q, length) + strnlen(t_buf, 128); + if ((combined = malloc((qlen + 1) * sizeof(char))) == NULL) + { + MXS_ERROR("Out of memory"); + } + strcpy(combined, t_buf); + strncat(combined, canon_q, length); + + pushMessage(my_instance, prop, combined); + free(canon_q); + } + + } + + /** Pass the query downstream */ } - - - - if(my_instance->trgtype & TRG_SCHEMA && my_instance->shm_trg){ - int tbsz = 0,z; - char** tblnames = skygw_get_table_names(queue,&tbsz,true); - char* tmp; - bool all_remotes = true; - - for(z = 0;zshm_trg->size; i++){ - - if(strcmp(tmp,my_instance->shm_trg->objects[i]) == 0){ - - MXS_INFO("Trigger is TRG_SCHEMA: %s = %s",tmp,my_instance->shm_trg->objects[i]); - - schema_ok = true; - break; - } - } - }else{ - all_remotes = false; - } - free(tblnames[z]); - } - free(tblnames); - - if(!schema_ok && !all_remotes && my_session->db && strlen(my_session->db)>0){ - - for(i = 0; ishm_trg->size; i++){ - - if(strcmp(my_session->db,my_instance->shm_trg->objects[i]) == 0){ - - MXS_INFO("Trigger is TRG_SCHEMA: %s = %s",my_session->db,my_instance->shm_trg->objects[i]); - - schema_ok = true; - break; - } - } - } - - if(schema_ok && !my_instance->strict_logging){ - src_ok = true; - obj_ok = true; - goto validate_triggers; - } - - }else{ - schema_ok = true; - } - - - if(my_instance->trgtype & TRG_OBJECT && my_instance->obj_trg){ - - sesstbls = skygw_get_table_names(queue,&dbcount,false); - - for(j = 0; jobj_trg->size; i++){ - - - if(!strcmp(tbnm,my_instance->obj_trg->objects[i])){ - obj_ok = true; - MXS_INFO("Trigger is TRG_OBJECT: %s = %s",my_instance->obj_trg->objects[i],sesstbls[j]); - break; - } - - } - - } - if(dbcount > 0){ - for(j = 0; jstrict_logging){ - src_ok = true; - schema_ok = true; - goto validate_triggers; - } - - }else{ - obj_ok = true; - } - - - validate_triggers: - - if(src_ok&&schema_ok&&obj_ok){ - - /** - * Something matched the trigger, log the query - */ - - MXS_INFO("Routing message to: %s:%d %s as %s/%s, exchange: %s<%s> key:%s queue:%s", - my_instance->hostname,my_instance->port, - my_instance->vhost,my_instance->username, - my_instance->password,my_instance->exchange, - my_instance->exchange_type,my_instance->key, - my_instance->queue); - - if(my_session->uid == NULL){ - - my_session->uid = calloc(33,sizeof(char)); - - if(!my_session->uid){ - MXS_ERROR("Out of memory."); - }else{ - genkey(my_session->uid,32); - } - - } - - if (queue->next != NULL) - { - queue = gwbuf_make_contiguous(queue); - } - - if(modutil_extract_SQL(queue, &ptr, &length)){ - - my_session->was_query = true; - - if((prop = malloc(sizeof(amqp_basic_properties_t)))){ - prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG | - AMQP_BASIC_DELIVERY_MODE_FLAG | - AMQP_BASIC_MESSAGE_ID_FLAG | - AMQP_BASIC_CORRELATION_ID_FLAG; - prop->content_type = amqp_cstring_bytes("text/plain"); - prop->delivery_mode = AMQP_DELIVERY_PERSISTENT; - prop->correlation_id = amqp_cstring_bytes(my_session->uid); - prop->message_id = amqp_cstring_bytes("query"); - } - - - - if(success){ - - /**Try to convert to a canonical form and use the plain query if unsuccessful*/ - if((canon_q = skygw_get_canonical(queue)) == NULL){ - MXS_ERROR("Cannot form canonical query."); - } - - } - - memset(t_buf,0,128); - sprintf(t_buf, "%lu|",(unsigned long)time(NULL)); - - int qlen = strnlen(canon_q,length) + strnlen(t_buf,128); - if((combined = malloc((qlen+1)*sizeof(char))) == NULL){ - MXS_ERROR("Out of memory"); - } - strcpy(combined,t_buf); - strncat(combined,canon_q,length); - - pushMessage(my_instance,prop,combined); - free(canon_q); - } - - } - - /** Pass the query downstream */ - } - send_downstream: - return my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, queue); +send_downstream: + return my_session->down.routeQuery(my_session->down.instance, + my_session->down.session, queue); } /** @@ -1276,49 +1405,61 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue) */ unsigned int leitoi(unsigned char* c) { - unsigned char* ptr = c; - unsigned int sz = *ptr; - if(*ptr < 0xfb) return sz; - if(*ptr == 0xfc){ - sz = *++ptr; - sz += (*++ptr << 8); - }else if(*ptr == 0xfd){ - sz = *++ptr; - sz += (*++ptr << 8); - sz += (*++ptr << 8); - }else{ - sz = *++ptr; - sz += (*++ptr << 8); - sz += (*++ptr << 8); - sz += (*++ptr << 8); - sz += (*++ptr << 8); - sz += (*++ptr << 8); - sz += (*++ptr << 8); - sz += (*++ptr << 8); - sz += (*++ptr << 8); - } - return sz; + unsigned char* ptr = c; + unsigned int sz = *ptr; + if (*ptr < 0xfb) return sz; + if (*ptr == 0xfc) + { + sz = *++ptr; + sz += (*++ptr << 8); + } + else if (*ptr == 0xfd) + { + sz = *++ptr; + sz += (*++ptr << 8); + sz += (*++ptr << 8); + } + else + { + sz = *++ptr; + sz += (*++ptr << 8); + sz += (*++ptr << 8); + sz += (*++ptr << 8); + sz += (*++ptr << 8); + sz += (*++ptr << 8); + sz += (*++ptr << 8); + sz += (*++ptr << 8); + sz += (*++ptr << 8); + } + return sz; } /** - * Converts a length-encoded integer into a standard unsigned integer + * Converts a length-encoded integer into a standard unsigned integer * and advances the pointer to the next unrelated byte. * * @param c Pointer to the first byte of a length-encoded integer */ unsigned int consume_leitoi(unsigned char** c) { - unsigned int rval = leitoi(*c); - if(**c == 0xfc){ - *c += 3; - }else if(**c == 0xfd){ - *c += 4; - }else if(**c == 0xfe){ - *c += 9; - }else{ - *c += 1; - } - return rval; + unsigned int rval = leitoi(*c); + if (**c == 0xfc) + { + *c += 3; + } + else if (**c == 0xfd) + { + *c += 4; + } + else if (**c == 0xfe) + { + *c += 9; + } + else + { + *c += 1; + } + return rval; } /** @@ -1329,13 +1470,14 @@ unsigned int consume_leitoi(unsigned char** c) */ char* consume_lestr(unsigned char** c) { - unsigned int slen = consume_leitoi(c); - char *str = calloc((slen + 1), sizeof(char)); - if(str){ - memcpy(str,*c,slen); - *c += slen; - } - return str; + unsigned int slen = consume_leitoi(c); + char *str = calloc((slen + 1), sizeof(char)); + if (str) + { + memcpy(str, *c, slen); + *c += slen; + } + return str; } /** @@ -1345,11 +1487,10 @@ char* consume_lestr(unsigned char** c) */ unsigned int is_eof(void* p) { - unsigned char* ptr = (unsigned char*) p; - return *(ptr) == 0x05 && *(ptr + 1) == 0x00 && *(ptr + 2) == 0x00 && *(ptr + 4) == 0xfe; + unsigned char* ptr = (unsigned char*) p; + return *(ptr) == 0x05 && *(ptr + 1) == 0x00 && *(ptr + 2) == 0x00 && *(ptr + 4) == 0xfe; } - /** * The clientReply entry point. This is passed the response buffer * to which the filter should be applied. Once processed the @@ -1359,127 +1500,142 @@ unsigned int is_eof(void* p) * The function tries to extract a SQL query response out of the response buffer, * adds a timestamp to it and publishes the resulting string on the exchange. * The message is tagged with the same identifier that the query was. - * + * * @param instance The filter instance data * @param session The filter session * @param reply The response data */ static int clientReply(FILTER* instance, void *session, GWBUF *reply) { - MQ_SESSION *my_session = (MQ_SESSION *)session; - MQ_INSTANCE *my_instance = (MQ_INSTANCE *)instance; - char t_buf[128],*combined; - unsigned int pkt_len = pktlen(reply->sbuf->data), offset = 0; - amqp_basic_properties_t *prop; + MQ_SESSION *my_session = (MQ_SESSION *) session; + MQ_INSTANCE *my_instance = (MQ_INSTANCE *) instance; + char t_buf[128], *combined; + unsigned int pkt_len = pktlen(reply->sbuf->data), offset = 0; + amqp_basic_properties_t *prop; - if (my_session->was_query){ + if (my_session->was_query) + { - int packet_ok = 0, was_last = 0; + int packet_ok = 0, was_last = 0; - my_session->was_query = false; + my_session->was_query = false; - if(pkt_len > 0){ - if((prop = malloc(sizeof(amqp_basic_properties_t)))){ - prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG | - AMQP_BASIC_DELIVERY_MODE_FLAG | - AMQP_BASIC_MESSAGE_ID_FLAG | - AMQP_BASIC_CORRELATION_ID_FLAG; - prop->content_type = amqp_cstring_bytes("text/plain"); - prop->delivery_mode = AMQP_DELIVERY_PERSISTENT; - prop->correlation_id = amqp_cstring_bytes(my_session->uid); - prop->message_id = amqp_cstring_bytes("reply"); - } - if(!(combined = calloc(GWBUF_LENGTH(reply) + 256,sizeof(char)))){ - MXS_ERROR("Out of memory"); - } + if (pkt_len > 0) + { + if ((prop = malloc(sizeof(amqp_basic_properties_t)))) + { + prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG | + AMQP_BASIC_DELIVERY_MODE_FLAG | + AMQP_BASIC_MESSAGE_ID_FLAG | + AMQP_BASIC_CORRELATION_ID_FLAG; + prop->content_type = amqp_cstring_bytes("text/plain"); + prop->delivery_mode = AMQP_DELIVERY_PERSISTENT; + prop->correlation_id = amqp_cstring_bytes(my_session->uid); + prop->message_id = amqp_cstring_bytes("reply"); + } + if (!(combined = calloc(GWBUF_LENGTH(reply) + 256, sizeof(char)))) + { + MXS_ERROR("Out of memory"); + } - memset(t_buf,0,128); - sprintf(t_buf,"%lu|",(unsigned long)time(NULL)); - - - memcpy(combined + offset,t_buf,strnlen(t_buf,40)); - offset += strnlen(t_buf,40); + memset(t_buf, 0, 128); + sprintf(t_buf, "%lu|", (unsigned long) time(NULL)); - if(*(reply->sbuf->data + 4) == 0x00){ /**OK packet*/ - unsigned int aff_rows = 0, l_id = 0, s_flg = 0, wrn = 0; - unsigned char *ptr = (unsigned char*)(reply->sbuf->data + 5); - pkt_len = pktlen(reply->sbuf->data); - aff_rows = consume_leitoi(&ptr); - l_id = consume_leitoi(&ptr); - s_flg |= *ptr++; - s_flg |= (*ptr++ << 8); - wrn |= *ptr++; - wrn |= (*ptr++ << 8); - sprintf(combined + offset,"OK - affected_rows: %d " - " last_insert_id: %d " - " status_flags: %#0x " - " warnings: %d ", - aff_rows,l_id,s_flg,wrn); - offset += strnlen(combined,GWBUF_LENGTH(reply) + 256) - offset; - if(pkt_len > 7){ - int plen = consume_leitoi(&ptr); - if(plen > 0){ - sprintf(combined + offset," message: %.*s\n",plen,ptr); - } - } + memcpy(combined + offset, t_buf, strnlen(t_buf, 40)); + offset += strnlen(t_buf, 40); - packet_ok = 1; - was_last = 1; + if (*(reply->sbuf->data + 4) == 0x00) + { /**OK packet*/ + unsigned int aff_rows = 0, l_id = 0, s_flg = 0, wrn = 0; + unsigned char *ptr = (unsigned char*) (reply->sbuf->data + 5); + pkt_len = pktlen(reply->sbuf->data); + aff_rows = consume_leitoi(&ptr); + l_id = consume_leitoi(&ptr); + s_flg |= *ptr++; + s_flg |= (*ptr++ << 8); + wrn |= *ptr++; + wrn |= (*ptr++ << 8); + sprintf(combined + offset, "OK - affected_rows: %d " + " last_insert_id: %d " + " status_flags: %#0x " + " warnings: %d ", + aff_rows, l_id, s_flg, wrn); + offset += strnlen(combined, GWBUF_LENGTH(reply) + 256) - offset; - }else if(*(reply->sbuf->data + 4) == 0xff){ /**ERR packet*/ + if (pkt_len > 7) + { + int plen = consume_leitoi(&ptr); + if (plen > 0) + { + sprintf(combined + offset, " message: %.*s\n", plen, ptr); + } + } - sprintf(combined + offset,"ERROR - message: %.*s", - (int)(reply->end - ((void*)(reply->sbuf->data + 13))), - (char *)reply->sbuf->data + 13); - packet_ok = 1; - was_last = 1; - - }else if(*(reply->sbuf->data + 4) == 0xfb){ /**LOCAL_INFILE request packet*/ - - unsigned char *rset = (unsigned char*)reply->sbuf->data; - strcpy(combined + offset,"LOCAL_INFILE: "); - strncat(combined + offset,(const char*)rset+5,pktlen(rset)); - packet_ok = 1; - was_last = 1; - - }else{ /**Result set*/ - - unsigned char *rset = (unsigned char*)(reply->sbuf->data + 4); - char *tmp; - unsigned int col_cnt = consume_leitoi(&rset); + packet_ok = 1; + was_last = 1; - tmp = calloc(256,sizeof(char)); - sprintf(tmp,"Columns: %d",col_cnt); - memcpy(combined + offset,tmp,strnlen(tmp,256)); - offset += strnlen(tmp,256); - memcpy(combined + offset,"\n",1); - offset++; - free(tmp); - - packet_ok = 1; - was_last = 1; - - } - if(packet_ok){ + } + else if (*(reply->sbuf->data + 4) == 0xff) + { /**ERR packet*/ - pushMessage(my_instance,prop,combined); + sprintf(combined + offset, "ERROR - message: %.*s", + (int) (reply->end - ((void*) (reply->sbuf->data + 13))), + (char *) reply->sbuf->data + 13); + packet_ok = 1; + was_last = 1; - if(was_last){ + } + else if (*(reply->sbuf->data + 4) == 0xfb) + { /**LOCAL_INFILE request packet*/ - /**Successful reply received and sent, releasing uid*/ - - free(my_session->uid); - my_session->uid = NULL; + unsigned char *rset = (unsigned char*) reply->sbuf->data; + strcpy(combined + offset, "LOCAL_INFILE: "); + strncat(combined + offset, (const char*) rset + 5, pktlen(rset)); + packet_ok = 1; + was_last = 1; + + } + else + { /**Result set*/ + + unsigned char *rset = (unsigned char*) (reply->sbuf->data + 4); + char *tmp; + unsigned int col_cnt = consume_leitoi(&rset); + + tmp = calloc(256, sizeof(char)); + sprintf(tmp, "Columns: %d", col_cnt); + memcpy(combined + offset, tmp, strnlen(tmp, 256)); + offset += strnlen(tmp, 256); + memcpy(combined + offset, "\n", 1); + offset++; + free(tmp); + + packet_ok = 1; + was_last = 1; + + } + if (packet_ok) + { + + pushMessage(my_instance, prop, combined); + + if (was_last) + { + + /**Successful reply received and sent, releasing uid*/ + + free(my_session->uid); + my_session->uid = NULL; + + } + } + } - } - } } - } - - return my_session->up.clientReply(my_session->up.instance, - my_session->up.session, reply); + return my_session->up.clientReply(my_session->up.instance, + my_session->up.session, reply); } /** @@ -1492,25 +1648,24 @@ static int clientReply(FILTER* instance, void *session, GWBUF *reply) * @param fsession Filter session, may be NULL * @param dcb The DCB for diagnostic output */ -static void +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb) { - MQ_INSTANCE *my_instance = (MQ_INSTANCE *)instance; + MQ_INSTANCE *my_instance = (MQ_INSTANCE *) instance; - if (my_instance) + if (my_instance) { - dcb_printf(dcb, "Connecting to %s:%d as '%s'.\nVhost: %s\tExchange: %s\nKey: %s\tQueue: %s\n\n", - my_instance->hostname,my_instance->port, - my_instance->username, - my_instance->vhost, my_instance->exchange, - my_instance->key, my_instance->queue - ); - dcb_printf(dcb, "%-16s%-16s%-16s\n", - "Messages","Queued","Sent"); - dcb_printf(dcb, "%-16d%-16d%-16d\n", - my_instance->stats.n_msg, - my_instance->stats.n_queued, - my_instance->stats.n_sent); + dcb_printf(dcb, "Connecting to %s:%d as '%s'.\nVhost: %s\tExchange: %s\nKey: %s\tQueue: %s\n\n", + my_instance->hostname, my_instance->port, + my_instance->username, + my_instance->vhost, my_instance->exchange, + my_instance->key, my_instance->queue + ); + dcb_printf(dcb, "%-16s%-16s%-16s\n", + "Messages", "Queued", "Sent"); + dcb_printf(dcb, "%-16d%-16d%-16d\n", + my_instance->stats.n_msg, + my_instance->stats.n_queued, + my_instance->stats.n_sent); } } - diff --git a/server/modules/filter/namedserverfilter.c b/server/modules/filter/namedserverfilter.c index c634d8198..a7a9a09e2 100644 --- a/server/modules/filter/namedserverfilter.c +++ b/server/modules/filter/namedserverfilter.c @@ -15,6 +15,7 @@ * * Copyright MariaDB Corporation Ab 2014 */ + #include #include #include @@ -32,42 +33,44 @@ * * A simple regular expression based query routing filter. * Two parameters should be defined in the filter configuration - * match= - * server= + * match= + * server= * Two optional parameters - * source= - * user= + * source= + * user= * - * Date Who Description - * 22/01/2015 Mark Riddoch Written as example based on regex filter + * Date Who Description + * 22/01/2015 Mark Riddoch Written as example based on regex filter * @endverbatim */ -MODULE_INFO info = { - MODULE_API_FILTER, - MODULE_GA, - FILTER_VERSION, - "A routing hint filter that uses regular expressions to direct queries" +MODULE_INFO info = +{ + MODULE_API_FILTER, + MODULE_GA, + FILTER_VERSION, + "A routing hint filter that uses regular expressions to direct queries" }; static char *version_str = "V1.1.0"; -static FILTER *createInstance(char **options, FILTER_PARAMETER **params); -static void *newSession(FILTER *instance, SESSION *session); -static void closeSession(FILTER *instance, void *session); -static void freeSession(FILTER *instance, void *session); -static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); -static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); -static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); +static FILTER *createInstance(char **options, FILTER_PARAMETER **params); +static void *newSession(FILTER *instance, SESSION *session); +static void closeSession(FILTER *instance, void *session); +static void freeSession(FILTER *instance, void *session); +static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); +static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); -static FILTER_OBJECT MyObject = { +static FILTER_OBJECT MyObject = +{ createInstance, newSession, closeSession, freeSession, setDownstream, - NULL, // No Upstream requirement + NULL, // No Upstream requirement routeQuery, NULL, diagnostic, @@ -76,23 +79,25 @@ static FILTER_OBJECT MyObject = { /** * Instance structure */ -typedef struct { - char *source; /* Source address to restrict matches */ - char *user; /* User name to restrict matches */ - char *match; /* Regular expression to match */ - char *server; /* Server to route to */ - int cflags; /* Regexec compile flags */ - regex_t re; /* Compiled regex text */ +typedef struct +{ + char *source; /* Source address to restrict matches */ + char *user; /* User name to restrict matches */ + char *match; /* Regular expression to match */ + char *server; /* Server to route to */ + int cflags; /* Regexec compile flags */ + regex_t re; /* Compiled regex text */ } REGEXHINT_INSTANCE; /** * The session structuee for this regex filter */ -typedef struct { - DOWNSTREAM down; /* The downstream filter */ - int n_diverted; /* No. of statements diverted */ - int n_undiverted; /* No. of statements not diverted */ - int active; /* Is filter active */ +typedef struct +{ + DOWNSTREAM down; /* The downstream filter */ + int n_diverted; /* No. of statements diverted */ + int n_undiverted; /* No. of statements not diverted */ + int active; /* Is filter active */ } REGEXHINT_SESSION; /** @@ -103,7 +108,7 @@ typedef struct { char * version() { - return version_str; + return version_str; } /** @@ -126,134 +131,142 @@ ModuleInit() FILTER_OBJECT * GetModuleObject() { - return &MyObject; + return &MyObject; } /** * Create an instance of the filter for a particular service * within MaxScale. - * - * @param options The options for this filter - * @param params The array of name/value pair parameters for the filter + * + * @param options The options for this filter + * @param params The array of name/value pair parameters for the filter * * @return The instance data for this new instance */ -static FILTER * +static FILTER * createInstance(char **options, FILTER_PARAMETER **params) { -REGEXHINT_INSTANCE *my_instance; -int i, cflags = REG_ICASE; + REGEXHINT_INSTANCE *my_instance; + int i, cflags = REG_ICASE; - if ((my_instance = calloc(1, sizeof(REGEXHINT_INSTANCE))) != NULL) - { - my_instance->match = NULL; - my_instance->server = NULL; + if ((my_instance = calloc(1, sizeof(REGEXHINT_INSTANCE))) != NULL) + { + my_instance->match = NULL; + my_instance->server = NULL; - for (i = 0; params && params[i]; i++) - { - if (!strcmp(params[i]->name, "match")) - my_instance->match = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "server")) - my_instance->server = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "source")) - my_instance->source = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "user")) - my_instance->user = strdup(params[i]->value); - else if (!filter_standard_parameter(params[i]->name)) - { - MXS_ERROR("namedserverfilter: Unexpected parameter '%s'.", - params[i]->name); - } - } + for (i = 0; params && params[i]; i++) + { + if (!strcmp(params[i]->name, "match")) + { + my_instance->match = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "server")) + { + my_instance->server = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "source")) + { + my_instance->source = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "user")) + { + my_instance->user = strdup(params[i]->value); + } + else if (!filter_standard_parameter(params[i]->name)) + { + MXS_ERROR("namedserverfilter: Unexpected parameter '%s'.", + params[i]->name); + } + } - if (options) - { - for (i = 0; options[i]; i++) - { - if (!strcasecmp(options[i], "ignorecase")) - { - cflags |= REG_ICASE; - } - else if (!strcasecmp(options[i], "case")) - { - cflags &= ~REG_ICASE; - } - else - { - MXS_ERROR("namedserverfilter: unsupported option '%s'.", - options[i]); - } - } - } - my_instance->cflags = cflags; + if (options) + { + for (i = 0; options[i]; i++) + { + if (!strcasecmp(options[i], "ignorecase")) + { + cflags |= REG_ICASE; + } + else if (!strcasecmp(options[i], "case")) + { + cflags &= ~REG_ICASE; + } + else + { + MXS_ERROR("namedserverfilter: unsupported option '%s'.", + options[i]); + } + } + } + my_instance->cflags = cflags; - if (my_instance->match == NULL || my_instance->server == NULL) - { - MXS_ERROR("namedserverfilter: Missing required configured" - " option. You must specify a match and server " - "option as a minimum."); - free(my_instance); - return NULL; - } + if (my_instance->match == NULL || my_instance->server == NULL) + { + MXS_ERROR("namedserverfilter: Missing required configured" + " option. You must specify a match and server " + "option as a minimum."); + free(my_instance); + return NULL; + } - if (regcomp(&my_instance->re, my_instance->match, - my_instance->cflags)) - { - MXS_ERROR("namedserverfilter: Invalid regular expression '%s'.\n", - my_instance->match); - free(my_instance->match); - free(my_instance->server); - free(my_instance); - return NULL; - } - } - return (FILTER *)my_instance; + if (regcomp(&my_instance->re, my_instance->match, + my_instance->cflags)) + { + MXS_ERROR("namedserverfilter: Invalid regular expression '%s'.\n", + my_instance->match); + free(my_instance->match); + free(my_instance->server); + free(my_instance); + return NULL; + } + } + return(FILTER *) my_instance; } /** * Associate a new session with this instance of the filter. * - * @param instance The filter instance data - * @param session The session itself + * @param instance The filter instance data + * @param session The session itself * @return Session specific data for this session */ -static void * +static void * newSession(FILTER *instance, SESSION *session) { -REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *)instance; -REGEXHINT_SESSION *my_session; -char *remote, *user; + REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance; + REGEXHINT_SESSION *my_session; + char *remote, *user; - if ((my_session = calloc(1, sizeof(REGEXHINT_SESSION))) != NULL) - { - my_session->n_diverted = 0; - my_session->n_undiverted = 0; - my_session->active = 1; - if (my_instance->source - && (remote = session_get_remote(session)) != NULL) - { - if (strcmp(remote, my_instance->source)) - my_session->active = 0; - } + if ((my_session = calloc(1, sizeof(REGEXHINT_SESSION))) != NULL) + { + my_session->n_diverted = 0; + my_session->n_undiverted = 0; + my_session->active = 1; + if (my_instance->source + && (remote = session_get_remote(session)) != NULL) + { + if (strcmp(remote, my_instance->source)) + my_session->active = 0; + } - if (my_instance->user && (user = session_getUser(session)) - && strcmp(user, my_instance->user)) - { - my_session->active = 0; - } - } + if (my_instance->user && (user = session_getUser(session)) + && strcmp(user, my_instance->user)) + { + my_session->active = 0; + } + } - return my_session; + return my_session; } /** * Close a session with the filter, this is the mechanism * by which a filter may cleanup data structure etc. * - * @param instance The filter instance data - * @param session The session being closed + * @param instance The filter instance data + * @param session The session being closed */ -static void +static void closeSession(FILTER *instance, void *session) { } @@ -261,29 +274,28 @@ closeSession(FILTER *instance, void *session) /** * Free the memory associated with this filter session. * - * @param instance The filter instance data - * @param session The session being closed + * @param instance The filter instance data + * @param session The session being closed */ static void freeSession(FILTER *instance, void *session) { - free(session); - return; + free(session); + return; } /** * Set the downstream component for this filter. * - * @param instance The filter instance data - * @param session The session being closed - * @param downstream The downstream filter or router + * @param instance The filter instance data + * @param session The session being closed + * @param downstream The downstream filter or router */ static void setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) { -REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)session; - - my_session->down = *downstream; + REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) session; + my_session->down = *downstream; } /** @@ -296,40 +308,41 @@ REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)session; * filter definition matches the SQL text then add the hint * "Route to named server" with the name defined in the server parameter * - * @param instance The filter instance data - * @param session The filter session - * @param queue The query data + * @param instance The filter instance data + * @param session The filter session + * @param queue The query data */ -static int +static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { -REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *)instance; -REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)session; -char *sql; + REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance; + REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) session; + char *sql; - if (modutil_is_SQL(queue)) - { - if (queue->next != NULL) - { - queue = gwbuf_make_contiguous(queue); - } - if ((sql = modutil_get_SQL(queue)) != NULL) - { - if (regexec(&my_instance->re,sql,0,NULL, 0) == 0) - { - queue->hint = hint_create_route(queue->hint, - HINT_ROUTE_TO_NAMED_SERVER, - my_instance->server); - my_session->n_diverted++; - } - else - my_session->n_undiverted++; - free(sql); - } - - } - return my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, queue); + if (modutil_is_SQL(queue)) + { + if (queue->next != NULL) + { + queue = gwbuf_make_contiguous(queue); + } + if ((sql = modutil_get_SQL(queue)) != NULL) + { + if (regexec(&my_instance->re, sql, 0, NULL, 0) == 0) + { + queue->hint = hint_create_route(queue->hint, + HINT_ROUTE_TO_NAMED_SERVER, + my_instance->server); + my_session->n_diverted++; + } + else + { + my_session->n_undiverted++; + } + free(sql); + } + } + return my_session->down.routeQuery(my_session->down.instance, + my_session->down.session, queue); } /** @@ -339,31 +352,35 @@ char *sql; * instance as a whole, otherwise print diagnostics for the * particular session. * - * @param instance The filter instance - * @param fsession Filter session, may be NULL - * @param dcb The DCB for diagnostic output + * @param instance The filter instance + * @param fsession Filter session, may be NULL + * @param dcb The DCB for diagnostic output */ -static void +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb) { -REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *)instance; -REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)fsession; + REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance; + REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) fsession; - dcb_printf(dcb, "\t\tMatch and route: /%s/ -> %s\n", - my_instance->match, my_instance->server); - if (my_session) - { - dcb_printf(dcb, "\t\tNo. of queries diverted by filter: %d\n", - my_session->n_diverted); - dcb_printf(dcb, "\t\tNo. of queries not diverted by filter: %d\n", - my_session->n_undiverted); - } - if (my_instance->source) - dcb_printf(dcb, - "\t\tReplacement limited to connections from %s\n", - my_instance->source); - if (my_instance->user) - dcb_printf(dcb, - "\t\tReplacement limit to user %s\n", - my_instance->user); + dcb_printf(dcb, "\t\tMatch and route: /%s/ -> %s\n", + my_instance->match, my_instance->server); + if (my_session) + { + dcb_printf(dcb, "\t\tNo. of queries diverted by filter: %d\n", + my_session->n_diverted); + dcb_printf(dcb, "\t\tNo. of queries not diverted by filter: %d\n", + my_session->n_undiverted); + } + if (my_instance->source) + { + dcb_printf(dcb, + "\t\tReplacement limited to connections from %s\n", + my_instance->source); + } + if (my_instance->user) + { + dcb_printf(dcb, + "\t\tReplacement limit to user %s\n", + my_instance->user); + } } diff --git a/server/modules/filter/qlafilter.c b/server/modules/filter/qlafilter.c index 1b72326ea..89adf4849 100644 --- a/server/modules/filter/qlafilter.c +++ b/server/modules/filter/qlafilter.c @@ -31,13 +31,14 @@ * file to which the queries are logged. A serial number is appended to this * name in order that each session logs to a different file. * - * Date Who Description - * 03/06/2014 Mark Riddoch Initial implementation - * 11/06/2014 Mark Riddoch Addition of source and match parameters - * 19/06/2014 Mark Riddoch Addition of user parameter + * Date Who Description + * 03/06/2014 Mark Riddoch Initial implementation + * 11/06/2014 Mark Riddoch Addition of source and match parameters + * 19/06/2014 Mark Riddoch Addition of user parameter * * @endverbatim */ + #include #include #include @@ -52,11 +53,12 @@ #include #include -MODULE_INFO info = { - MODULE_API_FILTER, - MODULE_GA, - FILTER_VERSION, - "A simple query logging filter" +MODULE_INFO info = +{ + MODULE_API_FILTER, + MODULE_GA, + FILTER_VERSION, + "A simple query logging filter" }; static char *version_str = "V1.1.1"; @@ -64,24 +66,25 @@ static char *version_str = "V1.1.1"; /* * The filter entry points */ -static FILTER *createInstance(char **options, FILTER_PARAMETER **); -static void *newSession(FILTER *instance, SESSION *session); -static void closeSession(FILTER *instance, void *session); -static void freeSession(FILTER *instance, void *session); -static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); -static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); -static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); +static FILTER *createInstance(char **options, FILTER_PARAMETER **); +static void *newSession(FILTER *instance, SESSION *session); +static void closeSession(FILTER *instance, void *session); +static void freeSession(FILTER *instance, void *session); +static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); +static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); -static FILTER_OBJECT MyObject = { +static FILTER_OBJECT MyObject = +{ createInstance, newSession, closeSession, freeSession, setDownstream, - NULL, // No Upstream requirement + NULL, // No Upstream requirement routeQuery, - NULL, // No client reply + NULL, // No client reply diagnostic, }; @@ -93,30 +96,32 @@ static FILTER_OBJECT MyObject = { * To this base a session number is attached such that each session will * have a unique name. */ -typedef struct { - int sessions; /* The count of sessions */ - char *filebase; /* The filename base */ - char *source; /* The source of the client connection */ - char *userName; /* The user name to filter on */ - char *match; /* Optional text to match against */ - regex_t re; /* Compiled regex text */ - char *nomatch; /* Optional text to match against for exclusion */ - regex_t nore; /* Compiled regex nomatch text */ +typedef struct +{ + int sessions; /* The count of sessions */ + char *filebase; /* The filename base */ + char *source; /* The source of the client connection */ + char *userName; /* The user name to filter on */ + char *match; /* Optional text to match against */ + regex_t re; /* Compiled regex text */ + char *nomatch; /* Optional text to match against for exclusion */ + regex_t nore; /* Compiled regex nomatch text */ } QLA_INSTANCE; /** * The session structure for this QLA filter. - * This stores the downstream filter information, such that the + * This stores the downstream filter information, such that the * filter is able to pass the query on to the next filter (or router) * in the chain. * * It also holds the file descriptor to which queries are written. */ -typedef struct { - DOWNSTREAM down; - char *filename; - FILE *fp; - int active; +typedef struct +{ + DOWNSTREAM down; + char *filename; + FILE *fp; + int active; } QLA_SESSION; /** @@ -127,7 +132,7 @@ typedef struct { char * version() { - return version_str; + return version_str; } /** @@ -150,100 +155,112 @@ ModuleInit() FILTER_OBJECT * GetModuleObject() { - return &MyObject; + return &MyObject; } /** * Create an instance of the filter for a particular service * within MaxScale. - * - * @param options The options for this filter - * @param params The array of name/value pair parameters for the filter + * + * @param options The options for this filter + * @param params The array of name/value pair parameters for the filter * * @return The instance data for this new instance */ -static FILTER * +static FILTER * createInstance(char **options, FILTER_PARAMETER **params) { -QLA_INSTANCE *my_instance; -int i; + QLA_INSTANCE *my_instance; + int i; - if ((my_instance = calloc(1, sizeof(QLA_INSTANCE))) != NULL) - { - if (options){ - my_instance->filebase = strdup(options[0]); - }else{ - my_instance->filebase = strdup("qla"); - } - my_instance->source = NULL; - my_instance->userName = NULL; - my_instance->match = NULL; - my_instance->nomatch = NULL; - if (params) - { - for (i = 0; params[i]; i++) - { - if (!strcmp(params[i]->name, "match")) - { - my_instance->match = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "exclude")) - { - my_instance->nomatch = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "source")) - my_instance->source = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "user")) - my_instance->userName = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "filebase")) - { - if (my_instance->filebase){ - free(my_instance->filebase); - my_instance->filebase = NULL; - } - my_instance->filebase = strdup(params[i]->value); - } - else if (!filter_standard_parameter(params[i]->name)) - { - MXS_ERROR("qlafilter: Unexpected parameter '%s'.", - params[i]->name); - } - } - } - my_instance->sessions = 0; - if (my_instance->match && - regcomp(&my_instance->re, my_instance->match, REG_ICASE)) - { - MXS_ERROR("qlafilter: Invalid regular expression '%s'" - " for the match parameter.\n", - my_instance->match); - free(my_instance->match); - free(my_instance->source); - if(my_instance->filebase){ + if ((my_instance = calloc(1, sizeof(QLA_INSTANCE))) != NULL) + { + if (options) + { + my_instance->filebase = strdup(options[0]); + } + else + { + my_instance->filebase = strdup("qla"); + } + my_instance->source = NULL; + my_instance->userName = NULL; + my_instance->match = NULL; + my_instance->nomatch = NULL; + if (params) + { + for (i = 0; params[i]; i++) + { + if (!strcmp(params[i]->name, "match")) + { + my_instance->match = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "exclude")) + { + my_instance->nomatch = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "source")) + { + my_instance->source = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "user")) + { + my_instance->userName = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "filebase")) + { + if (my_instance->filebase) + { free(my_instance->filebase); + my_instance->filebase = NULL; } - free(my_instance); - return NULL; - } - if (my_instance->nomatch && - regcomp(&my_instance->nore, my_instance->nomatch, - REG_ICASE)) - { + my_instance->filebase = strdup(params[i]->value); + } + else if (!filter_standard_parameter(params[i]->name)) + { + MXS_ERROR("qlafilter: Unexpected parameter '%s'.", + params[i]->name); + } + } + } + my_instance->sessions = 0; + if (my_instance->match && + regcomp(&my_instance->re, my_instance->match, REG_ICASE)) + { + MXS_ERROR("qlafilter: Invalid regular expression '%s'" + " for the match parameter.\n", + my_instance->match); + free(my_instance->match); + free(my_instance->source); + if (my_instance->filebase) + { + free(my_instance->filebase); + } + free(my_instance); + return NULL; + } + if (my_instance->nomatch && + regcomp(&my_instance->nore, my_instance->nomatch, + REG_ICASE)) + { MXS_ERROR("qlafilter: Invalid regular expression '%s'" " for the nomatch paramter.", my_instance->match); - if (my_instance->match) - regfree(&my_instance->re); - free(my_instance->match); - free(my_instance->source); - if(my_instance->filebase){ - free(my_instance->filebase); - } - free(my_instance); - return NULL; - } - } - return (FILTER *)my_instance; + if (my_instance->match) + { + regfree(&my_instance->re); + } + free(my_instance->match); + free(my_instance->source); + if (my_instance->filebase) + { + free(my_instance->filebase); + } + free(my_instance); + return NULL; + } + } + return(FILTER *) my_instance; } /** @@ -251,80 +268,82 @@ int i; * * Create the file to log to and open it. * - * @param instance The filter instance data - * @param session The session itself + * @param instance The filter instance data + * @param session The session itself * @return Session specific data for this session */ -static void * +static void * newSession(FILTER *instance, SESSION *session) { -QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; -QLA_SESSION *my_session; -char *remote, *userName; + QLA_INSTANCE *my_instance = (QLA_INSTANCE *) instance; + QLA_SESSION *my_session; + char *remote, *userName; - if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL) - { - if ((my_session->filename = - (char *)malloc(strlen(my_instance->filebase) + 20)) - == NULL) - { - char errbuf[STRERROR_BUFLEN]; - MXS_ERROR("Memory allocation for qla filter " - "file name failed due to %d, %s.", - errno, - strerror_r(errno, errbuf, sizeof(errbuf))); - free(my_session); - return NULL; - } - my_session->active = 1; - - if (my_instance->source - && (remote = session_get_remote(session)) != NULL) - { - if (strcmp(remote, my_instance->source)) - my_session->active = 0; - } - userName = session_getUser(session); - - if (my_instance->userName && - userName && - strcmp(userName,my_instance->userName)) - { - my_session->active = 0; - } - sprintf(my_session->filename, "%s.%d", - my_instance->filebase, - my_instance->sessions); + if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL) + { + if ((my_session->filename = + (char *) malloc(strlen(my_instance->filebase) + 20)) + == NULL) + { + char errbuf[STRERROR_BUFLEN]; + MXS_ERROR("Memory allocation for qla filter " + "file name failed due to %d, %s.", + errno, + strerror_r(errno, errbuf, sizeof(errbuf))); + free(my_session); + return NULL; + } + my_session->active = 1; + + if (my_instance->source + && (remote = session_get_remote(session)) != NULL) + { + if (strcmp(remote, my_instance->source)) + { + my_session->active = 0; + } + } + userName = session_getUser(session); + + if (my_instance->userName && + userName && + strcmp(userName, my_instance->userName)) + { + my_session->active = 0; + } + sprintf(my_session->filename, "%s.%d", + my_instance->filebase, + my_instance->sessions); // Multiple sessions can try to update my_instance->sessions simultaneously - atomic_add(&(my_instance->sessions), 1); - - if (my_session->active) - { - my_session->fp = fopen(my_session->filename, "w"); - - if (my_session->fp == NULL) - { - char errbuf[STRERROR_BUFLEN]; - MXS_ERROR("Opening output file for qla " - "fileter failed due to %d, %s", - errno, - strerror_r(errno, errbuf, sizeof(errbuf))); - free(my_session->filename); - free(my_session); - my_session = NULL; - } - } - } - else - { + atomic_add(&(my_instance->sessions), 1); + + if (my_session->active) + { + my_session->fp = fopen(my_session->filename, "w"); + + if (my_session->fp == NULL) + { char errbuf[STRERROR_BUFLEN]; - MXS_ERROR("Memory allocation for qla filter failed due to " - "%d, %s.", + MXS_ERROR("Opening output file for qla " + "fileter failed due to %d, %s", errno, strerror_r(errno, errbuf, sizeof(errbuf))); - } - return my_session; + free(my_session->filename); + free(my_session); + my_session = NULL; + } + } + } + else + { + char errbuf[STRERROR_BUFLEN]; + MXS_ERROR("Memory allocation for qla filter failed due to " + "%d, %s.", + errno, + strerror_r(errno, errbuf, sizeof(errbuf))); + } + return my_session; } /** @@ -332,48 +351,50 @@ char *remote, *userName; * by which a filter may cleanup data structure etc. * In the case of the QLA filter we simple close the file descriptor. * - * @param instance The filter instance data - * @param session The session being closed + * @param instance The filter instance data + * @param session The session being closed */ -static void +static void closeSession(FILTER *instance, void *session) { -QLA_SESSION *my_session = (QLA_SESSION *)session; + QLA_SESSION *my_session = (QLA_SESSION *) session; - if (my_session->active && my_session->fp) - fclose(my_session->fp); + if (my_session->active && my_session->fp) + { + fclose(my_session->fp); + } } /** * Free the memory associated with the session * - * @param instance The filter instance - * @param session The filter session + * @param instance The filter instance + * @param session The filter session */ static void freeSession(FILTER *instance, void *session) { -QLA_SESSION *my_session = (QLA_SESSION *)session; + QLA_SESSION *my_session = (QLA_SESSION *) session; - free(my_session->filename); - free(session); - return; + free(my_session->filename); + free(session); + return; } /** * Set the downstream filter or router to which queries will be * passed from this filter. * - * @param instance The filter instance data - * @param session The filter session - * @param downstream The downstream filter or router. + * @param instance The filter instance data + * @param session The filter session + * @param downstream The downstream filter or router. */ static void setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) { -QLA_SESSION *my_session = (QLA_SESSION *)session; + QLA_SESSION *my_session = (QLA_SESSION *) session; - my_session->down = *downstream; + my_session->down = *downstream; } /** @@ -382,48 +403,48 @@ QLA_SESSION *my_session = (QLA_SESSION *)session; * query should normally be passed to the downstream component * (filter or router) in the filter chain. * - * @param instance The filter instance data - * @param session The filter session - * @param queue The query data + * @param instance The filter instance data + * @param session The filter session + * @param queue The query data */ -static int +static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { -QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; -QLA_SESSION *my_session = (QLA_SESSION *)session; -char *ptr; -int length = 0; -struct tm t; -struct timeval tv; + QLA_INSTANCE *my_instance = (QLA_INSTANCE *) instance; + QLA_SESSION *my_session = (QLA_SESSION *) session; + char *ptr; + int length = 0; + struct tm t; + struct timeval tv; - if (my_session->active) - { - if (queue->next != NULL) - { - queue = gwbuf_make_contiguous(queue); - } - if ((ptr = modutil_get_SQL(queue)) != NULL) - { - if ((my_instance->match == NULL || - regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && - (my_instance->nomatch == NULL || - regexec(&my_instance->nore,ptr,0,NULL, 0) != 0)) - { - gettimeofday(&tv, NULL); - localtime_r(&tv.tv_sec, &t); - fprintf(my_session->fp, - "%02d:%02d:%02d.%-3d %d/%02d/%d, ", - t.tm_hour, t.tm_min, t.tm_sec, (int)(tv.tv_usec / 1000), - t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year); - fprintf(my_session->fp,"%s\n",ptr); - - } - free(ptr); - } - } - /* Pass the query downstream */ - return my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, queue); + if (my_session->active) + { + if (queue->next != NULL) + { + queue = gwbuf_make_contiguous(queue); + } + if ((ptr = modutil_get_SQL(queue)) != NULL) + { + if ((my_instance->match == NULL || + regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && + (my_instance->nomatch == NULL || + regexec(&my_instance->nore, ptr, 0, NULL, 0) != 0)) + { + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &t); + fprintf(my_session->fp, + "%02d:%02d:%02d.%-3d %d/%02d/%d, ", + t.tm_hour, t.tm_min, t.tm_sec, (int) (tv.tv_usec / 1000), + t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year); + fprintf(my_session->fp, "%s\n", ptr); + + } + free(ptr); + } + } + /* Pass the query downstream */ + return my_session->down.routeQuery(my_session->down.instance, + my_session->down.session, queue); } /** @@ -433,31 +454,39 @@ struct timeval tv; * instance as a whole, otherwise print diagnostics for the * particular session. * - * @param instance The filter instance - * @param fsession Filter session, may be NULL - * @param dcb The DCB for diagnostic output + * @param instance The filter instance + * @param fsession Filter session, may be NULL + * @param dcb The DCB for diagnostic output */ -static void +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb) { -QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; -QLA_SESSION *my_session = (QLA_SESSION *)fsession; + QLA_INSTANCE *my_instance = (QLA_INSTANCE *) instance; + QLA_SESSION *my_session = (QLA_SESSION *) fsession; - if (my_session) - { - dcb_printf(dcb, "\t\tLogging to file %s.\n", - my_session->filename); - } - if (my_instance->source) - dcb_printf(dcb, "\t\tLimit logging to connections from %s\n", - my_instance->source); - if (my_instance->userName) - dcb_printf(dcb, "\t\tLimit logging to user %s\n", - my_instance->userName); - if (my_instance->match) - dcb_printf(dcb, "\t\tInclude queries that match %s\n", - my_instance->match); - if (my_instance->nomatch) - dcb_printf(dcb, "\t\tExclude queries that match %s\n", - my_instance->nomatch); + if (my_session) + { + dcb_printf(dcb, "\t\tLogging to file %s.\n", + my_session->filename); + } + if (my_instance->source) + { + dcb_printf(dcb, "\t\tLimit logging to connections from %s\n", + my_instance->source); + } + if (my_instance->userName) + { + dcb_printf(dcb, "\t\tLimit logging to user %s\n", + my_instance->userName); + } + if (my_instance->match) + { + dcb_printf(dcb, "\t\tInclude queries that match %s\n", + my_instance->match); + } + if (my_instance->nomatch) + { + dcb_printf(dcb, "\t\tExclude queries that match %s\n", + my_instance->nomatch); + } } diff --git a/server/modules/filter/regexfilter.c b/server/modules/filter/regexfilter.c index ab35c0af2..05ffea41a 100644 --- a/server/modules/filter/regexfilter.c +++ b/server/modules/filter/regexfilter.c @@ -15,6 +15,7 @@ * * Copyright MariaDB Corporation Ab 2014 */ + #define PCRE2_CODE_UNIT_WIDTH 8 #include #include @@ -33,43 +34,46 @@ * * A simple regular expression query rewrite filter. * Two parameters should be defined in the filter configuration - * match= - * replace= + * match= + * replace= * Two optional parameters - * source= - * user= + * source= + * user= * - * Date Who Description - * 19/06/2014 Mark Riddoch Addition of source and user parameters + * Date Who Description + * 19/06/2014 Mark Riddoch Addition of source and user parameters * @endverbatim */ -MODULE_INFO info = { - MODULE_API_FILTER, - MODULE_GA, - FILTER_VERSION, - "A query rewrite filter that uses regular expressions to rewite queries" +MODULE_INFO info = +{ + MODULE_API_FILTER, + MODULE_GA, + FILTER_VERSION, + "A query rewrite filter that uses regular expressions to rewite queries" }; static char *version_str = "V1.1.0"; -static FILTER *createInstance(char **options, FILTER_PARAMETER **params); -static void *newSession(FILTER *instance, SESSION *session); -static void closeSession(FILTER *instance, void *session); -static void freeSession(FILTER *instance, void *session); -static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); -static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); -static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); +static FILTER *createInstance(char **options, FILTER_PARAMETER **params); +static void *newSession(FILTER *instance, SESSION *session); +static void closeSession(FILTER *instance, void *session); +static void freeSession(FILTER *instance, void *session); +static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); +static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); -static char *regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *study, const char *replace); +static char *regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *study, + const char *replace); -static FILTER_OBJECT MyObject = { +static FILTER_OBJECT MyObject = +{ createInstance, newSession, closeSession, freeSession, setDownstream, - NULL, // No Upstream requirement + NULL, // No Upstream requirement routeQuery, NULL, diagnostic, @@ -102,7 +106,7 @@ typedef struct int active; /* Is filter active */ } REGEX_SESSION; -void log_match(REGEX_INSTANCE* inst,char* re, char* old, char* new); +void log_match(REGEX_INSTANCE* inst, char* re, char* old, char* new); void log_nomatch(REGEX_INSTANCE* inst, char* re, char* old); /** @@ -113,7 +117,7 @@ void log_nomatch(REGEX_INSTANCE* inst, char* re, char* old); char * version() { - return version_str; + return version_str; } /** @@ -136,7 +140,7 @@ ModuleInit() FILTER_OBJECT * GetModuleObject() { - return &MyObject; + return &MyObject; } /** @@ -168,13 +172,13 @@ void free_instance(REGEX_INSTANCE *instance) /** * Create an instance of the filter for a particular service * within MaxScale. - * - * @param options The options for this filter - * @param params The array of name/value pair parameters for the filter + * + * @param options The options for this filter + * @param params The array of name/value pair parameters for the filter * * @return The instance data for this new instance */ -static FILTER * +static FILTER * createInstance(char **options, FILTER_PARAMETER **params) { REGEX_INSTANCE *my_instance; @@ -183,54 +187,66 @@ createInstance(char **options, FILTER_PARAMETER **params) char *logfile = NULL; const char *errmsg; - if ((my_instance = calloc(1, sizeof(REGEX_INSTANCE))) != NULL) - { - my_instance->match = NULL; - my_instance->replace = NULL; + if ((my_instance = calloc(1, sizeof(REGEX_INSTANCE))) != NULL) + { + my_instance->match = NULL; + my_instance->replace = NULL; - for (i = 0; params && params[i]; i++) - { - if (!strcmp(params[i]->name, "match")) - my_instance->match = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "replace")) - my_instance->replace = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "source")) - my_instance->source = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "user")) - my_instance->user = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "log_trace")) - my_instance->log_trace = config_truth_value(params[i]->value); - else if (!strcmp(params[i]->name, "log_file")) - { - if(logfile) - free(logfile); - logfile = strdup(params[i]->value); - } - else if (!filter_standard_parameter(params[i]->name)) - { - MXS_ERROR("regexfilter: Unexpected parameter '%s'.", - params[i]->name); - } - } + for (i = 0; params && params[i]; i++) + { + if (!strcmp(params[i]->name, "match")) + { + my_instance->match = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "replace")) + { + my_instance->replace = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "source")) + { + my_instance->source = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "user")) + { + my_instance->user = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "log_trace")) + { + my_instance->log_trace = config_truth_value(params[i]->value); + } + else if (!strcmp(params[i]->name, "log_file")) + { + if (logfile) + { + free(logfile); + } + logfile = strdup(params[i]->value); + } + else if (!filter_standard_parameter(params[i]->name)) + { + MXS_ERROR("regexfilter: Unexpected parameter '%s'.", + params[i]->name); + } + } - if (options) - { - for (i = 0; options[i]; i++) - { - if (!strcasecmp(options[i], "ignorecase")) - { - cflags |= PCRE2_CASELESS; - } - else if (!strcasecmp(options[i], "case")) - { - cflags &= ~PCRE2_CASELESS; - } - else - { - MXS_ERROR("regexfilter: unsupported option '%s'.", - options[i]); - } - } + if (options) + { + for (i = 0; options[i]; i++) + { + if (!strcasecmp(options[i], "ignorecase")) + { + cflags |= PCRE2_CASELESS; + } + else if (!strcasecmp(options[i], "case")) + { + cflags &= ~PCRE2_CASELESS; + } + else + { + MXS_ERROR("regexfilter: unsupported option '%s'.", + options[i]); + } + } } if (logfile != NULL) @@ -248,19 +264,19 @@ createInstance(char **options, FILTER_PARAMETER **params) } free(logfile); - if (my_instance->match == NULL || my_instance->replace == NULL) - { - free_instance(my_instance); - return NULL; - } + if (my_instance->match == NULL || my_instance->replace == NULL) + { + free_instance(my_instance); + return NULL; + } - if ((my_instance->re = pcre2_compile((PCRE2_SPTR)my_instance->match, + if ((my_instance->re = pcre2_compile((PCRE2_SPTR) my_instance->match, PCRE2_ZERO_TERMINATED, cflags, &errnumber, &erroffset, NULL)) == NULL) - { + { char errbuffer[1024]; pcre2_get_error_message(errnumber, (PCRE2_UCHAR*) & errbuffer, sizeof(errbuffer)); MXS_ERROR("regexfilter: Compiling regular expression '%s' failed at %lu: %s", @@ -269,62 +285,64 @@ createInstance(char **options, FILTER_PARAMETER **params) return NULL; } - if((my_instance->match_data = pcre2_match_data_create_from_pattern( - my_instance->re, NULL)) == NULL) + if ((my_instance->match_data = + pcre2_match_data_create_from_pattern(my_instance->re, NULL)) == NULL) { MXS_ERROR("regexfilter: Failure to create PCRE2 matching data. " "This is most likely caused by a lack of available memory."); free_instance(my_instance); return NULL; } - } - return (FILTER *)my_instance; + } + return(FILTER *) my_instance; } /** * Associate a new session with this instance of the filter. * - * @param instance The filter instance data - * @param session The session itself + * @param instance The filter instance data + * @param session The session itself * @return Session specific data for this session */ -static void * +static void * newSession(FILTER *instance, SESSION *session) { -REGEX_INSTANCE *my_instance = (REGEX_INSTANCE *)instance; -REGEX_SESSION *my_session; -char *remote, *user; + REGEX_INSTANCE *my_instance = (REGEX_INSTANCE *) instance; + REGEX_SESSION *my_session; + char *remote, *user; - if ((my_session = calloc(1, sizeof(REGEX_SESSION))) != NULL) - { - my_session->no_change = 0; - my_session->replacements = 0; - my_session->active = 1; - if (my_instance->source - && (remote = session_get_remote(session)) != NULL) - { - if (strcmp(remote, my_instance->source)) - my_session->active = 0; - } + if ((my_session = calloc(1, sizeof(REGEX_SESSION))) != NULL) + { + my_session->no_change = 0; + my_session->replacements = 0; + my_session->active = 1; + if (my_instance->source + && (remote = session_get_remote(session)) != NULL) + { + if (strcmp(remote, my_instance->source)) + { + my_session->active = 0; + } + } - if (my_instance->user && (user = session_getUser(session)) - && strcmp(user, my_instance->user)) - { - my_session->active = 0; - } - } + if (my_instance->user && (user = session_getUser(session)) + && strcmp(user, my_instance->user)) + { + my_session->active = 0; + } + } - return my_session; + return my_session; } /** * Close a session with the filter, this is the mechanism * by which a filter may cleanup data structure etc. * - * @param instance The filter instance data - * @param session The session being closed + * @param instance The filter instance data + * @param session The session being closed */ -static void +static void closeSession(FILTER *instance, void *session) { } @@ -332,29 +350,28 @@ closeSession(FILTER *instance, void *session) /** * Free the memory associated with this filter session. * - * @param instance The filter instance data - * @param session The session being closed + * @param instance The filter instance data + * @param session The session being closed */ static void freeSession(FILTER *instance, void *session) { - free(session); - return; + free(session); + return; } /** * Set the downstream component for this filter. * - * @param instance The filter instance data - * @param session The session being closed - * @param downstream The downstream filter or router + * @param instance The filter instance data + * @param session The session being closed + * @param downstream The downstream filter or router */ static void setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) { -REGEX_SESSION *my_session = (REGEX_SESSION *)session; - - my_session->down = *downstream; + REGEX_SESSION *my_session = (REGEX_SESSION *) session; + my_session->down = *downstream; } /** @@ -363,52 +380,52 @@ REGEX_SESSION *my_session = (REGEX_SESSION *)session; * query shoudl normally be passed to the downstream component * (filter or router) in the filter chain. * - * @param instance The filter instance data - * @param session The filter session - * @param queue The query data + * @param instance The filter instance data + * @param session The filter session + * @param queue The query data */ -static int +static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { -REGEX_INSTANCE *my_instance = (REGEX_INSTANCE *)instance; -REGEX_SESSION *my_session = (REGEX_SESSION *)session; -char *sql, *newsql; + REGEX_INSTANCE *my_instance = (REGEX_INSTANCE *) instance; + REGEX_SESSION *my_session = (REGEX_SESSION *) session; + char *sql, *newsql; - if (modutil_is_SQL(queue)) - { - if (queue->next != NULL) - { - queue = gwbuf_make_contiguous(queue); - } - if ((sql = modutil_get_SQL(queue)) != NULL) - { - newsql = regex_replace(sql, - my_instance->re, - my_instance->match_data, - my_instance->replace); - if (newsql) - { - queue = modutil_replace_SQL(queue, newsql); - queue = gwbuf_make_contiguous(queue); - spinlock_acquire(&my_session->lock); - log_match(my_instance,my_instance->match,sql,newsql); - spinlock_release(&my_session->lock); - free(newsql); - my_session->replacements++; - } - else - { - spinlock_acquire(&my_session->lock); - log_nomatch(my_instance,my_instance->match,sql); - spinlock_release(&my_session->lock); - my_session->no_change++; - } - free(sql); - } - - } - return my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, queue); + if (modutil_is_SQL(queue)) + { + if (queue->next != NULL) + { + queue = gwbuf_make_contiguous(queue); + } + if ((sql = modutil_get_SQL(queue)) != NULL) + { + newsql = regex_replace(sql, + my_instance->re, + my_instance->match_data, + my_instance->replace); + if (newsql) + { + queue = modutil_replace_SQL(queue, newsql); + queue = gwbuf_make_contiguous(queue); + spinlock_acquire(&my_session->lock); + log_match(my_instance, my_instance->match, sql, newsql); + spinlock_release(&my_session->lock); + free(newsql); + my_session->replacements++; + } + else + { + spinlock_acquire(&my_session->lock); + log_nomatch(my_instance, my_instance->match, sql); + spinlock_release(&my_session->lock); + my_session->no_change++; + } + free(sql); + } + + } + return my_session->down.routeQuery(my_session->down.instance, + my_session->down.session, queue); } /** @@ -418,43 +435,47 @@ char *sql, *newsql; * instance as a whole, otherwise print diagnostics for the * particular session. * - * @param instance The filter instance - * @param fsession Filter session, may be NULL - * @param dcb The DCB for diagnostic output + * @param instance The filter instance + * @param fsession Filter session, may be NULL + * @param dcb The DCB for diagnostic output */ -static void +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb) { -REGEX_INSTANCE *my_instance = (REGEX_INSTANCE *)instance; -REGEX_SESSION *my_session = (REGEX_SESSION *)fsession; + REGEX_INSTANCE *my_instance = (REGEX_INSTANCE *) instance; + REGEX_SESSION *my_session = (REGEX_SESSION *) fsession; - dcb_printf(dcb, "\t\tSearch and replace: s/%s/%s/\n", - my_instance->match, my_instance->replace); - if (my_session) - { - dcb_printf(dcb, "\t\tNo. of queries unaltered by filter: %d\n", - my_session->no_change); - dcb_printf(dcb, "\t\tNo. of queries altered by filter: %d\n", - my_session->replacements); - } - if (my_instance->source) - dcb_printf(dcb, - "\t\tReplacement limited to connections from %s\n", - my_instance->source); - if (my_instance->user) - dcb_printf(dcb, - "\t\tReplacement limit to user %s\n", - my_instance->user); + dcb_printf(dcb, "\t\tSearch and replace: s/%s/%s/\n", + my_instance->match, my_instance->replace); + if (my_session) + { + dcb_printf(dcb, "\t\tNo. of queries unaltered by filter: %d\n", + my_session->no_change); + dcb_printf(dcb, "\t\tNo. of queries altered by filter: %d\n", + my_session->replacements); + } + if (my_instance->source) + { + dcb_printf(dcb, + "\t\tReplacement limited to connections from %s\n", + my_instance->source); + } + if (my_instance->user) + { + dcb_printf(dcb, + "\t\tReplacement limit to user %s\n", + my_instance->user); + } } /** * Perform a regular expression match and substitution on the SQL * - * @param sql The original SQL text - * @param re The compiled regular expression + * @param sql The original SQL text + * @param re The compiled regular expression * @param match_data The PCRE2 matching data buffer - * @param replace The replacement text - * @return The replaced text or NULL if no replacement was done. + * @param replace The replacement text + * @return The replaced text or NULL if no replacement was done. */ static char * regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *match_data, const char *replace) @@ -463,16 +484,16 @@ regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *match_data, con size_t result_size; /** This should never fail with rc == 0 because we used pcre2_match_data_create_from_pattern() */ - if (pcre2_match(re, (PCRE2_SPTR)sql, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL)) + if (pcre2_match(re, (PCRE2_SPTR) sql, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL)) { result_size = strlen(sql) + strlen(replace); result = malloc(result_size); while (result && - pcre2_substitute(re, (PCRE2_SPTR)sql, PCRE2_ZERO_TERMINATED, 0, + pcre2_substitute(re, (PCRE2_SPTR) sql, PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_GLOBAL, match_data, NULL, - (PCRE2_SPTR)replace, PCRE2_ZERO_TERMINATED, - (PCRE2_UCHAR*)result, (PCRE2_SIZE*)&result_size) == PCRE2_ERROR_NOMEMORY) + (PCRE2_SPTR) replace, PCRE2_ZERO_TERMINATED, + (PCRE2_UCHAR*) result, (PCRE2_SIZE*) & result_size) == PCRE2_ERROR_NOMEMORY) { char *tmp; if ((tmp = realloc(result, (result_size *= 1.5))) == NULL) @@ -496,14 +517,14 @@ regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *match_data, con */ void log_match(REGEX_INSTANCE* inst, char* re, char* old, char* new) { - if(inst->logfile) + if (inst->logfile) { - fprintf(inst->logfile,"Matched %s: [%s] -> [%s]\n",re,old,new); - fflush(inst->logfile); + fprintf(inst->logfile, "Matched %s: [%s] -> [%s]\n", re, old, new); + fflush(inst->logfile); } - if(inst->log_trace) + if (inst->log_trace) { - MXS_INFO("Match %s: [%s] -> [%s]",re,old,new); + MXS_INFO("Match %s: [%s] -> [%s]", re, old, new); } } @@ -515,13 +536,13 @@ void log_match(REGEX_INSTANCE* inst, char* re, char* old, char* new) */ void log_nomatch(REGEX_INSTANCE* inst, char* re, char* old) { - if(inst->logfile) + if (inst->logfile) { - fprintf(inst->logfile,"No match %s: [%s]\n",re,old); - fflush(inst->logfile); + fprintf(inst->logfile, "No match %s: [%s]\n", re, old); + fflush(inst->logfile); } - if(inst->log_trace) + if (inst->log_trace) { - MXS_INFO("No match %s: [%s]",re,old); + MXS_INFO("No match %s: [%s]", re, old); } } diff --git a/server/modules/filter/tee.c b/server/modules/filter/tee.c index 880bc5c24..fc97e7bbb 100644 --- a/server/modules/filter/tee.c +++ b/server/modules/filter/tee.c @@ -45,6 +45,7 @@ * * @endverbatim */ + #include #include #include @@ -63,44 +64,47 @@ #include #include -#define MYSQL_COM_QUIT 0x01 -#define MYSQL_COM_INITDB 0x02 -#define MYSQL_COM_FIELD_LIST 0x04 -#define MYSQL_COM_CHANGE_USER 0x11 -#define MYSQL_COM_STMT_PREPARE 0x16 -#define MYSQL_COM_STMT_EXECUTE 0x17 +#define MYSQL_COM_QUIT 0x01 +#define MYSQL_COM_INITDB 0x02 +#define MYSQL_COM_FIELD_LIST 0x04 +#define MYSQL_COM_CHANGE_USER 0x11 +#define MYSQL_COM_STMT_PREPARE 0x16 +#define MYSQL_COM_STMT_EXECUTE 0x17 #define MYSQL_COM_STMT_SEND_LONG_DATA 0x18 -#define MYSQL_COM_STMT_CLOSE 0x19 -#define MYSQL_COM_STMT_RESET 0x1a -#define MYSQL_COM_CONNECT 0x1b +#define MYSQL_COM_STMT_CLOSE 0x19 +#define MYSQL_COM_STMT_RESET 0x1a +#define MYSQL_COM_CONNECT 0x1b -#define REPLY_TIMEOUT_SECOND 5 -#define REPLY_TIMEOUT_MILLISECOND 1 -#define PARENT 0 -#define CHILD 1 +#define REPLY_TIMEOUT_SECOND 5 +#define REPLY_TIMEOUT_MILLISECOND 1 +#define PARENT 0 +#define CHILD 1 #ifdef SS_DEBUG static int debug_seq = 0; #endif -static unsigned char required_packets[] = { - MYSQL_COM_QUIT, - MYSQL_COM_INITDB, - MYSQL_COM_FIELD_LIST, - MYSQL_COM_CHANGE_USER, - MYSQL_COM_STMT_PREPARE, - MYSQL_COM_STMT_EXECUTE, - MYSQL_COM_STMT_SEND_LONG_DATA, - MYSQL_COM_STMT_CLOSE, - MYSQL_COM_STMT_RESET, - MYSQL_COM_CONNECT, - 0 }; +static unsigned char required_packets[] = +{ + MYSQL_COM_QUIT, + MYSQL_COM_INITDB, + MYSQL_COM_FIELD_LIST, + MYSQL_COM_CHANGE_USER, + MYSQL_COM_STMT_PREPARE, + MYSQL_COM_STMT_EXECUTE, + MYSQL_COM_STMT_SEND_LONG_DATA, + MYSQL_COM_STMT_CLOSE, + MYSQL_COM_STMT_RESET, + MYSQL_COM_CONNECT, + 0 +}; -MODULE_INFO info = { - MODULE_API_FILTER, - MODULE_GA, - FILTER_VERSION, - "A tee piece in the filter plumbing" +MODULE_INFO info = +{ + MODULE_API_FILTER, + MODULE_GA, + FILTER_VERSION, + "A tee piece in the filter plumbing" }; static char *version_str = "V1.0.0"; @@ -108,17 +112,18 @@ static char *version_str = "V1.0.0"; /* * The filter entry points */ -static FILTER *createInstance(char **options, FILTER_PARAMETER **); -static void *newSession(FILTER *instance, SESSION *session); -static void closeSession(FILTER *instance, void *session); -static void freeSession(FILTER *instance, void *session); -static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); -static void setUpstream(FILTER *instance, void *fsession, UPSTREAM *upstream); -static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); -static int clientReply(FILTER *instance, void *fsession, GWBUF *queue); -static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); +static FILTER *createInstance(char **options, FILTER_PARAMETER **); +static void *newSession(FILTER *instance, SESSION *session); +static void closeSession(FILTER *instance, void *session); +static void freeSession(FILTER *instance, void *session); +static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); +static void setUpstream(FILTER *instance, void *fsession, UPSTREAM *upstream); +static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); +static int clientReply(FILTER *instance, void *fsession, GWBUF *queue); +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); -static FILTER_OBJECT MyObject = { +static FILTER_OBJECT MyObject = +{ createInstance, newSession, closeSession, @@ -134,52 +139,53 @@ static FILTER_OBJECT MyObject = { * The instance structure for the TEE filter - this holds the configuration * information for the filter. */ -typedef struct { - SERVICE *service; /* The service to duplicate requests to */ - char *source; /* The source of the client connection */ - char *userName; /* The user name to filter on */ - char *match; /* Optional text to match against */ - regex_t re; /* Compiled regex text */ - char *nomatch; /* Optional text to match against for exclusion */ - regex_t nore; /* Compiled regex nomatch text */ +typedef struct +{ + SERVICE *service; /* The service to duplicate requests to */ + char *source; /* The source of the client connection */ + char *userName; /* The user name to filter on */ + char *match; /* Optional text to match against */ + regex_t re; /* Compiled regex text */ + char *nomatch; /* Optional text to match against for exclusion */ + regex_t nore; /* Compiled regex nomatch text */ } TEE_INSTANCE; /** * The session structure for this TEE filter. - * This stores the downstream filter information, such that the + * This stores the downstream filter information, such that the * filter is able to pass the query on to the next filter (or router) * in the chain. * * It also holds the file descriptor to which queries are written. */ -typedef struct { - DOWNSTREAM down; /* The downstream filter */ - UPSTREAM up; /* The upstream filter */ - +typedef struct +{ + DOWNSTREAM down; /* The downstream filter */ + UPSTREAM up; /* The upstream filter */ FILTER_DEF* dummy_filterdef; - int active; /* filter is active? */ - bool use_ok; - int client_multistatement; - bool multipacket[2]; - unsigned char command; - bool waiting[2]; /* if the client is waiting for a reply */ - int eof[2]; - int replies[2]; /* Number of queries received */ - int reply_packets[2]; /* Number of OK, ERR, LOCAL_INFILE_REQUEST or RESULT_SET packets received */ - DCB *branch_dcb; /* Client DCB for "branch" service */ - SESSION *branch_session;/* The branch service session */ - TEE_INSTANCE *instance; - int n_duped; /* Number of duplicated queries */ - int n_rejected; /* Number of rejected queries */ - int residual; /* Any outstanding SQL text */ - GWBUF* tee_replybuf; /* Buffer for reply */ - GWBUF* tee_partials[2]; - GWBUF* queue; - SPINLOCK tee_lock; - DCB* client_dcb; + int active; /* filter is active? */ + bool use_ok; + int client_multistatement; + bool multipacket[2]; + unsigned char command; + bool waiting[2]; /* if the client is waiting for a reply */ + int eof[2]; + int replies[2]; /* Number of queries received */ + int reply_packets[2]; /* Number of OK, ERR, LOCAL_INFILE_REQUEST or RESULT_SET packets received */ + DCB *branch_dcb; /* Client DCB for "branch" service */ + SESSION *branch_session; /* The branch service session */ + TEE_INSTANCE *instance; + int n_duped; /* Number of duplicated queries */ + int n_rejected; /* Number of rejected queries */ + int residual; /* Any outstanding SQL text */ + GWBUF* tee_replybuf; /* Buffer for reply */ + GWBUF* tee_partials[2]; + GWBUF* queue; + SPINLOCK tee_lock; + DCB* client_dcb; #ifdef SS_DEBUG - long d_id; + long d_id; #endif } TEE_SESSION; @@ -188,7 +194,7 @@ typedef struct orphan_session_tt SESSION* session; /*< The child branch session whose parent was freed before * the child session was in a suitable state. */ struct orphan_session_tt* next; -}orphan_session_t; +} orphan_session_t; #ifdef SS_DEBUG static SPINLOCK debug_lock; @@ -203,9 +209,9 @@ static int detect_loops(TEE_INSTANCE *instance, HASHTABLE* ht, SERVICE* session) int internal_route(DCB* dcb); GWBUF* clone_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF* buffer); int route_single_query(TEE_INSTANCE* my_instance, - TEE_SESSION* my_session, - GWBUF* buffer, - GWBUF* clone); + TEE_SESSION* my_session, + GWBUF* buffer, + GWBUF* clone); int reset_session_state(TEE_SESSION* my_session, GWBUF* buffer); void create_orphan(SESSION* ses); @@ -217,13 +223,11 @@ orphan_free(void* data) #ifdef SS_DEBUG int o_stopping = 0, o_ready = 0, o_freed = 0; #endif - while(ptr) + while (ptr) { - if(ptr->session->state == SESSION_STATE_TO_BE_FREED) + if (ptr->session->state == SESSION_STATE_TO_BE_FREED) { - - - if(ptr == allOrphans) + if (ptr == allOrphans) { tmp = ptr; allOrphans = ptr->next; @@ -231,38 +235,39 @@ orphan_free(void* data) else { tmp = allOrphans; - while(tmp && tmp->next != ptr) + while (tmp && tmp->next != ptr) + { tmp = tmp->next; - if(tmp) + } + if (tmp) { tmp->next = ptr->next; tmp = ptr; } } - } - + /* * The session has been unlinked from all the DCBs and it is ready to be freed. */ - - if(ptr->session->state == SESSION_STATE_STOPPING && + + if (ptr->session->state == SESSION_STATE_STOPPING && ptr->session->refcount == 0 && ptr->session->client == NULL) { ptr->session->state = SESSION_STATE_TO_BE_FREED; } #ifdef SS_DEBUG - else if(ptr->session->state == SESSION_STATE_STOPPING) + else if (ptr->session->state == SESSION_STATE_STOPPING) { o_stopping++; } - else if(ptr->session->state == SESSION_STATE_ROUTER_READY) + else if (ptr->session->state == SESSION_STATE_ROUTER_READY) { o_ready++; } #endif ptr = ptr->next; - if(tmp) + if (tmp) { tmp->next = finished; finished = tmp; @@ -273,13 +278,15 @@ orphan_free(void* data) spinlock_release(&orphanLock); #ifdef SS_DEBUG - if(o_stopping + o_ready > 0) + if (o_stopping + o_ready > 0) + { MXS_DEBUG("tee.c: %d orphans in " "SESSION_STATE_STOPPING, %d orphans in " "SESSION_STATE_ROUTER_READY. ", o_stopping, o_ready); + } #endif - while(finished) + while (finished) { #ifdef SS_DEBUG o_freed++; @@ -309,7 +316,7 @@ orphan_free(void* data) char * version() { - return version_str; + return version_str; } /** @@ -336,102 +343,106 @@ ModuleInit() FILTER_OBJECT * GetModuleObject() { - return &MyObject; + return &MyObject; } /** * Create an instance of the filter for a particular service * within MaxScale. - * + * * @param options The options for this filter * @param params The array of name/value pair parameters for the filter * * @return The instance data for this new instance */ -static FILTER * +static FILTER * createInstance(char **options, FILTER_PARAMETER **params) { -TEE_INSTANCE *my_instance; -int i; + TEE_INSTANCE *my_instance; + int i; - if ((my_instance = calloc(1, sizeof(TEE_INSTANCE))) != NULL) - { - if (options) - { - MXS_ERROR("tee: The tee filter has been passed an option, " - "this filter does not support any options."); - } - my_instance->service = NULL; - my_instance->source = NULL; - my_instance->userName = NULL; - my_instance->match = NULL; - my_instance->nomatch = NULL; - if (params) - { - for (i = 0; params[i]; i++) - { - if (!strcmp(params[i]->name, "service")) - { - if ((my_instance->service = service_find(params[i]->value)) == NULL) - { - MXS_ERROR("tee: service '%s' not found.\n", - params[i]->value); - } - } - else if (!strcmp(params[i]->name, "match")) - { - my_instance->match = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "exclude")) - { - my_instance->nomatch = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "source")) - my_instance->source = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "user")) - my_instance->userName = strdup(params[i]->value); - else if (!filter_standard_parameter(params[i]->name)) - { - MXS_ERROR("tee: Unexpected parameter '%s'.", - params[i]->name); - } - } - } - if (my_instance->service == NULL) - { - free(my_instance->match); - free(my_instance->source); - free(my_instance); - return NULL; - } + if ((my_instance = calloc(1, sizeof(TEE_INSTANCE))) != NULL) + { + if (options) + { + MXS_ERROR("tee: The tee filter has been passed an option, " + "this filter does not support any options."); + } + my_instance->service = NULL; + my_instance->source = NULL; + my_instance->userName = NULL; + my_instance->match = NULL; + my_instance->nomatch = NULL; + if (params) + { + for (i = 0; params[i]; i++) + { + if (!strcmp(params[i]->name, "service")) + { + if ((my_instance->service = service_find(params[i]->value)) == NULL) + { + MXS_ERROR("tee: service '%s' not found.\n", + params[i]->value); + } + } + else if (!strcmp(params[i]->name, "match")) + { + my_instance->match = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "exclude")) + { + my_instance->nomatch = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "source")) + { + my_instance->source = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "user")) + { + my_instance->userName = strdup(params[i]->value); + } + else if (!filter_standard_parameter(params[i]->name)) + { + MXS_ERROR("tee: Unexpected parameter '%s'.", + params[i]->name); + } + } + } + if (my_instance->service == NULL) + { + free(my_instance->match); + free(my_instance->source); + free(my_instance); + return NULL; + } - if (my_instance->match && - regcomp(&my_instance->re, my_instance->match, REG_ICASE)) - { - MXS_ERROR("tee: Invalid regular expression '%s'" - " for the match parameter.", - my_instance->match); - free(my_instance->match); - free(my_instance->source); - free(my_instance); - return NULL; - } - if (my_instance->nomatch && - regcomp(&my_instance->nore, my_instance->nomatch, - REG_ICASE)) - { - MXS_ERROR("tee: Invalid regular expression '%s'" - " for the nomatch paramter.\n", - my_instance->match); - if (my_instance->match) - regfree(&my_instance->re); - free(my_instance->match); - free(my_instance->source); - free(my_instance); - return NULL; - } - } - return (FILTER *)my_instance; + if (my_instance->match && + regcomp(&my_instance->re, my_instance->match, REG_ICASE)) + { + MXS_ERROR("tee: Invalid regular expression '%s'" + " for the match parameter.", + my_instance->match); + free(my_instance->match); + free(my_instance->source); + free(my_instance); + return NULL; + } + if (my_instance->nomatch && + regcomp(&my_instance->nore, my_instance->nomatch, + REG_ICASE)) + { + MXS_ERROR("tee: Invalid regular expression '%s'" + " for the nomatch paramter.\n", + my_instance->match); + if (my_instance->match) + regfree(&my_instance->re); + free(my_instance->match); + free(my_instance->source); + free(my_instance); + return NULL; + } + } + return(FILTER *) my_instance; } /** @@ -443,138 +454,138 @@ int i; * @param session The session itself * @return Session specific data for this session */ -static void * +static void * newSession(FILTER *instance, SESSION *session) { -TEE_INSTANCE *my_instance = (TEE_INSTANCE *)instance; -TEE_SESSION *my_session; -char *remote, *userName; + TEE_INSTANCE *my_instance = (TEE_INSTANCE *) instance; + TEE_SESSION *my_session; + char *remote, *userName; - if (strcmp(my_instance->service->name, session->service->name) == 0) - { - MXS_ERROR("%s: Recursive use of tee filter in service.", - session->service->name); - my_session = NULL; - goto retblock; - } - - HASHTABLE* ht = hashtable_alloc(100,simple_str_hash,strcmp); - bool is_loop = detect_loops(my_instance,ht,session->service); - hashtable_free(ht); - - if(is_loop) - { - MXS_ERROR("%s: Recursive use of tee filter in service.", - session->service->name); - my_session = NULL; - goto retblock; - } - - if ((my_session = calloc(1, sizeof(TEE_SESSION))) != NULL) - { - my_session->active = 1; - my_session->residual = 0; - my_session->tee_replybuf = NULL; - my_session->client_dcb = session->client; - my_session->instance = my_instance; - my_session->client_multistatement = false; - my_session->queue = NULL; - spinlock_init(&my_session->tee_lock); - if (my_instance->source && - (remote = session_get_remote(session)) != NULL) - { - if (strcmp(remote, my_instance->source)) - { - my_session->active = 0; - - MXS_WARNING("Tee filter is not active."); - } - } - userName = session_getUser(session); - - if (my_instance->userName && - userName && - strcmp(userName, my_instance->userName)) - { - my_session->active = 0; - - MXS_WARNING("Tee filter is not active."); - } - - if (my_session->active) - { - DCB* dcb; - SESSION* ses; - FILTER_DEF* dummy; - UPSTREAM* dummy_upstream; - - if ((dcb = dcb_clone(session->client)) == NULL) - { - freeSession(instance, (void *)my_session); - my_session = NULL; - - MXS_ERROR("Creating client DCB for Tee " - "filter failed. Terminating session."); - - goto retblock; - } + if (strcmp(my_instance->service->name, session->service->name) == 0) + { + MXS_ERROR("%s: Recursive use of tee filter in service.", + session->service->name); + my_session = NULL; + goto retblock; + } - if((dummy = filter_alloc("tee_dummy","tee_dummy")) == NULL) - { - dcb_close(dcb); - freeSession(instance, (void *)my_session); - my_session = NULL; - MXS_ERROR("tee: Allocating memory for " - "dummy filter definition failed." - " Terminating session."); - - goto retblock; - } - - - - if ((ses = session_alloc(my_instance->service, dcb)) == NULL) - { - filter_free(dummy); - dcb_close(dcb); - freeSession(instance, (void *)my_session); - my_session = NULL; - MXS_ERROR("Creating client session for Tee " - "filter failed. Terminating session."); - - goto retblock; - } - - ss_dassert(ses->ses_is_child); + HASHTABLE* ht = hashtable_alloc(100, simple_str_hash, strcmp); + bool is_loop = detect_loops(my_instance, ht, session->service); + hashtable_free(ht); - dummy->obj = GetModuleObject(); - dummy->filter = NULL; - my_session->branch_session = ses; - my_session->branch_dcb = dcb; - my_session->dummy_filterdef = dummy; + if (is_loop) + { + MXS_ERROR("%s: Recursive use of tee filter in service.", + session->service->name); + my_session = NULL; + goto retblock; + } - if((dummy_upstream = filterUpstream( - dummy, my_session, &ses->tail)) == NULL) - { - filter_free(dummy); - closeSession(instance,(void*)my_session); - dcb_close(dcb); - free(my_session); - MXS_ERROR("tee: Allocating memory for" - "dummy upstream failed." - " Terminating session."); + if ((my_session = calloc(1, sizeof(TEE_SESSION))) != NULL) + { + my_session->active = 1; + my_session->residual = 0; + my_session->tee_replybuf = NULL; + my_session->client_dcb = session->client; + my_session->instance = my_instance; + my_session->client_multistatement = false; + my_session->queue = NULL; + spinlock_init(&my_session->tee_lock); + if (my_instance->source && + (remote = session_get_remote(session)) != NULL) + { + if (strcmp(remote, my_instance->source)) + { + my_session->active = 0; - return NULL; - } - - ses->tail = *dummy_upstream; - MySQLProtocol* protocol = (MySQLProtocol*)session->client->protocol; - my_session->use_ok = protocol->client_capabilities & (1 << 6); - free(dummy_upstream); - } - } + MXS_WARNING("Tee filter is not active."); + } + } + userName = session_getUser(session); + + if (my_instance->userName && + userName && + strcmp(userName, my_instance->userName)) + { + my_session->active = 0; + + MXS_WARNING("Tee filter is not active."); + } + + if (my_session->active) + { + DCB* dcb; + SESSION* ses; + FILTER_DEF* dummy; + UPSTREAM* dummy_upstream; + + if ((dcb = dcb_clone(session->client)) == NULL) + { + freeSession(instance, (void *) my_session); + my_session = NULL; + + MXS_ERROR("Creating client DCB for Tee " + "filter failed. Terminating session."); + + goto retblock; + } + + if ((dummy = filter_alloc("tee_dummy", "tee_dummy")) == NULL) + { + dcb_close(dcb); + freeSession(instance, (void *) my_session); + my_session = NULL; + MXS_ERROR("tee: Allocating memory for " + "dummy filter definition failed." + " Terminating session."); + + goto retblock; + } + + + + if ((ses = session_alloc(my_instance->service, dcb)) == NULL) + { + filter_free(dummy); + dcb_close(dcb); + freeSession(instance, (void *) my_session); + my_session = NULL; + MXS_ERROR("Creating client session for Tee " + "filter failed. Terminating session."); + + goto retblock; + } + + ss_dassert(ses->ses_is_child); + + dummy->obj = GetModuleObject(); + dummy->filter = NULL; + my_session->branch_session = ses; + my_session->branch_dcb = dcb; + my_session->dummy_filterdef = dummy; + + if ((dummy_upstream = filterUpstream( + dummy, my_session, &ses->tail)) == NULL) + { + filter_free(dummy); + closeSession(instance, (void*) my_session); + dcb_close(dcb); + free(my_session); + MXS_ERROR("tee: Allocating memory for" + "dummy upstream failed." + " Terminating session."); + + return NULL; + } + + ses->tail = *dummy_upstream; + MySQLProtocol* protocol = (MySQLProtocol*) session->client->protocol; + my_session->use_ok = protocol->client_capabilities & (1 << 6); + free(dummy_upstream); + } + } retblock: - return my_session; + return my_session; } /** @@ -586,56 +597,56 @@ retblock: * @param instance The filter instance data * @param session The session being closed */ -static void +static void closeSession(FILTER *instance, void *session) { -TEE_SESSION *my_session = (TEE_SESSION *)session; -ROUTER_OBJECT *router; -void *router_instance, *rsession; -SESSION *bsession; + TEE_SESSION *my_session = (TEE_SESSION *) session; + ROUTER_OBJECT *router; + void *router_instance, *rsession; + SESSION *bsession; #ifdef SS_DEBUG -MXS_INFO("Tee close: %d", atomic_add(&debug_seq,1)); + MXS_INFO("Tee close: %d", atomic_add(&debug_seq, 1)); #endif - if (my_session->active) - { - - if ((bsession = my_session->branch_session) != NULL) - { - CHK_SESSION(bsession); - spinlock_acquire(&bsession->ses_lock); - - if (bsession->state != SESSION_STATE_STOPPING) - { - bsession->state = SESSION_STATE_STOPPING; - } - router = bsession->service->router; - router_instance = bsession->service->router_instance; - rsession = bsession->router_session; - spinlock_release(&bsession->ses_lock); - - /** Close router session and all its connections */ - router->closeSession(router_instance, rsession); - } - /* No need to free the session, this is done as - * a side effect of closing the client DCB of the - * session. - */ + if (my_session->active) + { - if(my_session->waiting[PARENT]) - { - if(my_session->command != 0x01 && - my_session->client_dcb && - my_session->client_dcb->state == DCB_STATE_POLLING) - { - MXS_INFO("Tee session closed mid-query."); - GWBUF* errbuf = modutil_create_mysql_err_msg(1,0,1,"00000","Session closed."); - my_session->client_dcb->func.write(my_session->client_dcb,errbuf); - } - } + if ((bsession = my_session->branch_session) != NULL) + { + CHK_SESSION(bsession); + spinlock_acquire(&bsession->ses_lock); + + if (bsession->state != SESSION_STATE_STOPPING) + { + bsession->state = SESSION_STATE_STOPPING; + } + router = bsession->service->router; + router_instance = bsession->service->router_instance; + rsession = bsession->router_session; + spinlock_release(&bsession->ses_lock); + + /** Close router session and all its connections */ + router->closeSession(router_instance, rsession); + } + /* No need to free the session, this is done as + * a side effect of closing the client DCB of the + * session. + */ + + if (my_session->waiting[PARENT]) + { + if (my_session->command != 0x01 && + my_session->client_dcb && + my_session->client_dcb->state == DCB_STATE_POLLING) + { + MXS_INFO("Tee session closed mid-query."); + GWBUF* errbuf = modutil_create_mysql_err_msg(1, 0, 1, "00000", "Session closed."); + my_session->client_dcb->func.write(my_session->client_dcb, errbuf); + } + } - my_session->active = 0; - } + my_session->active = 0; + } } /** @@ -647,55 +658,58 @@ MXS_INFO("Tee close: %d", atomic_add(&debug_seq,1)); static void freeSession(FILTER *instance, void *session) { -TEE_SESSION *my_session = (TEE_SESSION *)session; -SESSION* ses = my_session->branch_session; -session_state_t state; + TEE_SESSION *my_session = (TEE_SESSION *) session; + SESSION* ses = my_session->branch_session; + session_state_t state; #ifdef SS_DEBUG -MXS_INFO("Tee free: %d", atomic_add(&debug_seq,1)); + MXS_INFO("Tee free: %d", atomic_add(&debug_seq, 1)); #endif - if (ses != NULL) - { - state = ses->state; - - if (state == SESSION_STATE_ROUTER_READY) - { - session_free(ses); - } - else if (state == SESSION_STATE_TO_BE_FREED) - { - /** Free branch router session */ - ses->service->router->freeSession( - ses->service->router_instance, - ses->router_session); - /** Free memory of branch client session */ - ses->state = SESSION_STATE_FREE; - free(ses); - /** This indicates that branch session is not available anymore */ - my_session->branch_session = NULL; - } - else if(state == SESSION_STATE_STOPPING) - { - create_orphan(ses); - } - } - if (my_session->dummy_filterdef) - { - filter_free(my_session->dummy_filterdef); - } - if(my_session->tee_replybuf) - gwbuf_free(my_session->tee_replybuf); - free(session); - - orphan_free(NULL); + if (ses != NULL) + { + state = ses->state; - return; + if (state == SESSION_STATE_ROUTER_READY) + { + session_free(ses); + } + else if (state == SESSION_STATE_TO_BE_FREED) + { + /** Free branch router session */ + ses->service->router->freeSession( + ses->service->router_instance, + ses->router_session); + /** Free memory of branch client session */ + ses->state = SESSION_STATE_FREE; + free(ses); + /** This indicates that branch session is not available anymore */ + my_session->branch_session = NULL; + } + else if (state == SESSION_STATE_STOPPING) + { + create_orphan(ses); + } + } + if (my_session->dummy_filterdef) + { + filter_free(my_session->dummy_filterdef); + } + if (my_session->tee_replybuf) + { + gwbuf_free(my_session->tee_replybuf); + } + free(session); + + orphan_free(NULL); + + return; } + /** * Set the downstream filter or router to which queries will be * passed from this filter. * * @param instance The filter instance data - * @param session The filter session + * @param session The filter session * @param downstream The downstream filter or router. */ static void @@ -710,7 +724,7 @@ setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) * passed from this filter. * * @param instance The filter instance data - * @param session The filter session + * @param session The filter session * @param downstream The downstream filter or router. */ static void @@ -738,62 +752,64 @@ setUpstream(FILTER *instance, void *session, UPSTREAM *upstream) * @param session The filter session * @param queue The query data */ -static int +static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { - TEE_INSTANCE *my_instance = (TEE_INSTANCE *)instance; - TEE_SESSION *my_session = (TEE_SESSION *)session; - char *ptr; - int rval; - GWBUF *buffer = NULL, *clone = NULL; - unsigned char command = gwbuf_length(queue) >= 5 ? - *((unsigned char*)queue->start + 4) : 1; + TEE_INSTANCE *my_instance = (TEE_INSTANCE *) instance; + TEE_SESSION *my_session = (TEE_SESSION *) session; + char *ptr; + int rval; + GWBUF *buffer = NULL, *clone = NULL; + unsigned char command = gwbuf_length(queue) >= 5 ? + *((unsigned char*) queue->start + 4) : 1; #ifdef SS_DEBUG - int prev_debug_seq = atomic_add(&debug_seq,1); + int prev_debug_seq = atomic_add(&debug_seq, 1); MXS_INFO("Tee routeQuery: %d : %s", prev_debug_seq, - ((char*)queue->start + 5)); + ((char*) queue->start + 5)); #endif spinlock_acquire(&my_session->tee_lock); - if(!my_session->active) + if (!my_session->active) { - MXS_INFO("Tee: Received a reply when the session was closed."); - gwbuf_free(queue); - spinlock_release(&my_session->tee_lock); - return 0; + MXS_INFO("Tee: Received a reply when the session was closed."); + gwbuf_free(queue); + spinlock_release(&my_session->tee_lock); + return 0; } - if(my_session->queue) + if (my_session->queue) { - my_session->queue = gwbuf_append(my_session->queue,queue); - buffer = modutil_get_next_MySQL_packet(&my_session->queue); + my_session->queue = gwbuf_append(my_session->queue, queue); + buffer = modutil_get_next_MySQL_packet(&my_session->queue); } else { - buffer = modutil_get_next_MySQL_packet(&queue); - my_session->queue = queue; + buffer = modutil_get_next_MySQL_packet(&queue); + my_session->queue = queue; } - if(buffer == NULL) + if (buffer == NULL) { - spinlock_release(&my_session->tee_lock); - return 1; + spinlock_release(&my_session->tee_lock); + return 1; } - - clone = clone_query(my_instance, my_session,buffer); + + clone = clone_query(my_instance, my_session, buffer); spinlock_release(&my_session->tee_lock); /* Reset session state */ - if(!reset_session_state(my_session,buffer)) - return 0; + if (!reset_session_state(my_session, buffer)) + { + return 0; + } /** Route query downstream */ spinlock_acquire(&my_session->tee_lock); - rval = route_single_query(my_instance,my_session,buffer,clone); + rval = route_single_query(my_instance, my_session, buffer, clone); spinlock_release(&my_session->tee_lock); return rval; @@ -801,29 +817,32 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue) int count_replies(GWBUF* buffer) { - unsigned char* ptr = (unsigned char*)buffer->start; + unsigned char* ptr = (unsigned char*) buffer->start; unsigned char* end = (unsigned char*) buffer->end; int pktlen, eof = 0; int replies = 0; - while(ptr < end) + while (ptr < end) { - pktlen = MYSQL_GET_PACKET_LEN(ptr) + 4; - if(PTR_IS_OK(ptr) || PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr)) - { - replies++; - ptr += pktlen; - } - else - { - while(ptr < end && eof < 2) - { - pktlen = MYSQL_GET_PACKET_LEN(ptr) + 4; - if(PTR_IS_EOF(ptr) || PTR_IS_ERR(ptr)) eof++; - ptr += pktlen; - } - if(eof == 2) replies++; - eof = 0; - } + pktlen = MYSQL_GET_PACKET_LEN(ptr) + 4; + if (PTR_IS_OK(ptr) || PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr)) + { + replies++; + ptr += pktlen; + } + else + { + while (ptr < end && eof < 2) + { + pktlen = MYSQL_GET_PACKET_LEN(ptr) + 4; + if (PTR_IS_EOF(ptr) || PTR_IS_ERR(ptr)) eof++; + ptr += pktlen; + } + if (eof == 2) + { + replies++; + } + eof = 0; + } } return replies; @@ -832,14 +851,22 @@ int count_replies(GWBUF* buffer) int lenenc_length(uint8_t* ptr) { char val = *ptr; - if(val < 251) - return 1; - else if(val == 0xfc) - return 3; - else if(val == 0xfd) - return 4; + if (val < 251) + { + return 1; + } + else if (val == 0xfc) + { + return 3; + } + else if (val == 0xfd) + { + return 4; + } else - return 9; + { + return 9; + } } uint16_t get_response_flags(uint8_t* datastart, bool ok_packet) @@ -850,17 +877,17 @@ uint16_t get_response_flags(uint8_t* datastart, bool ok_packet) ptr += 4; - if(ok_packet) + if (ok_packet) { - ptr += lenenc_length(ptr); - ptr += lenenc_length(ptr); - memcpy(&rval,ptr,sizeof(uint8_t)*2); + ptr += lenenc_length(ptr); + ptr += lenenc_length(ptr); + memcpy(&rval, ptr, sizeof(uint8_t)*2); } else { - /** This is an EOF packet*/ - ptr += 2; - memcpy(&rval,ptr,sizeof(uint8_t)*2); + /** This is an EOF packet*/ + ptr += 2; + memcpy(&rval, ptr, sizeof(uint8_t)*2); } return rval; @@ -877,21 +904,21 @@ uint16_t get_response_flags(uint8_t* datastart, bool ok_packet) * @param reply The response data */ static int -clientReply (FILTER* instance, void *session, GWBUF *reply) +clientReply(FILTER* instance, void *session, GWBUF *reply) { int rc, branch, eof; TEE_SESSION *my_session = (TEE_SESSION *) session; - bool route = false,mpkt; + bool route = false, mpkt; GWBUF *complete = NULL; unsigned char *ptr; uint16_t flags = 0; int min_eof = my_session->command != 0x04 ? 2 : 1; int more_results = 0; #ifdef SS_DEBUG - int prev_debug_seq = atomic_add(&debug_seq,1); + int prev_debug_seq = atomic_add(&debug_seq, 1); ptr = (unsigned char*) reply->start; MXS_INFO("Tee clientReply [%s] [%s] [%s]: %d", - instance ? "parent":"child", + instance ? "parent" : "child", my_session->active ? "open" : "closed", PTR_IS_ERR(ptr) ? "ERR" : PTR_IS_OK(ptr) ? "OK" : "RSET", prev_debug_seq); @@ -899,20 +926,20 @@ clientReply (FILTER* instance, void *session, GWBUF *reply) spinlock_acquire(&my_session->tee_lock); - if(!my_session->active) + if (!my_session->active) { - MXS_INFO("Tee: Failed to return reply, session is closed"); - gwbuf_free(reply); - rc = 0; - if(my_session->waiting[PARENT]) - { - GWBUF* errbuf = modutil_create_mysql_err_msg(1,0,1,"0000","Session closed."); - my_session->waiting[PARENT] = false; - my_session->up.clientReply (my_session->up.instance, - my_session->up.session, - errbuf); - } - goto retblock; + MXS_INFO("Tee: Failed to return reply, session is closed"); + gwbuf_free(reply); + rc = 0; + if (my_session->waiting[PARENT]) + { + GWBUF* errbuf = modutil_create_mysql_err_msg(1, 0, 1, "0000", "Session closed."); + my_session->waiting[PARENT] = false; + my_session->up.clientReply(my_session->up.instance, + my_session->up.session, + errbuf); + } + goto retblock; } branch = instance == NULL ? CHILD : PARENT; @@ -921,166 +948,166 @@ clientReply (FILTER* instance, void *session, GWBUF *reply) my_session->tee_partials[branch] = gwbuf_make_contiguous(my_session->tee_partials[branch]); complete = modutil_get_complete_packets(&my_session->tee_partials[branch]); - if(complete == NULL) + if (complete == NULL) { - /** Incomplete packet */ - MXS_DEBUG("tee.c: Incomplete packet, " + /** Incomplete packet */ + MXS_DEBUG("tee.c: Incomplete packet, " "waiting for a complete packet before forwarding."); - rc = 1; - goto retblock; + rc = 1; + goto retblock; } - + complete = gwbuf_make_contiguous(complete); - if(my_session->tee_partials[branch] && - GWBUF_EMPTY(my_session->tee_partials[branch])) + if (my_session->tee_partials[branch] && + GWBUF_EMPTY(my_session->tee_partials[branch])) { gwbuf_free(my_session->tee_partials[branch]); my_session->tee_partials[branch] = NULL; } ptr = (unsigned char*) complete->start; - - if(my_session->replies[branch] == 0) + + if (my_session->replies[branch] == 0) { - MXS_INFO("Tee: First reply to a query for [%s].",branch == PARENT ? "PARENT":"CHILD"); - /* Reply is in a single packet if it is an OK, ERR or LOCAL_INFILE packet. - * Otherwise the reply is a result set and the amount of packets is unknown. - */ - if(PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr) || - PTR_IS_OK(ptr) || !my_session->multipacket[branch] ) - { - my_session->waiting[branch] = false; - my_session->multipacket[branch] = false; - if(PTR_IS_OK(ptr)) - { - flags = get_response_flags(ptr,true); - more_results = (flags & 0x08) && my_session->client_multistatement; - if(more_results) - { - MXS_INFO("Tee: [%s] waiting for more results.",branch == PARENT ? "PARENT":"CHILD"); - } - } - } + MXS_INFO("Tee: First reply to a query for [%s].", branch == PARENT ? "PARENT" : "CHILD"); + /* Reply is in a single packet if it is an OK, ERR or LOCAL_INFILE packet. + * Otherwise the reply is a result set and the amount of packets is unknown. + */ + if (PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr) || + PTR_IS_OK(ptr) || !my_session->multipacket[branch]) + { + my_session->waiting[branch] = false; + my_session->multipacket[branch] = false; + if (PTR_IS_OK(ptr)) + { + flags = get_response_flags(ptr, true); + more_results = (flags & 0x08) && my_session->client_multistatement; + if (more_results) + { + MXS_INFO("Tee: [%s] waiting for more results.", branch == PARENT ? "PARENT" : "CHILD"); + } + } + } #ifdef SS_DEBUG - else - { - MXS_DEBUG("tee.c: [%ld] Waiting for a result set from %s session.", + else + { + MXS_DEBUG("tee.c: [%ld] Waiting for a result set from %s session.", my_session->d_id, - branch == PARENT?"parent":"child"); - } + branch == PARENT ? "parent" : "child"); + } #endif } - if(my_session->waiting[branch]) + if (my_session->waiting[branch]) { - eof = modutil_count_signal_packets(complete,my_session->use_ok,my_session->eof[branch] > 0,&more_results); - more_results &= my_session->client_multistatement; - my_session->eof[branch] += eof; + eof = modutil_count_signal_packets(complete, my_session->use_ok, my_session->eof[branch] > 0, &more_results); + more_results &= my_session->client_multistatement; + my_session->eof[branch] += eof; - if(my_session->eof[branch] >= min_eof) - { + if (my_session->eof[branch] >= min_eof) + { #ifdef SS_DEBUG - MXS_DEBUG("tee.c [%ld] %s received last EOF packet", + MXS_DEBUG("tee.c [%ld] %s received last EOF packet", my_session->d_id, - branch == PARENT?"parent":"child"); + branch == PARENT ? "parent" : "child"); #endif - my_session->waiting[branch] = more_results; - if(more_results) - { - my_session->eof[branch] = 0; - } - } + my_session->waiting[branch] = more_results; + if (more_results) + { + my_session->eof[branch] = 0; + } + } } - if(branch == PARENT) + if (branch == PARENT) { - my_session->tee_replybuf = gwbuf_append(my_session->tee_replybuf,complete); + my_session->tee_replybuf = gwbuf_append(my_session->tee_replybuf, complete); } else { - gwbuf_free(complete); + gwbuf_free(complete); } my_session->replies[branch]++; rc = 1; mpkt = my_session->multipacket[PARENT] || my_session->multipacket[CHILD]; - if(my_session->tee_replybuf != NULL) - { + if (my_session->tee_replybuf != NULL) + { - if(my_session->branch_session == NULL) - { - rc = 0; - gwbuf_free(my_session->tee_replybuf); - my_session->tee_replybuf = NULL; - MXS_ERROR("Tee child session was closed."); - } + if (my_session->branch_session == NULL) + { + rc = 0; + gwbuf_free(my_session->tee_replybuf); + my_session->tee_replybuf = NULL; + MXS_ERROR("Tee child session was closed."); + } - if(mpkt) - { + if (mpkt) + { - if(my_session->waiting[PARENT]) - { - route = true; + if (my_session->waiting[PARENT]) + { + route = true; - } - else if(my_session->eof[PARENT] >= min_eof && - my_session->eof[CHILD] >= min_eof) - { - route = true; + } + else if (my_session->eof[PARENT] >= min_eof && + my_session->eof[CHILD] >= min_eof) + { + route = true; #ifdef SS_DEBUG - MXS_DEBUG("tee.c:[%ld] Routing final packet of response set.",my_session->d_id); + MXS_DEBUG("tee.c:[%ld] Routing final packet of response set.", my_session->d_id); #endif - } - } - else if(!my_session->waiting[PARENT] && - !my_session->waiting[CHILD]) - { + } + } + else if (!my_session->waiting[PARENT] && + !my_session->waiting[CHILD]) + { #ifdef SS_DEBUG - MXS_DEBUG("tee.c:[%ld] Routing single packet response.",my_session->d_id); + MXS_DEBUG("tee.c:[%ld] Routing single packet response.", my_session->d_id); #endif - route = true; - } + route = true; + } } - if(route) + if (route) { #ifdef SS_DEBUG - MXS_DEBUG("tee.c:[%ld] Routing buffer '%p' parent(waiting [%s] replies [%d] eof[%d])" + MXS_DEBUG("tee.c:[%ld] Routing buffer '%p' parent(waiting [%s] replies [%d] eof[%d])" " child(waiting [%s] replies[%d] eof [%d])", - my_session->d_id, - my_session->tee_replybuf, - my_session->waiting[PARENT] ? "true":"false", - my_session->replies[PARENT], - my_session->eof[PARENT], - my_session->waiting[CHILD]?"true":"false", - my_session->replies[CHILD], - my_session->eof[CHILD]); + my_session->d_id, + my_session->tee_replybuf, + my_session->waiting[PARENT] ? "true" : "false", + my_session->replies[PARENT], + my_session->eof[PARENT], + my_session->waiting[CHILD] ? "true" : "false", + my_session->replies[CHILD], + my_session->eof[CHILD]); #endif - - rc = my_session->up.clientReply (my_session->up.instance, - my_session->up.session, - my_session->tee_replybuf); - my_session->tee_replybuf = NULL; + + rc = my_session->up.clientReply(my_session->up.instance, + my_session->up.session, + my_session->tee_replybuf); + my_session->tee_replybuf = NULL; } - if(my_session->queue && - !my_session->waiting[PARENT] && - !my_session->waiting[CHILD]) + if (my_session->queue && + !my_session->waiting[PARENT] && + !my_session->waiting[CHILD]) { - GWBUF* buffer = modutil_get_next_MySQL_packet(&my_session->queue); - GWBUF* clone = clone_query(my_session->instance,my_session,buffer); - reset_session_state(my_session,buffer); - route_single_query(my_session->instance,my_session,buffer,clone); - MXS_INFO("tee: routing queued query"); + GWBUF* buffer = modutil_get_next_MySQL_packet(&my_session->queue); + GWBUF* clone = clone_query(my_session->instance, my_session, buffer); + reset_session_state(my_session, buffer); + route_single_query(my_session->instance, my_session, buffer, clone); + MXS_INFO("tee: routing queued query"); } - retblock: +retblock: spinlock_release(&my_session->tee_lock); - + return rc; } @@ -1095,33 +1122,41 @@ clientReply (FILTER* instance, void *session, GWBUF *reply) * @param fsession Filter session, may be NULL * @param dcb The DCB for diagnostic output */ -static void +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb) { -TEE_INSTANCE *my_instance = (TEE_INSTANCE *)instance; -TEE_SESSION *my_session = (TEE_SESSION *)fsession; + TEE_INSTANCE *my_instance = (TEE_INSTANCE *) instance; + TEE_SESSION *my_session = (TEE_SESSION *) fsession; - if (my_instance->source) - dcb_printf(dcb, "\t\tLimit to connections from %s\n", - my_instance->source); - dcb_printf(dcb, "\t\tDuplicate statements to service %s\n", - my_instance->service->name); - if (my_instance->userName) - dcb_printf(dcb, "\t\tLimit to user %s\n", - my_instance->userName); - if (my_instance->match) - dcb_printf(dcb, "\t\tInclude queries that match %s\n", - my_instance->match); - if (my_instance->nomatch) - dcb_printf(dcb, "\t\tExclude queries that match %s\n", - my_instance->nomatch); - if (my_session) - { - dcb_printf(dcb, "\t\tNo. of statements duplicated: %d.\n", - my_session->n_duped); - dcb_printf(dcb, "\t\tNo. of statements rejected: %d.\n", - my_session->n_rejected); - } + if (my_instance->source) + { + dcb_printf(dcb, "\t\tLimit to connections from %s\n", + my_instance->source); + } + dcb_printf(dcb, "\t\tDuplicate statements to service %s\n", + my_instance->service->name); + if (my_instance->userName) + { + dcb_printf(dcb, "\t\tLimit to user %s\n", + my_instance->userName); + } + if (my_instance->match) + { + dcb_printf(dcb, "\t\tInclude queries that match %s\n", + my_instance->match); + } + if (my_instance->nomatch) + { + dcb_printf(dcb, "\t\tExclude queries that match %s\n", + my_instance->nomatch); + } + if (my_session) + { + dcb_printf(dcb, "\t\tNo. of statements duplicated: %d.\n", + my_session->n_duped); + dcb_printf(dcb, "\t\tNo. of statements rejected: %d.\n", + my_session->n_rejected); + } } /** @@ -1135,46 +1170,52 @@ TEE_SESSION *my_session = (TEE_SESSION *)fsession; static int packet_is_required(GWBUF *queue) { -uint8_t *ptr; -int i; + uint8_t *ptr; + int i; - ptr = GWBUF_DATA(queue); - if (GWBUF_LENGTH(queue) > 4) - for (i = 0; required_packets[i]; i++) - if (ptr[4] == required_packets[i]) - return 1; - return 0; + ptr = GWBUF_DATA(queue); + if (GWBUF_LENGTH(queue) > 4) + { + for (i = 0; required_packets[i]; i++) + { + if (ptr[4] == required_packets[i]) + { + return 1; + } + } + } + return 0; } /** * Detects possible loops in the query cloning chain. */ -int detect_loops(TEE_INSTANCE *instance,HASHTABLE* ht, SERVICE* service) +int detect_loops(TEE_INSTANCE *instance, HASHTABLE* ht, SERVICE* service) { SERVICE* svc = service; int i; - if(ht == NULL) + if (ht == NULL) { return -1; } - if(hashtable_add(ht,(void*)service->name,(void*)true) == 0) + if (hashtable_add(ht, (void*) service->name, (void*) true) == 0) { return true; } - - for(i = 0;in_filters;i++) + + for (i = 0; i < svc->n_filters; i++) { - if(strcmp(svc->filters[i]->module,"tee") == 0) + if (strcmp(svc->filters[i]->module, "tee") == 0) { /* * Found a Tee filter, recurse down its path * if the service name isn't already in the hashtable. */ - TEE_INSTANCE* ninst = (TEE_INSTANCE*)svc->filters[i]->filter; - if(ninst == NULL) + TEE_INSTANCE* ninst = (TEE_INSTANCE*) svc->filters[i]->filter; + if (ninst == NULL) { /** * This tee instance hasn't been initialized yet and full @@ -1184,14 +1225,14 @@ int detect_loops(TEE_INSTANCE *instance,HASHTABLE* ht, SERVICE* service) } SERVICE* tgt = ninst->service; - if(detect_loops((TEE_INSTANCE*)svc->filters[i]->filter,ht,tgt)) + if (detect_loops((TEE_INSTANCE*) svc->filters[i]->filter, ht, tgt)) { return true; } - + } } - + return false; } @@ -1202,7 +1243,7 @@ int internal_route(DCB* dcb) /** This was set in the newSession function*/ TEE_SESSION* session = dcb->data; - return routeQuery((FILTER*)session->instance,session,buffer); + return routeQuery((FILTER*) session->instance, session, buffer); } /** @@ -1217,42 +1258,42 @@ GWBUF* clone_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF* bu GWBUF* clone = NULL; int residual = 0; char* ptr; - - if (my_session->branch_session && - my_session->branch_session->state == SESSION_STATE_ROUTER_READY) - { - if (my_session->residual) - { - clone = gwbuf_clone_all(buffer); - if (my_session->residual < GWBUF_LENGTH(clone)) - { - GWBUF_RTRIM(clone, GWBUF_LENGTH(clone) - residual); - } - my_session->residual -= GWBUF_LENGTH(clone); + if (my_session->branch_session && + my_session->branch_session->state == SESSION_STATE_ROUTER_READY) + { + if (my_session->residual) + { + clone = gwbuf_clone_all(buffer); - if (my_session->residual < 0) - { - my_session->residual = 0; - } - } - else if (my_session->active && (ptr = modutil_get_SQL(buffer)) != NULL) - { - if ((my_instance->match == NULL || - regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && - (my_instance->nomatch == NULL || - regexec(&my_instance->nore,ptr,0,NULL, 0) != 0)) - { - clone = gwbuf_clone_all(buffer); - my_session->residual = residual; - } - free(ptr); - } - else if (packet_is_required(buffer)) - { - clone = gwbuf_clone_all(buffer); - } - } + if (my_session->residual < GWBUF_LENGTH(clone)) + { + GWBUF_RTRIM(clone, GWBUF_LENGTH(clone) - residual); + } + my_session->residual -= GWBUF_LENGTH(clone); + + if (my_session->residual < 0) + { + my_session->residual = 0; + } + } + else if (my_session->active && (ptr = modutil_get_SQL(buffer)) != NULL) + { + if ((my_instance->match == NULL || + regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && + (my_instance->nomatch == NULL || + regexec(&my_instance->nore, ptr, 0, NULL, 0) != 0)) + { + clone = gwbuf_clone_all(buffer); + my_session->residual = residual; + } + free(ptr); + } + else if (packet_is_required(buffer)) + { + clone = gwbuf_clone_all(buffer); + } + } return clone; } @@ -1269,43 +1310,43 @@ GWBUF* clone_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF* bu int route_single_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF* buffer, GWBUF* clone) { int rval = 0; - if(!my_session->active || - my_session->branch_session == NULL || - my_session->branch_session->state != SESSION_STATE_ROUTER_READY) + if (!my_session->active || + my_session->branch_session == NULL || + my_session->branch_session->state != SESSION_STATE_ROUTER_READY) { - rval = 0; - my_session->active = 0; - return rval; + rval = 0; + my_session->active = 0; + return rval; } rval = my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, - buffer); + my_session->down.session, + buffer); if (clone) { - my_session->n_duped++; + my_session->n_duped++; - if (my_session->branch_session->state == SESSION_STATE_ROUTER_READY) - { - SESSION_ROUTE_QUERY(my_session->branch_session, clone); - } - else - { - /** Close tee session */ - my_session->active = 0; - rval = 0; - MXS_INFO("Closed tee filter session: Child session in invalid state."); - gwbuf_free(clone); - } + if (my_session->branch_session->state == SESSION_STATE_ROUTER_READY) + { + SESSION_ROUTE_QUERY(my_session->branch_session, clone); + } + else + { + /** Close tee session */ + my_session->active = 0; + rval = 0; + MXS_INFO("Closed tee filter session: Child session in invalid state."); + gwbuf_free(clone); + } } else { - if (my_session->active) - { - MXS_INFO("Closed tee filter session: Child session is NULL."); - my_session->active = 0; - rval = 0; - } - my_session->n_rejected++; + if (my_session->active) + { + MXS_INFO("Closed tee filter session: Child session is NULL."); + my_session->active = 0; + rval = 0; + } + my_session->n_rejected++; } return rval; } @@ -1318,47 +1359,51 @@ int route_single_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF */ int reset_session_state(TEE_SESSION* my_session, GWBUF* buffer) { - if(gwbuf_length(buffer) < 5) - return 0; + if (gwbuf_length(buffer) < 5) + { + return 0; + } - unsigned char command = *((unsigned char*)buffer->start + 4); + unsigned char command = *((unsigned char*) buffer->start + 4); - switch(command) - { - case 0x1b: - my_session->client_multistatement = *((unsigned char*) buffer->start + 5); - MXS_INFO("tee: client %s multistatements", - my_session->client_multistatement ? "enabled":"disabled"); + switch (command) + { + case 0x1b: + my_session->client_multistatement = *((unsigned char*) buffer->start + 5); + MXS_INFO("tee: client %s multistatements", + my_session->client_multistatement ? "enabled" : "disabled"); case 0x03: case 0x16: case 0x17: case 0x04: case 0x0a: - memset(my_session->multipacket,(char)true,2*sizeof(bool)); + memset(my_session->multipacket, (char) true, 2 * sizeof(bool)); break; default: - memset(my_session->multipacket,(char)false,2*sizeof(bool)); + memset(my_session->multipacket, (char) false, 2 * sizeof(bool)); break; - } + } - memset(my_session->replies,0,2*sizeof(int)); - memset(my_session->reply_packets,0,2*sizeof(int)); - memset(my_session->eof,0,2*sizeof(int)); - memset(my_session->waiting,1,2*sizeof(bool)); - my_session->command = command; + memset(my_session->replies, 0, 2 * sizeof(int)); + memset(my_session->reply_packets, 0, 2 * sizeof(int)); + memset(my_session->eof, 0, 2 * sizeof(int)); + memset(my_session->waiting, 1, 2 * sizeof(bool)); + my_session->command = command; - return 1; + return 1; } void create_orphan(SESSION* ses) { orphan_session_t* orphan; - if((orphan = malloc(sizeof(orphan_session_t))) == NULL) + if ((orphan = malloc(sizeof(orphan_session_t))) == NULL) { MXS_ERROR("Failed to " "allocate memory for orphan session struct, " "child session might leak memory."); - }else{ + } + else + { orphan->session = ses; spinlock_acquire(&orphanLock); orphan->next = allOrphans; diff --git a/server/modules/filter/topfilter.c b/server/modules/filter/topfilter.c index 457375a83..768050947 100644 --- a/server/modules/filter/topfilter.c +++ b/server/modules/filter/topfilter.c @@ -31,11 +31,12 @@ * file to which the queries are logged. A serial number is appended to this * name in order that each session logs to a different file. * - * Date Who Description - * 18/06/2014 Mark Riddoch Addition of source and user filters + * Date Who Description + * 18/06/2014 Mark Riddoch Addition of source and user filters * * @endverbatim */ + #include #include #include @@ -49,11 +50,12 @@ #include #include -MODULE_INFO info = { - MODULE_API_FILTER, - MODULE_GA, - FILTER_VERSION, - "A top N query logging filter" +MODULE_INFO info = +{ + MODULE_API_FILTER, + MODULE_GA, + FILTER_VERSION, + "A top N query logging filter" }; static char *version_str = "V1.0.1"; @@ -61,18 +63,19 @@ static char *version_str = "V1.0.1"; /* * The filter entry points */ -static FILTER *createInstance(char **options, FILTER_PARAMETER **); -static void *newSession(FILTER *instance, SESSION *session); -static void closeSession(FILTER *instance, void *session); -static void freeSession(FILTER *instance, void *session); -static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); -static void setUpstream(FILTER *instance, void *fsession, UPSTREAM *upstream); -static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); -static int clientReply(FILTER *instance, void *fsession, GWBUF *queue); -static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); +static FILTER *createInstance(char **options, FILTER_PARAMETER **); +static void *newSession(FILTER *instance, SESSION *session); +static void closeSession(FILTER *instance, void *session); +static void freeSession(FILTER *instance, void *session); +static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); +static void setUpstream(FILTER *instance, void *fsession, UPSTREAM *upstream); +static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); +static int clientReply(FILTER *instance, void *fsession, GWBUF *queue); +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); -static FILTER_OBJECT MyObject = { +static FILTER_OBJECT MyObject = +{ createInstance, newSession, closeSession, @@ -92,24 +95,26 @@ static FILTER_OBJECT MyObject = { * To this base a session number is attached such that each session will * have a unique name. */ -typedef struct { - int sessions; /* Session count */ - int topN; /* Number of queries to store */ - char *filebase; /* Base of fielname to log into */ - char *source; /* The source of the client connection */ - char *user; /* A user name to filter on */ - char *match; /* Optional text to match against */ - regex_t re; /* Compiled regex text */ - char *exclude; /* Optional text to match against for exclusion */ - regex_t exre; /* Compiled regex nomatch text */ +typedef struct +{ + int sessions; /* Session count */ + int topN; /* Number of queries to store */ + char *filebase; /* Base of fielname to log into */ + char *source; /* The source of the client connection */ + char *user; /* A user name to filter on */ + char *match; /* Optional text to match against */ + regex_t re; /* Compiled regex text */ + char *exclude; /* Optional text to match against for exclusion */ + regex_t exre; /* Compiled regex nomatch text */ } TOPN_INSTANCE; /** * Structure to hold the Top N queries */ -typedef struct topnq { - struct timeval duration; - char *sql; +typedef struct topnq +{ + struct timeval duration; + char *sql; } TOPNQ; /** @@ -120,21 +125,22 @@ typedef struct topnq { * * It also holds the file descriptor to which queries are written. */ -typedef struct { - DOWNSTREAM down; - UPSTREAM up; - int active; - char *clientHost; - char *userName; - char *filename; - int fd; - struct timeval start; - char *current; - TOPNQ **top; - int n_statements; - struct timeval total; - struct timeval connect; - struct timeval disconnect; +typedef struct +{ + DOWNSTREAM down; + UPSTREAM up; + int active; + char *clientHost; + char *userName; + char *filename; + int fd; + struct timeval start; + char *current; + TOPNQ **top; + int n_statements; + struct timeval total; + struct timeval connect; + struct timeval disconnect; } TOPN_SESSION; /** @@ -145,7 +151,7 @@ typedef struct { char * version() { - return version_str; + return version_str; } /** @@ -168,95 +174,101 @@ ModuleInit() FILTER_OBJECT * GetModuleObject() { - return &MyObject; + return &MyObject; } /** * Create an instance of the filter for a particular service * within MaxScale. - * - * @param options The options for this filter - * @param params The array of name/value pair parameters for the filter + * + * @param options The options for this filter + * @param params The array of name/value pair parameters for the filter * * @return The instance data for this new instance */ -static FILTER * +static FILTER * createInstance(char **options, FILTER_PARAMETER **params) { -int i; -TOPN_INSTANCE *my_instance; + int i; + TOPN_INSTANCE *my_instance; - if ((my_instance = calloc(1, sizeof(TOPN_INSTANCE))) != NULL) - { - my_instance->topN = 10; - my_instance->match = NULL; - my_instance->exclude = NULL; - my_instance->source = NULL; - my_instance->user = NULL; - my_instance->filebase = strdup("top"); - for (i = 0; params && params[i]; i++) - { - if (!strcmp(params[i]->name, "count")) - my_instance->topN = atoi(params[i]->value); - else if (!strcmp(params[i]->name, "filebase")) - { - free(my_instance->filebase); - my_instance->filebase = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "match")) - { - my_instance->match = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "exclude")) - { - my_instance->exclude = strdup(params[i]->value); - } - else if (!strcmp(params[i]->name, "source")) - my_instance->source = strdup(params[i]->value); - else if (!strcmp(params[i]->name, "user")) - my_instance->user = strdup(params[i]->value); - else if (!filter_standard_parameter(params[i]->name)) - { - MXS_ERROR("topfilter: Unexpected parameter '%s'.", - params[i]->name); - } - } - if (options) - { - MXS_ERROR("topfilter: Options are not supported by this " - " filter. They will be ignored."); - } - my_instance->sessions = 0; - if (my_instance->match && - regcomp(&my_instance->re, my_instance->match, REG_ICASE)) - { - MXS_ERROR("topfilter: Invalid regular expression '%s'" - " for the match parameter.", - my_instance->match); - free(my_instance->match); - free(my_instance->source); - free(my_instance->user); - free(my_instance->filebase); - free(my_instance); - return NULL; - } - if (my_instance->exclude && - regcomp(&my_instance->exre, my_instance->exclude, - REG_ICASE)) - { - MXS_ERROR("qlafilter: Invalid regular expression '%s'" - " for the nomatch paramter.\n", - my_instance->match); - regfree(&my_instance->re); - free(my_instance->match); - free(my_instance->source); - free(my_instance->user); - free(my_instance->filebase); - free(my_instance); - return NULL; - } - } - return (FILTER *)my_instance; + if ((my_instance = calloc(1, sizeof(TOPN_INSTANCE))) != NULL) + { + my_instance->topN = 10; + my_instance->match = NULL; + my_instance->exclude = NULL; + my_instance->source = NULL; + my_instance->user = NULL; + my_instance->filebase = strdup("top"); + for (i = 0; params && params[i]; i++) + { + if (!strcmp(params[i]->name, "count")) + { + my_instance->topN = atoi(params[i]->value); + } + else if (!strcmp(params[i]->name, "filebase")) + { + free(my_instance->filebase); + my_instance->filebase = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "match")) + { + my_instance->match = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "exclude")) + { + my_instance->exclude = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "source")) + { + my_instance->source = strdup(params[i]->value); + } + else if (!strcmp(params[i]->name, "user")) + { + my_instance->user = strdup(params[i]->value); + } + else if (!filter_standard_parameter(params[i]->name)) + { + MXS_ERROR("topfilter: Unexpected parameter '%s'.", + params[i]->name); + } + } + if (options) + { + MXS_ERROR("topfilter: Options are not supported by this " + " filter. They will be ignored."); + } + my_instance->sessions = 0; + if (my_instance->match && + regcomp(&my_instance->re, my_instance->match, REG_ICASE)) + { + MXS_ERROR("topfilter: Invalid regular expression '%s'" + " for the match parameter.", + my_instance->match); + free(my_instance->match); + free(my_instance->source); + free(my_instance->user); + free(my_instance->filebase); + free(my_instance); + return NULL; + } + if (my_instance->exclude && + regcomp(&my_instance->exre, my_instance->exclude, + REG_ICASE)) + { + MXS_ERROR("qlafilter: Invalid regular expression '%s'" + " for the nomatch paramter.\n", + my_instance->match); + regfree(&my_instance->re); + free(my_instance->match); + free(my_instance->source); + free(my_instance->user); + free(my_instance->filebase); + free(my_instance); + return NULL; + } + } + return(FILTER *) my_instance; } /** @@ -264,63 +276,75 @@ TOPN_INSTANCE *my_instance; * * Create the file to log to and open it. * - * @param instance The filter instance data - * @param session The session itself + * @param instance The filter instance data + * @param session The session itself * @return Session specific data for this session */ -static void * +static void * newSession(FILTER *instance, SESSION *session) { -TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *)instance; -TOPN_SESSION *my_session; -int i; -char *remote, *user; + TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *) instance; + TOPN_SESSION *my_session; + int i; + char *remote, *user; - if ((my_session = calloc(1, sizeof(TOPN_SESSION))) != NULL) - { - if ((my_session->filename = - (char *)malloc(strlen(my_instance->filebase) + 20)) - == NULL) - { - free(my_session); - return NULL; - } - sprintf(my_session->filename, "%s.%d", my_instance->filebase, - my_instance->sessions); - atomic_add(&my_instance->sessions,1); - my_session->top = (TOPNQ **)calloc(my_instance->topN + 1, - sizeof(TOPNQ *)); - for (i = 0; i < my_instance->topN; i++) - { - my_session->top[i] = (TOPNQ *)calloc(1, sizeof(TOPNQ)); - my_session->top[i]->sql = NULL; - } - my_session->n_statements = 0; - my_session->total.tv_sec = 0; - my_session->total.tv_usec = 0; - my_session->current = NULL; - if ((remote = session_get_remote(session)) != NULL) - my_session->clientHost = strdup(remote); - else - my_session->clientHost = NULL; - if ((user = session_getUser(session)) != NULL) - my_session->userName = strdup(user); - else - my_session->userName = NULL; - my_session->active = 1; - if (my_instance->source && my_session->clientHost && strcmp(my_session->clientHost, - my_instance->source)) - my_session->active = 0; - if (my_instance->user && my_session->userName && strcmp(my_session->userName, - my_instance->user)) - my_session->active = 0; + if ((my_session = calloc(1, sizeof(TOPN_SESSION))) != NULL) + { + if ((my_session->filename = + (char *) malloc(strlen(my_instance->filebase) + 20)) + == NULL) + { + free(my_session); + return NULL; + } + sprintf(my_session->filename, "%s.%d", my_instance->filebase, + my_instance->sessions); + atomic_add(&my_instance->sessions, 1); + my_session->top = (TOPNQ **) calloc(my_instance->topN + 1, + sizeof(TOPNQ *)); + for (i = 0; i < my_instance->topN; i++) + { + my_session->top[i] = (TOPNQ *) calloc(1, sizeof(TOPNQ)); + my_session->top[i]->sql = NULL; + } + my_session->n_statements = 0; + my_session->total.tv_sec = 0; + my_session->total.tv_usec = 0; + my_session->current = NULL; + if ((remote = session_get_remote(session)) != NULL) + { + my_session->clientHost = strdup(remote); + } + else + { + my_session->clientHost = NULL; + } + if ((user = session_getUser(session)) != NULL) + { + my_session->userName = strdup(user); + } + else + { + my_session->userName = NULL; + } + my_session->active = 1; + if (my_instance->source && my_session->clientHost && strcmp(my_session->clientHost, + my_instance->source)) + { + my_session->active = 0; + } + if (my_instance->user && my_session->userName && strcmp(my_session->userName, + my_instance->user)) + { + my_session->active = 0; + } - sprintf(my_session->filename, "%s.%d", my_instance->filebase, - my_instance->sessions); - gettimeofday(&my_session->connect, NULL); - } + sprintf(my_session->filename, "%s.%d", my_instance->filebase, + my_instance->sessions); + gettimeofday(&my_session->connect, NULL); + } - return my_session; + return my_session; } /** @@ -328,110 +352,117 @@ char *remote, *user; * by which a filter may cleanup data structure etc. * In the case of the TOPN filter we simple close the file descriptor. * - * @param instance The filter instance data - * @param session The session being closed + * @param instance The filter instance data + * @param session The session being closed */ -static void +static void closeSession(FILTER *instance, void *session) { -TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *)instance; -TOPN_SESSION *my_session = (TOPN_SESSION *)session; -struct timeval diff; -int i; -FILE *fp; -int statements; + TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *) instance; + TOPN_SESSION *my_session = (TOPN_SESSION *) session; + struct timeval diff; + int i; + FILE *fp; + int statements; - gettimeofday(&my_session->disconnect, NULL); - timersub((&my_session->disconnect), &(my_session->connect), &diff); - if ((fp = fopen(my_session->filename, "w")) != NULL) - { - statements = my_session->n_statements != 0?my_session->n_statements:1; + gettimeofday(&my_session->disconnect, NULL); + timersub((&my_session->disconnect), &(my_session->connect), &diff); + if ((fp = fopen(my_session->filename, "w")) != NULL) + { + statements = my_session->n_statements != 0 ? my_session->n_statements : 1; - fprintf(fp, "Top %d longest running queries in session.\n", - my_instance->topN); - fprintf(fp, "==========================================\n\n"); - fprintf(fp, "Time (sec) | Query\n"); - fprintf(fp, "-----------+-----------------------------------------------------------------\n"); - for (i = 0; i < my_instance->topN; i++) - { - if (my_session->top[i]->sql) - { - fprintf(fp, "%10.3f | %s\n", - (double)((my_session->top[i]->duration.tv_sec * 1000) - + (my_session->top[i]->duration.tv_usec / 1000)) / 1000, - my_session->top[i]->sql); - } - } - fprintf(fp, "-----------+-----------------------------------------------------------------\n"); - fprintf(fp, "\n\nSession started %s", - asctime(localtime(&my_session->connect.tv_sec))); - if (my_session->clientHost) - fprintf(fp, "Connection from %s\n", - my_session->clientHost); - if (my_session->userName) - fprintf(fp, "Username %s\n", - my_session->userName); - fprintf(fp, "\nTotal of %d statements executed.\n", - statements); - fprintf(fp, "Total statement execution time %5d.%d seconds\n", - (int)my_session->total.tv_sec, - (int)my_session->total.tv_usec / 1000); - fprintf(fp, "Average statement execution time %9.3f seconds\n", - (double)((my_session->total.tv_sec * 1000) - + (my_session->total.tv_usec / 1000)) - / (1000 * statements)); - fprintf(fp, "Total connection time %5d.%d seconds\n", - (int)diff.tv_sec, (int)diff.tv_usec / 1000); - fclose(fp); - } + fprintf(fp, "Top %d longest running queries in session.\n", + my_instance->topN); + fprintf(fp, "==========================================\n\n"); + fprintf(fp, "Time (sec) | Query\n"); + fprintf(fp, "-----------+-----------------------------------------------------------------\n"); + for (i = 0; i < my_instance->topN; i++) + { + if (my_session->top[i]->sql) + { + fprintf(fp, "%10.3f | %s\n", + (double) ((my_session->top[i]->duration.tv_sec * 1000) + + (my_session->top[i]->duration.tv_usec / 1000)) / 1000, + my_session->top[i]->sql); + } + } + fprintf(fp, "-----------+-----------------------------------------------------------------\n"); + struct tm tm; + localtime_r(&my_session->connect.tv_sec, &tm); + char buffer[32]; // asctime_r documentation requires 26 + asctime_r(&tm, buffer); + fprintf(fp, "\n\nSession started %s", buffer); + if (my_session->clientHost) + { + fprintf(fp, "Connection from %s\n", + my_session->clientHost); + } + if (my_session->userName) + { + fprintf(fp, "Username %s\n", + my_session->userName); + } + fprintf(fp, "\nTotal of %d statements executed.\n", + statements); + fprintf(fp, "Total statement execution time %5d.%d seconds\n", + (int) my_session->total.tv_sec, + (int) my_session->total.tv_usec / 1000); + fprintf(fp, "Average statement execution time %9.3f seconds\n", + (double) ((my_session->total.tv_sec * 1000) + + (my_session->total.tv_usec / 1000)) + / (1000 * statements)); + fprintf(fp, "Total connection time %5d.%d seconds\n", + (int) diff.tv_sec, (int) diff.tv_usec / 1000); + fclose(fp); + } } /** * Free the memory associated with the session * - * @param instance The filter instance - * @param session The filter session + * @param instance The filter instance + * @param session The filter session */ static void freeSession(FILTER *instance, void *session) { -TOPN_SESSION *my_session = (TOPN_SESSION *)session; + TOPN_SESSION *my_session = (TOPN_SESSION *) session; - free(my_session->filename); - free(session); - return; + free(my_session->filename); + free(session); + return; } /** * Set the downstream filter or router to which queries will be * passed from this filter. * - * @param instance The filter instance data - * @param session The filter session - * @param downstream The downstream filter or router. + * @param instance The filter instance data + * @param session The filter session + * @param downstream The downstream filter or router. */ static void setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) { -TOPN_SESSION *my_session = (TOPN_SESSION *)session; + TOPN_SESSION *my_session = (TOPN_SESSION *) session; - my_session->down = *downstream; + my_session->down = *downstream; } /** * Set the upstream filter or session to which results will be * passed from this filter. * - * @param instance The filter instance data - * @param session The filter session - * @param upstream The upstream filter or session. + * @param instance The filter instance data + * @param session The filter session + * @param upstream The upstream filter or session. */ static void setUpstream(FILTER *instance, void *session, UPSTREAM *upstream) { -TOPN_SESSION *my_session = (TOPN_SESSION *)session; + TOPN_SESSION *my_session = (TOPN_SESSION *) session; - my_session->up = *upstream; + my_session->up = *upstream; } /** @@ -440,104 +471,112 @@ TOPN_SESSION *my_session = (TOPN_SESSION *)session; * query should normally be passed to the downstream component * (filter or router) in the filter chain. * - * @param instance The filter instance data - * @param session The filter session - * @param queue The query data + * @param instance The filter instance data + * @param session The filter session + * @param queue The query data */ -static int +static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { -TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *)instance; -TOPN_SESSION *my_session = (TOPN_SESSION *)session; -char *ptr; + TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *) instance; + TOPN_SESSION *my_session = (TOPN_SESSION *) session; + char *ptr; - if (my_session->active) - { - if (queue->next != NULL) - { - queue = gwbuf_make_contiguous(queue); - } - if ((ptr = modutil_get_SQL(queue)) != NULL) - { - if ((my_instance->match == NULL || - regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && - (my_instance->exclude == NULL || - regexec(&my_instance->exre,ptr,0,NULL, 0) != 0)) - { - my_session->n_statements++; - if (my_session->current) - free(my_session->current); - gettimeofday(&my_session->start, NULL); - my_session->current = ptr; - } - else - { - free(ptr); - } - } - } - /* Pass the query downstream */ - return my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, queue); + if (my_session->active) + { + if (queue->next != NULL) + { + queue = gwbuf_make_contiguous(queue); + } + if ((ptr = modutil_get_SQL(queue)) != NULL) + { + if ((my_instance->match == NULL || + regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && + (my_instance->exclude == NULL || + regexec(&my_instance->exre, ptr, 0, NULL, 0) != 0)) + { + my_session->n_statements++; + if (my_session->current) + { + free(my_session->current); + } + gettimeofday(&my_session->start, NULL); + my_session->current = ptr; + } + else + { + free(ptr); + } + } + } + /* Pass the query downstream */ + return my_session->down.routeQuery(my_session->down.instance, + my_session->down.session, queue); } static int cmp_topn(const void *va, const void *vb) { - TOPNQ **a = (TOPNQ **)va; - TOPNQ **b = (TOPNQ **)vb; + TOPNQ **a = (TOPNQ **) va; + TOPNQ **b = (TOPNQ **) vb; - if ((*b)->duration.tv_sec == (*a)->duration.tv_sec) - return (*b)->duration.tv_usec - (*a)->duration.tv_usec; - return (*b)->duration.tv_sec - (*a)->duration.tv_sec; + if ((*b)->duration.tv_sec == (*a)->duration.tv_sec) + { + return(*b)->duration.tv_usec - (*a)->duration.tv_usec; + } + return(*b)->duration.tv_sec - (*a)->duration.tv_sec; } static int clientReply(FILTER *instance, void *session, GWBUF *reply) { -TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *)instance; -TOPN_SESSION *my_session = (TOPN_SESSION *)session; -struct timeval tv, diff; -int i, inserted; + TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *) instance; + TOPN_SESSION *my_session = (TOPN_SESSION *) session; + struct timeval tv, diff; + int i, inserted; - if (my_session->current) - { - gettimeofday(&tv, NULL); - timersub(&tv, &(my_session->start), &diff); + if (my_session->current) + { + gettimeofday(&tv, NULL); + timersub(&tv, &(my_session->start), &diff); - timeradd(&(my_session->total), &diff, &(my_session->total)); + timeradd(&(my_session->total), &diff, &(my_session->total)); - inserted = 0; - for (i = 0; i < my_instance->topN; i++) - { - if (my_session->top[i]->sql == NULL) - { - my_session->top[i]->sql = my_session->current; - my_session->top[i]->duration = diff; - inserted = 1; - break; - } - } + inserted = 0; + for (i = 0; i < my_instance->topN; i++) + { + if (my_session->top[i]->sql == NULL) + { + my_session->top[i]->sql = my_session->current; + my_session->top[i]->duration = diff; + inserted = 1; + break; + } + } - if (inserted == 0 && ((diff.tv_sec > my_session->top[my_instance->topN-1]->duration.tv_sec) || (diff.tv_sec == my_session->top[my_instance->topN-1]->duration.tv_sec && diff.tv_usec > my_session->top[my_instance->topN-1]->duration.tv_usec ))) - { - free(my_session->top[my_instance->topN-1]->sql); - my_session->top[my_instance->topN-1]->sql = my_session->current; - my_session->top[my_instance->topN-1]->duration = diff; - inserted = 1; - } + if (inserted == 0 && ((diff.tv_sec > my_session->top[my_instance->topN - 1]->duration.tv_sec) || (diff.tv_sec == my_session->top[my_instance->topN - 1]->duration.tv_sec && diff.tv_usec > my_session->top[my_instance->topN - 1]->duration.tv_usec))) + { + free(my_session->top[my_instance->topN - 1]->sql); + my_session->top[my_instance->topN - 1]->sql = my_session->current; + my_session->top[my_instance->topN - 1]->duration = diff; + inserted = 1; + } - if (inserted) - qsort(my_session->top, my_instance->topN, - sizeof(TOPNQ *), cmp_topn); - else - free(my_session->current); - my_session->current = NULL; - } + if (inserted) + { + qsort(my_session->top, my_instance->topN, + sizeof(TOPNQ *), cmp_topn); + } + else + { + free(my_session->current); + } + my_session->current = NULL; + } - /* Pass the result upstream */ - return my_session->up.clientReply(my_session->up.instance, - my_session->up.session, reply); + /* Pass the result upstream */ + return my_session->up.clientReply(my_session->up.instance, + my_session->up.session, reply); } /** @@ -547,47 +586,55 @@ int i, inserted; * instance as a whole, otherwise print diagnostics for the * particular session. * - * @param instance The filter instance - * @param fsession Filter session, may be NULL - * @param dcb The DCB for diagnostic output + * @param instance The filter instance + * @param fsession Filter session, may be NULL + * @param dcb The DCB for diagnostic output */ -static void +static void diagnostic(FILTER *instance, void *fsession, DCB *dcb) { -TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *)instance; -TOPN_SESSION *my_session = (TOPN_SESSION *)fsession; -int i; + TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *) instance; + TOPN_SESSION *my_session = (TOPN_SESSION *) fsession; + int i; - dcb_printf(dcb, "\t\tReport size %d\n", - my_instance->topN); - if (my_instance->source) - dcb_printf(dcb, "\t\tLimit logging to connections from %s\n", - my_instance->source); - if (my_instance->user) - dcb_printf(dcb, "\t\tLimit logging to user %s\n", - my_instance->user); - if (my_instance->match) - dcb_printf(dcb, "\t\tInclude queries that match %s\n", - my_instance->match); - if (my_instance->exclude) - dcb_printf(dcb, "\t\tExclude queries that match %s\n", - my_instance->exclude); - if (my_session) - { - dcb_printf(dcb, "\t\tLogging to file %s.\n", - my_session->filename); - dcb_printf(dcb, "\t\tCurrent Top %d:\n", my_instance->topN); - for (i = 0; i < my_instance->topN; i++) - { - if (my_session->top[i]->sql) - { - dcb_printf(dcb, "\t\t%d place:\n", i + 1); - dcb_printf(dcb, "\t\t\tExecution time: %.3f seconds\n", - (double)((my_session->top[i]->duration.tv_sec * 1000) - + (my_session->top[i]->duration.tv_usec / 1000)) / 1000); - dcb_printf(dcb, "\t\t\tSQL: %s\n", - my_session->top[i]->sql); - } - } - } + dcb_printf(dcb, "\t\tReport size %d\n", + my_instance->topN); + if (my_instance->source) + { + dcb_printf(dcb, "\t\tLimit logging to connections from %s\n", + my_instance->source); + } + if (my_instance->user) + { + dcb_printf(dcb, "\t\tLimit logging to user %s\n", + my_instance->user); + } + if (my_instance->match) + { + dcb_printf(dcb, "\t\tInclude queries that match %s\n", + my_instance->match); + } + if (my_instance->exclude) + { + dcb_printf(dcb, "\t\tExclude queries that match %s\n", + my_instance->exclude); + } + if (my_session) + { + dcb_printf(dcb, "\t\tLogging to file %s.\n", + my_session->filename); + dcb_printf(dcb, "\t\tCurrent Top %d:\n", my_instance->topN); + for (i = 0; i < my_instance->topN; i++) + { + if (my_session->top[i]->sql) + { + dcb_printf(dcb, "\t\t%d place:\n", i + 1); + dcb_printf(dcb, "\t\t\tExecution time: %.3f seconds\n", + (double) ((my_session->top[i]->duration.tv_sec * 1000) + + (my_session->top[i]->duration.tv_usec / 1000)) / 1000); + dcb_printf(dcb, "\t\t\tSQL: %s\n", + my_session->top[i]->sql); + } + } + } } diff --git a/server/modules/protocol/httpd.c b/server/modules/protocol/httpd.c index 5d4aaeb7f..042a20366 100644 --- a/server/modules/protocol/httpd.c +++ b/server/modules/protocol/httpd.c @@ -491,7 +491,9 @@ static void httpd_send_headers(DCB *dcb, int final) const char *fmt = "%a, %d %b %Y %H:%M:%S GMT"; time_t httpd_current_time = time(NULL); - strftime(date, sizeof(date), fmt, localtime(&httpd_current_time)); + struct tm tm; + localtime_r(&httpd_current_time, &tm); + strftime(date, sizeof(date), fmt, &tm); dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: application/json\r\n", date, HTTP_SERVER_STRING); diff --git a/server/modules/routing/binlog/CMakeLists.txt b/server/modules/routing/binlog/CMakeLists.txt index b1b0021e6..997754cf1 100644 --- a/server/modules/routing/binlog/CMakeLists.txt +++ b/server/modules/routing/binlog/CMakeLists.txt @@ -20,7 +20,7 @@ add_executable(maxbinlogcheck maxbinlogcheck.c blr_file.c blr_cache.c blr_master ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc ${CMAKE_SOURCE_DIR}/server/core/externcmd.c) -target_link_libraries(maxbinlogcheck utils ssl pthread ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} aio rt crypt dl crypto inih z m stdc++ ${CURL_LIBRARIES}) +target_link_libraries(maxbinlogcheck utils ssl pthread ${LZMA_LINK_FLAGS} ${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/binlog/blr.c b/server/modules/routing/binlog/blr.c index 475d4e4eb..6be4414ea 100644 --- a/server/modules/routing/binlog/blr.c +++ b/server/modules/routing/binlog/blr.c @@ -157,9 +157,7 @@ version() void ModuleInit() { - LOGIF(LM, (skygw_log_write( - LOGFILE_MESSAGE, - "Initialise binlog router module %s.\n", version_str))); + MXS_NOTICE("Initialise binlog router module %s.\n", version_str); spinlock_init(&instlock); instances = NULL; } @@ -206,17 +204,16 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; if(service->credentials.name == NULL || service->credentials.authdata == NULL) { - skygw_log_write(LE,"%s: Error: Service is missing user credentials." - " Add the missing username or passwd parameter to the service.", - service->name); + MXS_ERROR("%s: Error: Service is missing user credentials." + " Add the missing username or passwd parameter to the service.", + service->name); return NULL; } if(options == NULL || options[0] == NULL) { - skygw_log_write(LE, - "%s: Error: No router options supplied for binlogrouter", - service->name); + MXS_ERROR("%s: Error: No router options supplied for binlogrouter", + service->name); return NULL; } @@ -227,11 +224,10 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; */ if (service->dbref != NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: Warning: backend database server is provided by master.ini file " - "for use with the binlog router." - " Server section is no longer required.", - service->name))); + MXS_WARNING("%s: backend database server is provided by master.ini file " + "for use with the binlog router." + " Server section is no longer required.", + service->name); server_free(service->dbref->server); free(service->dbref); @@ -239,9 +235,8 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; } if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: Error: failed to allocate memory for router instance.", - service->name))); + MXS_ERROR("%s: Error: failed to allocate memory for router instance.", + service->name); return NULL; } @@ -328,10 +323,9 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; { if ((value = strchr(options[i], '=')) == NULL) { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, "Warning : Unsupported router " + MXS_WARNING("Unsupported router " "option %s for binlog router.", - options[i]))); + options[i]); } else { @@ -345,20 +339,16 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; { inst->serverid = atoi(value); if (strcmp(options[i], "server-id") == 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "WARNING: Configuration setting '%s' in router_options is deprecated" - " and will be removed in a later version of MaxScale. " - "Please use the new setting '%s' instead.", - "server-id", "server_id"))); + MXS_WARNING("Configuration setting '%s' in router_options is deprecated" + " and will be removed in a later version of MaxScale. " + "Please use the new setting '%s' instead.", + "server-id", "server_id"); } if (inst->serverid <= 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error : Service %s, invalid server-id '%s'. " - "Please configure it with a unique positive integer value (1..2^32-1)", - service->name, value))); + MXS_ERROR("Service %s, invalid server-id '%s'. " + "Please configure it with a unique positive integer value (1..2^32-1)", + service->name, value); free(inst); return NULL; @@ -384,12 +374,10 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; inst->set_master_server_id = strdup(value); } if (strcmp(options[i], "master-id") == 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "WARNING: Configuration setting '%s' in router_options is deprecated" - " and will be removed in a later version of MaxScale. " - "Please use the new setting '%s' instead.", - "master-id", "master_id"))); + MXS_WARNING("Configuration setting '%s' in router_options is deprecated" + " and will be removed in a later version of MaxScale. " + "Please use the new setting '%s' instead.", + "master-id", "master_id"); } } else if (strcmp(options[i], "master_uuid") == 0) @@ -466,11 +454,9 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; int h_val = (int)strtol(value, NULL, 10); if (h_val <= 0 || (errno == ERANGE)) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Warning : invalid heartbeat period %s." - " Setting it to default value %ld.", - value, inst->heartbeat))); + MXS_WARNING("Invalid heartbeat period %s." + " Setting it to default value %ld.", + value, inst->heartbeat); } else { inst->heartbeat = h_val; } @@ -485,20 +471,17 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; } else { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Warning : Unsupported router " - "option %s for binlog router.", - options[i]))); + MXS_WARNING("Unsupported router " + "option %s for binlog router.", + options[i]); } } } } else { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, "%s: Error: No router options supplied for binlogrouter", - service->name))); + MXS_ERROR("%s: Error: No router options supplied for binlogrouter", + service->name); } if (inst->fileroot == NULL) @@ -520,18 +503,16 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; strcpy(inst->prevbinlog, ""); if ((inst->binlogdir == NULL) || (inst->binlogdir != NULL && !strlen(inst->binlogdir))) { - skygw_log_write_flush(LOGFILE_ERROR, - "Error : Service %s, binlog directory is not specified", - service->name); + MXS_ERROR("Service %s, binlog directory is not specified", + service->name); free(inst); return NULL; } if (inst->serverid <= 0) { - skygw_log_write_flush(LOGFILE_ERROR, - "Error : Service %s, server-id is not configured. " - "Please configure it with a unique positive integer value (1..2^32-1)", - service->name); + MXS_ERROR("Service %s, server-id is not configured. " + "Please configure it with a unique positive integer value (1..2^32-1)", + service->name); free(inst); return NULL; } @@ -545,12 +526,11 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; mkdir_rval = mkdir(inst->binlogdir, 0700); if (mkdir_rval == -1) { char err_msg[STRERROR_BUFLEN]; - skygw_log_write_flush(LOGFILE_ERROR, - "Error : Service %s, Failed to create binlog directory '%s': [%d] %s", - service->name, - inst->binlogdir, - errno, - strerror_r(errno, err_msg, sizeof(err_msg))); + MXS_ERROR("Service %s, Failed to create binlog directory '%s': [%d] %s", + service->name, + inst->binlogdir, + errno, + strerror_r(errno, err_msg, sizeof(err_msg))); free(inst); return NULL; @@ -561,9 +541,8 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; if (service->users == NULL) { service->users = (void *)mysql_users_alloc(); if (service->users == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: Error allocating dbusers in createInstance", - inst->service->name))); + MXS_ERROR("%s: Error allocating dbusers in createInstance", + inst->service->name); free(inst); return NULL; @@ -576,9 +555,8 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; SERVER *server; server = server_alloc("_none_", "MySQLBackend", (int)3306); if (server == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: Error for server_alloc in createInstance", - inst->service->name))); + MXS_ERROR("%s: Error for server_alloc in createInstance", + inst->service->name); if (service->users) { users_free(service->users); service->users = NULL; @@ -605,11 +583,10 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; rc = ini_parse(filename, blr_handler_config, inst); - LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE, - "%s: %s parse result is %d", - inst->service->name, - filename, - rc))); + MXS_INFO("%s: %s parse result is %d", + inst->service->name, + filename, + rc); /* * retcode: @@ -618,17 +595,15 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; if (rc != 0) { if (rc == -1) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: master.ini file not found in %s." - " Master registration cannot be started." - " Configure with CHANGE MASTER TO ...", - inst->service->name, inst->binlogdir))); + MXS_ERROR("%s: master.ini file not found in %s." + " Master registration cannot be started." + " Configure with CHANGE MASTER TO ...", + inst->service->name, inst->binlogdir); } else { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: master.ini file with errors in %s." - " Master registration cannot be started." - " Fix errors in it or configure with CHANGE MASTER TO ...", - inst->service->name, inst->binlogdir))); + MXS_ERROR("%s: master.ini file with errors in %s." + " Master registration cannot be started." + " Fix errors in it or configure with CHANGE MASTER TO ...", + inst->service->name, inst->binlogdir); } /* Set service user or load db users */ @@ -652,11 +627,9 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; /* Find latest binlog file or create a new one (000001) */ if (blr_file_init(inst) == 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "%s: Service not started due to lack of binlog directory %s", - service->name, - inst->binlogdir))); + MXS_ERROR("%s: Service not started due to lack of binlog directory %s", + service->name, + inst->binlogdir); if (service->users) { users_free(service->users); @@ -696,10 +669,8 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; /* Log whether the transaction safety option value is on*/ if (inst->trx_safe) { - LOGIF(LT, (skygw_log_write_flush( - LOGFILE_TRACE, - "%s: Service has transaction safety option set to ON", - service->name))); + MXS_INFO("%s: Service has transaction safety option set to ON", + service->name); } /** @@ -707,9 +678,8 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; */ if (inst->master_state == BLRM_UNCONNECTED) { /* Check current binlog */ - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, "Validating binlog file '%s' ...", - inst->binlog_name))); + MXS_NOTICE("Validating binlog file '%s' ...", + inst->binlog_name); if (inst->trx_safe && !blr_check_binlog(inst)) { /* Don't start replication, just return */ @@ -717,15 +687,11 @@ char task_name[BLRM_TASK_NAME_LEN+1] = ""; } if (!inst->trx_safe) { - LOGIF(LT, (skygw_log_write_flush( - LOGFILE_TRACE, - "Current binlog file is %s, current pos is %lu\n", - inst->binlog_name, inst->binlog_position))); + MXS_INFO("Current binlog file is %s, current pos is %lu\n", + inst->binlog_name, inst->binlog_position); } else { - LOGIF(LT, (skygw_log_write_flush( - LOGFILE_TRACE, - "Current binlog file is %s, safe pos %lu, current pos is %lu\n", - inst->binlog_name, inst->binlog_position, inst->current_pos))); + MXS_INFO("Current binlog file is %s, safe pos %lu, current pos is %lu\n", + inst->binlog_name, inst->binlog_position, inst->current_pos); } /* Start replication from master server */ @@ -752,20 +718,16 @@ newSession(ROUTER *instance, SESSION *session) ROUTER_INSTANCE *inst = (ROUTER_INSTANCE *)instance; ROUTER_SLAVE *slave; - LOGIF(LD, (skygw_log_write_flush( - LOGFILE_DEBUG, - "binlog router: %lu [newSession] new router session with " - "session %p, and inst %p.", - pthread_self(), - session, - inst))); + MXS_DEBUG("binlog router: %lu [newSession] new router session with " + "session %p, and inst %p.", + pthread_self(), + session, + inst); if ((slave = (ROUTER_SLAVE *)calloc(1, sizeof(ROUTER_SLAVE))) == NULL) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Insufficient memory to create new slave session for binlog router"))); + MXS_ERROR("Insufficient memory to create new slave session for binlog router"); return NULL; } @@ -849,14 +811,12 @@ int prev_val; } spinlock_release(&router->lock); - LOGIF(LD, (skygw_log_write_flush( - LOGFILE_DEBUG, - "%lu [freeSession] Unlinked router_client_session %p from " - "router %p. Connections : %d. ", - pthread_self(), - slave, - router, - prev_val-1))); + MXS_DEBUG("%lu [freeSession] Unlinked router_client_session %p from " + "router %p. Connections : %d. ", + pthread_self(), + slave, + router, + prev_val-1); if (slave->hostname) free(slave->hostname); @@ -886,16 +846,12 @@ ROUTER_SLAVE *slave = (ROUTER_SLAVE *)router_session; /* * We must be closing the master session. */ - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: Master %s disconnected after %ld seconds. " - "%lu events read,", - router->service->name, router->service->dbref->server->name, - time(0) - router->connect_time, router->stats.n_binlogs_ses))); - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Binlog router close session with master server %s", - router->service->dbref->server->unique_name))); + MXS_NOTICE("%s: Master %s disconnected after %ld seconds. " + "%lu events read,", + router->service->name, router->service->dbref->server->name, + time(0) - router->connect_time, router->stats.n_binlogs_ses); + MXS_ERROR("Binlog router close session with master server %s", + router->service->dbref->server->unique_name); blr_master_reconnect(router); return; } @@ -910,27 +866,24 @@ ROUTER_SLAVE *slave = (ROUTER_SLAVE *)router_session; atomic_add(&router->stats.n_registered, -1); if (slave->state > 0) { - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: Slave %s, server id %d, disconnected after %ld seconds. " - "%d SQL commands, %d events sent (%lu bytes), binlog '%s', last position %lu", - router->service->name, slave->dcb->remote, - slave->serverid, - time(0) - slave->connect_time, - slave->stats.n_queries, - slave->stats.n_events, - slave->stats.n_bytes, - slave->binlogfile, - (unsigned long)slave->binlog_pos))); + MXS_NOTICE("%s: Slave %s, server id %d, disconnected after %ld seconds. " + "%d SQL commands, %d events sent (%lu bytes), binlog '%s', " + "last position %lu", + router->service->name, slave->dcb->remote, + slave->serverid, + time(0) - slave->connect_time, + slave->stats.n_queries, + slave->stats.n_events, + slave->stats.n_bytes, + slave->binlogfile, + (unsigned long)slave->binlog_pos); } else { - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: Slave %s, server id %d, disconnected after %ld seconds. " - "%d SQL commands", - router->service->name, slave->dcb->remote, - slave->serverid, - time(0) - slave->connect_time, - slave->stats.n_queries))); + MXS_NOTICE("%s: Slave %s, server id %d, disconnected after %ld seconds. " + "%d SQL commands", + router->service->name, slave->dcb->remote, + slave->serverid, + time(0) - slave->connect_time, + slave->stats.n_queries); } /* @@ -1440,33 +1393,29 @@ unsigned long mysql_errno; free(router->m_errmsg); router->m_errmsg = strdup(errmsg); - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, "%s: Master connection error %lu '%s' in state '%s', " - "%sattempting reconnect to master %s:%d", - router->service->name, mysql_errno, errmsg, - blrm_states[router->master_state], msg, - router->service->dbref->server->name, - router->service->dbref->server->port))); + MXS_ERROR("%s: Master connection error %lu '%s' in state '%s', " + "%sattempting reconnect to master %s:%d", + router->service->name, mysql_errno, errmsg, + blrm_states[router->master_state], msg, + router->service->dbref->server->name, + router->service->dbref->server->port); } else { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, "%s: Master connection error %lu '%s' in state '%s', " - "%sattempting reconnect to master %s:%d", - router->service->name, router->m_errno, router->m_errmsg, - blrm_states[router->master_state], msg, - router->service->dbref->server->name, - router->service->dbref->server->port))); + MXS_ERROR("%s: Master connection error %lu '%s' in state '%s', " + "%sattempting reconnect to master %s:%d", + router->service->name, router->m_errno, router->m_errmsg, + blrm_states[router->master_state], msg, + router->service->dbref->server->name, + router->service->dbref->server->port); } if (errmsg) free(errmsg); *succp = true; dcb_close(backend_dcb); - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: Master %s disconnected after %ld seconds. " - "%lu events read.", - router->service->name, router->service->dbref->server->name, - time(0) - router->connect_time, router->stats.n_binlogs_ses))); + MXS_NOTICE("%s: Master %s disconnected after %ld seconds. " + "%lu events read.", + router->service->name, router->service->dbref->server->name, + time(0) - router->connect_time, router->stats.n_binlogs_ses); blr_master_reconnect(router); } @@ -1734,10 +1683,10 @@ SERVICE *service; { return blr_handle_config_item(name, value, inst); } else { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Error : master.ini has an invalid section [%s], it should be [binlog_configuration]. Service %s", - section, - service->name))); + MXS_ERROR("master.ini has an invalid section [%s], it should be [binlog_configuration]. " + "Service %s", + section, + service->name); return 0; } @@ -1796,9 +1745,8 @@ char *service_user = NULL; char *service_passwd = NULL; if (serviceGetUser(service, &service_user, &service_passwd) == 0) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "failed to get service user details for service %s", - service->name))); + MXS_ERROR("failed to get service user details for service %s", + service->name); return 1; } @@ -1806,10 +1754,9 @@ char *service_passwd = NULL; dpwd = decryptPassword(service->credentials.authdata); if (!dpwd) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "decrypt password failed for service user %s, service %s", - service_user, - service->name))); + MXS_ERROR("decrypt password failed for service user %s, service %s", + service_user, + service->name); return 1; } @@ -1817,9 +1764,8 @@ char *service_passwd = NULL; newpasswd = create_hex_sha1_sha1_passwd(dpwd); if (!newpasswd) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "create hex_sha1_sha1_password failed for service user %s", - service_user))); + MXS_ERROR("create hex_sha1_sha1_password failed for service user %s", + service_user); free(dpwd); return 1; @@ -1859,10 +1805,8 @@ SERVICE *service; if (loaded < 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error : Unable to load users for service %s", - service->name))); + MXS_ERROR("Unable to load users for service %s", + service->name); /* Try loading authentication data from file cache */ @@ -1870,29 +1814,23 @@ SERVICE *service; if (loaded != -1) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Service %s, Using cached credential information file %s.", - service->name, - path))); + MXS_ERROR("Service %s, Using cached credential information file %s.", + service->name, + path); } else { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error: Service %s, Unable to read cache credential information from %s." - " No database user added to service users table.", - service->name, - path))); + MXS_ERROR("Service %s, Unable to read cache credential information from %s." + " No database user added to service users table.", + service->name, + path); } } else { /* don't update cache if no user was loaded */ if (loaded == 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Service %s: failed to load any user " - "information. Authentication will " - "probably fail as a result.", - service->name))); + MXS_ERROR("Service %s: failed to load any user " + "information. Authentication will " + "probably fail as a result.", + service->name); } else { /* update cached data */ blr_save_dbusers(router); @@ -1936,12 +1874,11 @@ int mkdir_rval = 0; if (mkdir_rval == -1) { char err_msg[STRERROR_BUFLEN]; - skygw_log_write(LOGFILE_ERROR, - "Error : Service %s, Failed to create directory '%s': [%d] %s", - service->name, - path, - errno, - strerror_r(errno, err_msg, sizeof(err_msg))); + MXS_ERROR("Service %s, Failed to create directory '%s': [%d] %s", + service->name, + path, + errno, + strerror_r(errno, err_msg, sizeof(err_msg))); return -1; } @@ -1999,9 +1936,7 @@ static int blr_check_binlog(ROUTER_INSTANCE *router) { n = blr_read_events_all_events(router, 0, 0); - LOGIF(LD, (skygw_log_write_flush( - LOGFILE_DEBUG, - "blr_read_events_all_events() ret = %i\n", n))); + MXS_DEBUG("blr_read_events_all_events() ret = %i\n", n); if (n != 0) { char msg_err[BINLOG_ERROR_MSG_LEN + 1] = ""; @@ -2017,11 +1952,9 @@ static int blr_check_binlog(ROUTER_INSTANCE *router) { /* set last_safe_pos */ router->last_safe_pos = router->binlog_position; - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error found in binlog file %s. Safe starting pos is %lu", - router->binlog_name, - router->binlog_position))); + MXS_ERROR("Error found in binlog file %s. Safe starting pos is %lu", + router->binlog_name, + router->binlog_position); return 0; } else { diff --git a/server/modules/routing/binlog/blr_file.c b/server/modules/routing/binlog/blr_file.c index dc1683b9c..9a6e49f7a 100644 --- a/server/modules/routing/binlog/blr_file.c +++ b/server/modules/routing/binlog/blr_file.c @@ -65,7 +65,7 @@ static int blr_file_create(ROUTER_INSTANCE *router, char *file); static void blr_file_append(ROUTER_INSTANCE *router, char *file); -static void blr_log_header(logfile_id_t file, char *msg, uint8_t *ptr); +static void blr_log_header(int priority, char *msg, uint8_t *ptr); void blr_cache_read_master_data(ROUTER_INSTANCE *router); int blr_file_get_next_binlogname(ROUTER_INSTANCE *router); int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file); @@ -120,9 +120,8 @@ struct dirent *dp; } if (access(router->binlogdir, R_OK) == -1) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Unable to read the binlog directory %s.", - router->service->name, router->binlogdir))); + MXS_ERROR("%s: Unable to read the binlog directory %s.", + router->service->name, router->binlogdir); return 0; } @@ -131,10 +130,9 @@ struct dirent *dp; if ((dirp = opendir(path)) == NULL) { char err_msg[BLRM_STRERROR_R_MSG_SIZE]; - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Unable to read the binlog directory %s, %s.", - router->service->name, router->binlogdir, - strerror_r(errno, err_msg, sizeof(err_msg))))); + MXS_ERROR("%s: Unable to read the binlog directory %s, %s.", + router->service->name, router->binlogdir, + strerror_r(errno, err_msg, sizeof(err_msg))); return 0; } while ((dp = readdir(dirp)) != NULL) @@ -232,9 +230,8 @@ int fd; { char err_msg[STRERROR_BUFLEN]; - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Failed to create binlog file %s, %s.", - router->service->name, path, strerror_r(errno, err_msg, sizeof(err_msg))))); + MXS_ERROR("%s: Failed to create binlog file %s, %s.", + router->service->name, path, strerror_r(errno, err_msg, sizeof(err_msg))); return 0; } fsync(fd); @@ -264,9 +261,8 @@ int fd; if ((fd = open(path, O_RDWR|O_APPEND, 0666)) == -1) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Failed to open binlog file %s for append.", - path))); + MXS_ERROR("Failed to open binlog file %s for append.", + path); return; } fsync(fd); @@ -280,9 +276,8 @@ int fd; } else { /* If for any reason the file's length is between 1 and 3 bytes * then report an error. */ - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: binlog file %s has an invalid length %lu.", - router->service->name, path, router->current_pos))); + MXS_ERROR("%s: binlog file %s has an invalid length %lu.", + router->service->name, path, router->current_pos); close(fd); spinlock_release(&router->binlog_lock); return; @@ -309,12 +304,11 @@ int n; hdr->next_pos - hdr->event_size)) != hdr->event_size) { char err_msg[STRERROR_BUFLEN]; - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Failed to write binlog record at %d of %s, %s. " - "Truncating to previous record.", - router->service->name, hdr->next_pos - hdr->event_size, - router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))))); + MXS_ERROR("%s: Failed to write binlog record at %d of %s, %s. " + "Truncating to previous record.", + router->service->name, hdr->next_pos - hdr->event_size, + router->binlog_name, + strerror_r(errno, err_msg, sizeof(err_msg))); /* Remove any partual event that was written */ ftruncate(router->binlog_fd, hdr->next_pos - hdr->event_size); return 0; @@ -378,8 +372,7 @@ BLFILE *file; if ((file->fd = open(path, O_RDONLY, 0666)) == -1) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Failed to open binlog file %s", path))); + MXS_ERROR("Failed to open binlog file %s", path); free(file); spinlock_release(&router->fileslock); return NULL; @@ -458,9 +451,8 @@ struct stat statb; switch (n) { case 0: - LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG, - "Reached end of binlog file '%s' at %lu.", - file->binlogname, pos))); + MXS_DEBUG("Reached end of binlog file '%s' at %lu.", + file->binlogname, pos); /* set ok indicator */ hdr->ok = SLAVE_POS_READ_OK; @@ -514,21 +506,19 @@ struct stat statb; if (hdr->next_pos < pos && hdr->event_type != ROTATE_EVENT) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Next position in header appears to be incorrect " - "rereading event header at pos %lu in file %s, " - "file size is %lu. Master will write %lu in %s next.", - pos, file->binlogname, filelen, router->binlog_position, - router->binlog_name))); + MXS_ERROR("Next position in header appears to be incorrect " + "rereading event header at pos %lu in file %s, " + "file size is %lu. Master will write %lu in %s next.", + pos, file->binlogname, filelen, router->binlog_position, + router->binlog_name); if ((n = pread(file->fd, hdbuf, BINLOG_EVENT_HDR_LEN, pos)) != BINLOG_EVENT_HDR_LEN) { switch (n) { case 0: - LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG, - "Reached end of binlog file at %lu.", - pos))); + MXS_DEBUG("Reached end of binlog file at %lu.", + pos); /* set ok indicator */ hdr->ok = SLAVE_POS_READ_OK; @@ -570,9 +560,8 @@ struct stat statb; } else { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Next position corrected by " - "rereading"))); + MXS_ERROR("Next position corrected by " + "rereading"); } } if ((result = gwbuf_alloc(hdr->event_size)) == NULL) @@ -608,7 +597,7 @@ struct stat statb; "current file size is %lu, event at %lu in binlog file '%s'", filelen, pos, file->binlogname); } - blr_log_header(LOGFILE_ERROR, "Possible malformed event header", hdbuf); + blr_log_header(LOG_ERR, "Possible malformed event header", hdbuf); } gwbuf_free(result); @@ -667,12 +656,12 @@ blr_close_binlog(ROUTER_INSTANCE *router, BLFILE *file) /** * Log the event header of binlog event * - * @param file The log file into which to write the entry - * @param msg A message strign to preceed the header with - * @param ptr The event header raw data + * @param priority The syslog priority of the message (LOG_ERR, LOG_WARNING, etc.) + * @param msg A message strign to preceed the header with + * @param ptr The event header raw data */ static void -blr_log_header(logfile_id_t file, char *msg, uint8_t *ptr) +blr_log_header(int priority, char *msg, uint8_t *ptr) { char buf[400], *bufp; int i; @@ -681,8 +670,7 @@ int i; bufp += sprintf(bufp, "%s: ", msg); for (i = 0; i < BINLOG_EVENT_HDR_LEN; i++) bufp += sprintf(bufp, "0x%02x ", ptr[i]); - skygw_log_write_flush(file, "%s", buf); - + MXS_LOG_MESSAGE(priority, "%s", buf); } /** @@ -852,9 +840,8 @@ int fde_seen = 0; memset(&fde_event, '\0', sizeof(fde_event)); if (router->binlog_fd == -1) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Current binlog file %s is not open", - router->binlog_name))); + MXS_ERROR("Current binlog file %s is not open", + router->binlog_name); return 1; } @@ -872,10 +859,9 @@ int fde_seen = 0; switch (n) { case 0: - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - "End of binlog file [%s] at %llu.", - router->binlog_name, - pos))); + MXS_DEBUG("End of binlog file [%s] at %llu.", + router->binlog_name, + pos); if (n_transactions) average_events = (double)((double)total_events / (double)n_transactions) * (1.0); if (n_transactions) @@ -901,24 +887,25 @@ int fde_seen = 0; blr_format_event_size(&average_bytes, average_label); blr_format_event_size(&format_max_bytes, max_label); - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Transaction Summary for binlog '%s'\n" - "\t\t\tDescription %17s%17s%17s\n\t\t\t" - "No. of Transactions %16lu\n\t\t\t" - "No. of Events %16lu %16.1f %16lu\n\t\t\t" - "No. of Bytes %16.1f%s%16.1f%s%16.1f%s", router->binlog_name, - "Total", "Average", "Max", - n_transactions, total_events, - average_events, max_events, - format_total_bytes, total_label, average_bytes, average_label, format_max_bytes, max_label))); + MXS_NOTICE("Transaction Summary for binlog '%s'\n" + "\t\t\tDescription %17s%17s%17s\n\t\t\t" + "No. of Transactions %16lu\n\t\t\t" + "No. of Events %16lu %16.1f %16lu\n\t\t\t" + "No. of Bytes %16.1f%s%16.1f%s%16.1f%s", + router->binlog_name, + "Total", "Average", "Max", + n_transactions, total_events, + average_events, max_events, + format_total_bytes, total_label, + average_bytes, average_label, + format_max_bytes, max_label); } if (pending_transaction) { - LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE, - "Warning : Binlog file %s contains a previous Opened Transaction" - " @ %llu. This pos is safe for slaves", - router->binlog_name, - last_known_commit))); + MXS_WARNING("Binlog file %s contains a previous Opened " + "Transaction @ %llu. This pos is safe for slaves", + router->binlog_name, + last_known_commit); } @@ -927,24 +914,21 @@ int fde_seen = 0; { char err_msg[BLRM_STRERROR_R_MSG_SIZE+1] = ""; strerror_r(errno, err_msg, BLRM_STRERROR_R_MSG_SIZE); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Failed to read binlog file %s at position %llu" - " (%s).", router->binlog_name, - pos, err_msg))); + MXS_ERROR("Failed to read binlog file %s at position %llu" + " (%s).", router->binlog_name, + pos, err_msg); if (errno == EBADF) - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Bad file descriptor in read binlog for file %s" - ", descriptor %d.", - router->binlog_name, router->binlog_fd))); + MXS_ERROR("Bad file descriptor in read binlog for file %s" + ", descriptor %d.", + router->binlog_name, router->binlog_fd); break; } default: - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Short read when reading the header. " - "Expected 19 bytes but got %d bytes. " - "Binlog file is %s, position %llu", - n, router->binlog_name, pos))); + MXS_ERROR("Short read when reading the header. " + "Expected 19 bytes but got %d bytes. " + "Binlog file is %s, position %llu", + n, router->binlog_name, pos); break; } @@ -960,10 +944,9 @@ int fde_seen = 0; router->pending_transaction = 1; pending_transaction = 0; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Warning : pending transaction has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("pending transaction has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); return 0; } else { @@ -973,16 +956,14 @@ int fde_seen = 0; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1010,21 +991,19 @@ int fde_seen = 0; if (router->mariadb10_compat) { if (hdr.event_type > MAX_EVENT_TYPE_MARIADB10) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Invalid MariaDB 10 event type 0x%x. " - "Binlog file is %s, position %llu", - hdr.event_type, - router->binlog_name, pos))); + MXS_ERROR("Invalid MariaDB 10 event type 0x%x. " + "Binlog file is %s, position %llu", + hdr.event_type, + router->binlog_name, pos); event_error = 1; } } else { if (hdr.event_type > MAX_EVENT_TYPE) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Invalid event type 0x%x. " - "Binlog file is %s, position %llu", - hdr.event_type, - router->binlog_name, pos))); + MXS_ERROR("Invalid event type 0x%x. " + "Binlog file is %s, position %llu", + hdr.event_type, + router->binlog_name, pos); event_error = 1; } @@ -1036,19 +1015,17 @@ int fde_seen = 0; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found in %s. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_name, - router->binlog_position, - router->current_pos))); + MXS_WARNING("an error has been found in %s. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_name, + router->binlog_position, + router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1058,25 +1035,22 @@ int fde_seen = 0; if (hdr.event_size <= 0) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Event size error: " - "size %d at %llu.", - hdr.event_size, pos))); + MXS_ERROR("Event size error: " + "size %d at %llu.", + hdr.event_size, pos); router->binlog_position = last_known_commit; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1087,26 +1061,23 @@ int fde_seen = 0; /* Allocate a GWBUF for the event */ if ((result = gwbuf_alloc(hdr.event_size)) == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Failed to allocate memory for binlog entry, " - "size %d at %llu.", - hdr.event_size, pos))); + MXS_ERROR("Failed to allocate memory for binlog entry, " + "size %d at %llu.", + hdr.event_size, pos); router->binlog_position = last_known_commit; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1125,25 +1096,23 @@ int fde_seen = 0; { char err_msg[BLRM_STRERROR_R_MSG_SIZE+1] = ""; strerror_r(errno, err_msg, BLRM_STRERROR_R_MSG_SIZE); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Error reading the event at %llu in %s. " - "%s, expected %d bytes.", - pos, router->binlog_name, - err_msg, hdr.event_size - BINLOG_EVENT_HDR_LEN))); + MXS_ERROR("Error reading the event at %llu in %s. " + "%s, expected %d bytes.", + pos, router->binlog_name, + err_msg, hdr.event_size - BINLOG_EVENT_HDR_LEN); } else { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Short read when reading the event at %llu in %s. " - "Expected %d bytes got %d bytes.", - pos, router->binlog_name, hdr.event_size - BINLOG_EVENT_HDR_LEN, n))); + MXS_ERROR("Short read when reading the event at %llu in %s. " + "Expected %d bytes got %d bytes.", + pos, router->binlog_name, + hdr.event_size - BINLOG_EVENT_HDR_LEN, n); if (filelen > 0 && filelen - pos < hdr.event_size) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Binlog event is close to the end of the binlog file %s, " - " size is %lu.", - router->binlog_name, filelen))); + MXS_ERROR("Binlog event is close to the end of the binlog file %s, " + " size is %lu.", + router->binlog_name, filelen); } } @@ -1153,16 +1122,14 @@ int fde_seen = 0; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1209,9 +1176,8 @@ int fde_seen = 0; } if(debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - "- Format Description event FDE @ %llu, size %lu, time %lu (%s)", - pos, (unsigned long)hdr.event_size, fde_event.event_time, buf_t))); + MXS_DEBUG("- Format Description event FDE @ %llu, size %lu, time %lu (%s)", + pos, (unsigned long)hdr.event_size, fde_event.event_time, buf_t); event_header_length = ptr[2 + 50 + 4]; event_header_ntypes = hdr.event_size - event_header_length - (2 + 50 + 4 + 1); @@ -1232,14 +1198,12 @@ int fde_seen = 0; n_events = hdr.event_size - event_header_length - (2 + 50 + 4 + 1); if(debug) { - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - " FDE ServerVersion [%50s]", ptr + 2))); + MXS_DEBUG(" FDE ServerVersion [%50s]", ptr + 2); - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - " FDE Header EventLength %i" - ", N. of supported MySQL/MariaDB events %i", - event_header_length, - (n_events - event_header_ntypes)))); + MXS_DEBUG(" FDE Header EventLength %i" + ", N. of supported MySQL/MariaDB events %i", + event_header_length, + (n_events - event_header_ntypes)); } if (event_header_ntypes < n_events) { @@ -1247,10 +1211,10 @@ int fde_seen = 0; check_alg = checksum[0]; if(debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - " FDE Checksum alg desc %i, alg type %s", - check_alg, - check_alg == 1 ? "BINLOG_CHECKSUM_ALG_CRC32" : "NONE or UNDEF"))); + MXS_DEBUG(" FDE Checksum alg desc %i, alg type %s", + check_alg, + check_alg == 1 ? + "BINLOG_CHECKSUM_ALG_CRC32" : "NONE or UNDEF"); if (check_alg == 1) { found_chksum = 1; } else { @@ -1283,9 +1247,8 @@ int fde_seen = 0; file[slen] = 0; if(debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - "- Rotate event @ %llu, next file is [%s] @ %lu", - pos, file, new_pos))); + MXS_DEBUG("- Rotate event @ %llu, next file is [%s] @ %lu", + pos, file, new_pos); } /* If MariaDB 10 compatibility: @@ -1305,11 +1268,11 @@ int fde_seen = 0; if (flags == 0) { if (pending_transaction > 0) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Transaction cannot be @ pos %llu: " - "Another MariaDB 10 transaction (GTID %u-%u-%lu)" - " was opened at %llu", - pos, domainid, hdr.serverid, n_sequence, last_known_commit))); + MXS_ERROR("Transaction cannot be @ pos %llu: " + "Another MariaDB 10 transaction (GTID %u-%u-%lu)" + " was opened at %llu", + pos, domainid, hdr.serverid, + n_sequence, last_known_commit); gwbuf_free(result); @@ -1321,10 +1284,9 @@ int fde_seen = 0; event_bytes = 0; if (debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - "> MariaDB 10 Transaction (GTID %u-%u-%lu)" - " starts @ pos %llu", - domainid, hdr.serverid, n_sequence, pos))); + MXS_DEBUG("> MariaDB 10 Transaction (GTID %u-%u-%lu)" + " starts @ pos %llu", + domainid, hdr.serverid, n_sequence, pos); } } } @@ -1350,10 +1312,9 @@ int fde_seen = 0; /* A transaction starts with this event */ if (strncmp(statement_sql, "BEGIN", 5) == 0) { if (pending_transaction > 0) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: Transaction cannot be @ pos %llu: " - "Another transaction was opened at %llu", - pos, last_known_commit))); + MXS_ERROR("Transaction cannot be @ pos %llu: " + "Another transaction was opened at %llu", + pos, last_known_commit); free(statement_sql); gwbuf_free(result); @@ -1366,8 +1327,7 @@ int fde_seen = 0; event_bytes = 0; if (debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - "> Transaction starts @ pos %llu", pos))); + MXS_DEBUG("> Transaction starts @ pos %llu", pos); } } @@ -1377,8 +1337,8 @@ int fde_seen = 0; pending_transaction = 3; if (debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - " Transaction @ pos %llu, closing @ %llu", last_known_commit, pos))); + MXS_DEBUG(" Transaction @ pos %llu, closing @ %llu", + last_known_commit, pos); } } free(statement_sql); @@ -1391,15 +1351,15 @@ int fde_seen = 0; if (pending_transaction > 0) { pending_transaction = 2; if (debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - " Transaction XID @ pos %llu, closing @ %llu", last_known_commit, pos))); + MXS_DEBUG(" Transaction XID @ pos %llu, closing @ %llu", + last_known_commit, pos); } } if (pending_transaction > 1) { if (debug) - LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG, - "< Transaction @ pos %llu, is now closed @ %llu. %lu events seen", last_known_commit, pos, transaction_events))); + MXS_DEBUG("< Transaction @ pos %llu, is now closed @ %llu. %lu events seen", + last_known_commit, pos, transaction_events); pending_transaction = 0; last_known_commit = pos; @@ -1415,27 +1375,24 @@ int fde_seen = 0; /* pos and next_pos sanity checks */ if (hdr.next_pos > 0 && hdr.next_pos < pos) { - LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE, - "Binlog %s: next pos %u < pos %llu, truncating to %llu", - router->binlog_name, - hdr.next_pos, - pos, - pos))); + MXS_INFO("Binlog %s: next pos %u < pos %llu, truncating to %llu", + router->binlog_name, + hdr.next_pos, + pos, + pos); router->binlog_position = last_known_commit; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1444,29 +1401,26 @@ int fde_seen = 0; } if (hdr.next_pos > 0 && hdr.next_pos != (pos + hdr.event_size)) { - LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE, - "Binlog %s: next pos %u != (pos %llu + event_size %u), truncating to %llu", - router->binlog_name, - hdr.next_pos, - pos, - hdr.event_size, - pos))); + MXS_INFO("Binlog %s: next pos %u != (pos %llu + event_size %u), truncating to %llu", + router->binlog_name, + hdr.next_pos, + pos, + hdr.event_size, + pos); router->binlog_position = last_known_commit; router->current_safe_event = last_known_commit; router->current_pos = pos; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); if (fix) { if (ftruncate(router->binlog_fd, router->binlog_position) == 0) { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Binlog file %s has been truncated at %lu", - router->binlog_name, - router->binlog_position))); + MXS_NOTICE("Binlog file %s has been truncated at %lu", + router->binlog_name, + router->binlog_position); fsync(router->binlog_fd); } } @@ -1488,8 +1442,8 @@ int fde_seen = 0; pos = hdr.next_pos; } else { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Current event type %d @ %llu has nex pos = %u : exiting", hdr.event_type, pos, hdr.next_pos))); + MXS_ERROR("Current event type %d @ %llu has nex pos = %u : exiting", + hdr.event_type, pos, hdr.next_pos); break; } @@ -1497,20 +1451,18 @@ int fde_seen = 0; } if (pending_transaction) { - LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE, - "Binlog %s contains an Open Transaction, truncating to %llu", - router->binlog_name, - last_known_commit))); + MXS_INFO("Binlog %s contains an Open Transaction, truncating to %llu", + router->binlog_name, + last_known_commit); router->binlog_position = last_known_commit; router->current_safe_event = last_known_commit; router->current_pos = pos; router->pending_transaction = 1; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "warning : an error has been found. " - "Setting safe pos to %lu, current pos %lu", - router->binlog_position, router->current_pos))); + MXS_WARNING("an error has been found. " + "Setting safe pos to %lu, current pos %lu", + router->binlog_position, router->current_pos); return 0; } else { @@ -1707,10 +1659,9 @@ char *event_desc; event_desc = blr_get_event_description(router, first_event.event_type); - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "%lu @ %llu, %s, (%s), First EventTime", - first_event.event_time, first_event.event_pos, - event_desc != NULL ? event_desc : "unknown", buf_t))); + MXS_NOTICE("%lu @ %llu, %s, (%s), First EventTime", + first_event.event_time, first_event.event_pos, + event_desc != NULL ? event_desc : "unknown", buf_t); /* Last Event */ localtime_r(&last_event.event_time, &tm_t); @@ -1722,9 +1673,8 @@ char *event_desc; event_desc = blr_get_event_description(router, last_event.event_type); - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "%lu @ %llu, %s, (%s), Last EventTime", - last_event.event_time, last_event.event_pos, - event_desc != NULL ? event_desc : "unknown", buf_t))); + MXS_NOTICE("%lu @ %llu, %s, (%s), Last EventTime", + last_event.event_time, last_event.event_pos, + event_desc != NULL ? event_desc : "unknown", buf_t); } diff --git a/server/modules/routing/binlog/blr_master.c b/server/modules/routing/binlog/blr_master.c index 7126b6a20..cb555dd30 100644 --- a/server/modules/routing/binlog/blr_master.c +++ b/server/modules/routing/binlog/blr_master.c @@ -87,7 +87,7 @@ static int blr_rotate_event(ROUTER_INSTANCE *router, uint8_t *pkt, REP_HEADER * void blr_distribute_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint8_t *ptr); static void *CreateMySQLAuthData(char *username, char *password, char *database); void blr_extract_header(uint8_t *pkt, REP_HEADER *hdr); -static void blr_log_packet(logfile_id_t file, char *msg, uint8_t *ptr, int len); +static void blr_log_packet(int priority, char *msg, uint8_t *ptr, int len); void blr_master_close(ROUTER_INSTANCE *); char *blr_extract_column(GWBUF *buf, int col); void blr_cache_response(ROUTER_INSTANCE *router, char *response, GWBUF *buf); @@ -119,13 +119,11 @@ DCB *client; if (router->master_state != BLRM_UNCONNECTED) { if (router->master_state != BLRM_SLAVE_STOPPED) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "%s: Master Connect: Unexpected master state %s\n", - router->service->name, blrm_states[router->master_state]))); + MXS_ERROR("%s: Master Connect: Unexpected master state %s\n", + router->service->name, blrm_states[router->master_state]); } else { - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "%s: Master Connect: binlog state is %s\n", - router->service->name, blrm_states[router->master_state]))); + MXS_NOTICE("%s: Master Connect: binlog state is %s\n", + router->service->name, blrm_states[router->master_state]); } spinlock_release(&router->lock); return; @@ -142,8 +140,7 @@ DCB *client; spinlock_release(&router->lock); if ((client = dcb_alloc(DCB_ROLE_INTERNAL)) == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Binlog router: failed to create DCB for dummy client"))); + MXS_ERROR("Binlog router: failed to create DCB for dummy client"); return; } router->client = client; @@ -151,8 +148,7 @@ DCB *client; client->data = CreateMySQLAuthData(router->user, router->password, ""); if ((router->session = session_alloc(router->service, client)) == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Binlog router: failed to create session for connection to master"))); + MXS_ERROR("Binlog router: failed to create session for connection to master"); return; } client->session = router->session; @@ -169,17 +165,15 @@ DCB *client; } if (router->retry_backoff > BLR_MAX_BACKOFF) router->retry_backoff = BLR_MAX_BACKOFF; - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Binlog router: failed to connect to master server '%s'", - router->service->dbref->server->unique_name))); + MXS_ERROR("Binlog router: failed to connect to master server '%s'", + router->service->dbref->server->unique_name); return; } router->master->remote = strdup(router->service->dbref->server->name); - LOGIF(LM,(skygw_log_write( - LOGFILE_MESSAGE, - "%s: attempting to connect to master server %s:%d, binlog %s, pos %lu", - router->service->name, router->service->dbref->server->name, router->service->dbref->server->port, router->binlog_name, router->current_pos))); + MXS_NOTICE("%s: attempting to connect to master server %s:%d, binlog %s, pos %lu", + router->service->name, router->service->dbref->server->name, + router->service->dbref->server->port, router->binlog_name, router->current_pos); router->connect_time = time(0); @@ -339,10 +333,8 @@ char task_name[BLRM_TASK_NAME_LEN + 1] = ""; spinlock_release(&router->lock); if (router->master_state < 0 || router->master_state > BLRM_MAXSTATE) { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Invalid master state machine state (%d) for binlog router.", - router->master_state))); + MXS_ERROR("Invalid master state machine state (%d) for binlog router.", + router->master_state); gwbuf_consume(buf, gwbuf_length(buf)); spinlock_acquire(&router->lock); @@ -351,12 +343,9 @@ char task_name[BLRM_TASK_NAME_LEN + 1] = ""; router->active_logs = 0; spinlock_release(&router->lock); atomic_add(&router->handling_threads, -1); - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "%s: Pending reconnect in state %s.", - router->service->name, - blrm_states[router->master_state] - ))); + MXS_ERROR("%s: Pending reconnect in state %s.", + router->service->name, + blrm_states[router->master_state]); blr_restart_master(router); return; } @@ -374,10 +363,8 @@ char task_name[BLRM_TASK_NAME_LEN + 1] = ""; * continue. The error is saved and replayed to slaves if * they also request the GTID mode. */ - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "%s: Master server does not support GTID Mode.", - router->service->name))); + MXS_ERROR("%s: Master server does not support GTID Mode.", + router->service->name); } else if (router->master_state != BLRM_BINLOGDUMP && MYSQL_RESPONSE_ERR(buf)) { @@ -395,14 +382,11 @@ char task_name[BLRM_TASK_NAME_LEN + 1] = ""; /* NULL terminated error string */ *(msg_err+msg_len)='\0'; - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "%s: Received error: %lu, '%s' from master during '%s' phase " - "of the master state machine.", - router->service->name, - mysql_errno, msg_err, - blrm_states[router->master_state] - ))); + MXS_ERROR("%s: Received error: %lu, '%s' from master during '%s' phase " + "of the master state machine.", + router->service->name, + mysql_errno, msg_err, + blrm_states[router->master_state]); gwbuf_consume(buf, gwbuf_length(buf)); spinlock_acquire(&router->lock); @@ -643,14 +627,12 @@ char task_name[BLRM_TASK_NAME_LEN + 1] = ""; buf = blr_make_binlog_dump(router); router->master_state = BLRM_BINLOGDUMP; router->master->func.write(router->master, buf); - LOGIF(LM,(skygw_log_write( - LOGFILE_MESSAGE, - "%s: Request binlog records from %s at " - "position %lu from master server %s:%d", - router->service->name, router->binlog_name, - router->current_pos, - router->service->dbref->server->name, - router->service->dbref->server->port))); + MXS_NOTICE("%s: Request binlog records from %s at " + "position %lu from master server %s:%d", + router->service->name, router->binlog_name, + router->current_pos, + router->service->dbref->server->name, + router->service->dbref->server->port); /* Log binlog router identity */ blr_log_identity(router); @@ -867,12 +849,10 @@ int n_bufs = -1, pn_bufs = -1; if ((msg = malloc(len)) == NULL) { - LOGIF(LE,(skygw_log_write( - LOGFILE_ERROR, - "Insufficient memory to buffer event " - "of %d bytes. Binlog %s @ %lu.", - len, router->binlog_name, - router->current_pos))); + MXS_ERROR("Insufficient memory to buffer event " + "of %d bytes. Binlog %s @ %lu.", + len, router->binlog_name, + router->current_pos); break; } @@ -891,13 +871,11 @@ int n_bufs = -1, pn_bufs = -1; } if (remainder) { - LOGIF(LE,(skygw_log_write( - LOGFILE_ERROR, - "Expected entire message in buffer " - "chain, but failed to create complete " - "message as expected. %s @ %lu", - router->binlog_name, - router->current_pos))); + MXS_ERROR("Expected entire message in buffer " + "chain, but failed to create complete " + "message as expected. %s @ %lu", + router->binlog_name, + router->current_pos); free(msg); msg = NULL; break; @@ -914,11 +892,9 @@ int n_bufs = -1, pn_bufs = -1; * until we receive the next buffer. */ router->stats.n_residuals++; - LOGIF(LD,(skygw_log_write( - LOGFILE_DEBUG, - "Residual data left after %lu records. %s @ %lu", - router->stats.n_binlogs, - router->binlog_name, router->current_pos))); + MXS_DEBUG("Residual data left after %lu records. %s @ %lu", + router->stats.n_binlogs, + router->binlog_name, router->current_pos); break; } else @@ -949,10 +925,7 @@ int n_bufs = -1, pn_bufs = -1; { msg = "error"; } - LOGIF(LM,(skygw_log_write( - LOGFILE_MESSAGE, - "Non-event message (%s) from master.", - msg))); + MXS_NOTICE("Non-event message (%s) from master.", msg); } else { @@ -964,25 +937,22 @@ int n_bufs = -1, pn_bufs = -1; /* Sanity check */ if (hdr.ok == 0 && hdr.event_size != len - 5) { - LOGIF(LE,(skygw_log_write( - LOGFILE_ERROR, - "Packet length is %d, but event size is %d, " - "binlog file %s position %lu " - "reslen is %d and preslen is %d, " - "length of previous event %d. %s", - len, hdr.event_size, - router->binlog_name, - router->current_pos, - reslen, preslen, prev_length, - (prev_length == -1 ? - (no_residual ? "No residual data from previous call" : "Residual data from previous call") : "") - ))); - blr_log_packet(LOGFILE_ERROR, "Packet:", ptr, len); - LOGIF(LE,(skygw_log_write( - LOGFILE_ERROR, - "This event (0x%x) was contained in %d GWBUFs, " - "the previous events was contained in %d GWBUFs", - router->lastEventReceived, n_bufs, pn_bufs))); + MXS_ERROR("Packet length is %d, but event size is %d, " + "binlog file %s position %lu " + "reslen is %d and preslen is %d, " + "length of previous event %d. %s", + len, hdr.event_size, + router->binlog_name, + router->current_pos, + reslen, preslen, prev_length, + (prev_length == -1 ? + (no_residual ? "No residual data from previous call" : + "Residual data from previous call") : "")); + + blr_log_packet(LOG_ERR, "Packet:", ptr, len); + MXS_ERROR("This event (0x%x) was contained in %d GWBUFs, " + "the previous events was contained in %d GWBUFs", + router->lastEventReceived, n_bufs, pn_bufs); if (msg) { free(msg); @@ -1030,14 +1000,13 @@ int n_bufs = -1, pn_bufs = -1; free(msg); msg = NULL; } - LOGIF(LE,(skygw_log_write(LOGFILE_ERROR, - "%s: Checksum error in event " - "from master, " - "binlog %s @ %lu. " - "Closing master connection.", - router->service->name, - router->binlog_name, - router->current_pos))); + MXS_ERROR("%s: Checksum error in event " + "from master, " + "binlog %s @ %lu. " + "Closing master connection.", + router->service->name, + router->binlog_name, + router->current_pos); blr_master_close(router); blr_master_delayed_connect(router); return; @@ -1088,14 +1057,14 @@ int n_bufs = -1, pn_bufs = -1; if (flags == 0) { if (router->pending_transaction > 0) { - LOGIF(LE,(skygw_log_write_flush(LOGFILE_ERROR, - "Error: a MariaDB 10 transaction " - "is already open " - "@ %lu (GTID %u-%u-%lu) and " - "a new one starts @ %lu", - router->binlog_position, - domainid, hdr.serverid, n_sequence, - router->current_pos))); + MXS_ERROR("A MariaDB 10 transaction " + "is already open " + "@ %lu (GTID %u-%u-%lu) and " + "a new one starts @ %lu", + router->binlog_position, + domainid, hdr.serverid, + n_sequence, + router->current_pos); // An action should be taken here } @@ -1127,11 +1096,10 @@ int n_bufs = -1, pn_bufs = -1; if (strncmp(statement_sql, "BEGIN", 5) == 0) { if (router->pending_transaction > 0) { - LOGIF(LE,(skygw_log_write_flush(LOGFILE_ERROR, - "Error: a transaction is already open " - "@ %lu and a new one starts @ %lu", - router->binlog_position, - router->current_pos))); + MXS_ERROR("A transaction is already open " + "@ %lu and a new one starts @ %lu", + router->binlog_position, + router->current_pos); // An action should be taken here } @@ -1175,11 +1143,10 @@ int n_bufs = -1, pn_bufs = -1; if (hdr.event_type == FORMAT_DESCRIPTION_EVENT && hdr.next_pos == 0) { // Fake format description message - LOGIF(LD,(skygw_log_write(LOGFILE_DEBUG, - "Replication fake event. " - "Binlog %s @ %lu.", - router->binlog_name, - router->current_pos))); + MXS_DEBUG("Replication fake event. " + "Binlog %s @ %lu.", + router->binlog_name, + router->current_pos); router->stats.n_fakeevents++; if (hdr.event_type == FORMAT_DESCRIPTION_EVENT) @@ -1202,13 +1169,12 @@ int n_bufs = -1, pn_bufs = -1; } else { - LOGIF(LE,(skygw_log_write(LOGFILE_ERROR, - "%s: Received a format description " - "event that MaxScale was unable to " - "record. Event length is %d.", - router->service->name, - hdr.event_size))); - blr_log_packet(LOGFILE_ERROR, + MXS_ERROR("%s: Received a format description " + "event that MaxScale was unable to " + "record. Event length is %d.", + router->service->name, + hdr.event_size); + blr_log_packet(LOG_ERR, "Format Description Event:", ptr, len); } } @@ -1220,12 +1186,10 @@ int n_bufs = -1, pn_bufs = -1; #ifdef SHOW_EVENTS printf("Replication heartbeat\n"); #endif - LOGIF(LD,(skygw_log_write( - LOGFILE_DEBUG, - "Replication heartbeat. " - "Binlog %s @ %lu.", - router->binlog_name, - router->current_pos))); + MXS_DEBUG("Replication heartbeat. " + "Binlog %s @ %lu.", + router->binlog_name, + router->current_pos); router->stats.n_heartbeats++; @@ -1347,23 +1311,23 @@ int n_bufs = -1, pn_bufs = -1; /* No event has been sent */ if (pos == router->binlog_position) { - LOGIF(LE,(skygw_log_write(LOGFILE_ERROR, - "No events distributed to slaves for a pending transaction in %s at %lu." - " Last event from master at %lu", - router->binlog_name, - router->binlog_position, - router->current_pos))); + MXS_ERROR("No events distributed to slaves for a pending " + "transaction in %s at %lu. " + "Last event from master at %lu", + router->binlog_name, + router->binlog_position, + router->current_pos); strncpy(err_message, "No transaction events sent", BINLOG_ERROR_MSG_LEN); } else { /* Some events have been sent */ - LOGIF(LE,(skygw_log_write(LOGFILE_ERROR, - "Some events were not distributed to slaves for a pending transaction " - "in %s at %lu. Last distributed even at %llu, last event from master at %lu", - router->binlog_name, - router->binlog_position, - pos, - router->current_pos))); + MXS_ERROR("Some events were not distributed to slaves for a " + "pending transaction in %s at %lu. Last distributed " + "even at %llu, last event from master at %lu", + router->binlog_name, + router->binlog_position, + pos, + router->current_pos); strncpy(err_message, "Incomplete transaction events sent", BINLOG_ERROR_MSG_LEN); } @@ -1386,16 +1350,14 @@ int n_bufs = -1, pn_bufs = -1; else { router->stats.n_artificial++; - LOGIF(LD,(skygw_log_write( - LOGFILE_DEBUG, - "Artificial event not written " - "to disk or distributed. " - "Type 0x%x, Length %d, Binlog " - "%s @ %lu.", - hdr.event_type, - hdr.event_size, - router->binlog_name, - router->current_pos))); + MXS_DEBUG("Artificial event not written " + "to disk or distributed. " + "Type 0x%x, Length %d, Binlog " + "%s @ %lu.", + hdr.event_type, + hdr.event_size, + router->binlog_name, + router->current_pos); ptr += 5; if (hdr.event_type == ROTATE_EVENT) { @@ -1445,10 +1407,9 @@ int n_bufs = -1, pn_bufs = -1; spinlock_release(&router->lock); - LOGIF(LE,(skygw_log_write(LOGFILE_ERROR, - "Error packet in binlog stream.%s @ %lu.", - router->binlog_name, - router->current_pos))); + MXS_ERROR("Error packet in binlog stream.%s @ %lu.", + router->binlog_name, + router->current_pos); router->stats.n_binlog_errors++; } @@ -1572,9 +1533,7 @@ MYSQL_session *auth_info; if (username == NULL || password == NULL) { - LOGIF(LE,(skygw_log_write( - LOGFILE_ERROR, - "You must specify both username and password for the binlog router.\n"))); + MXS_ERROR("You must specify both username and password for the binlog router.\n"); return NULL; } @@ -1690,12 +1649,11 @@ int action; * happen. Force the slave to catchup mode in order to * try to resolve the issue. */ - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Slave %d is ahead of expected position %s@%lu. " - "Expected position %d", - slave->serverid, slave->binlogfile, - (unsigned long)slave->binlog_pos, - hdr->next_pos - hdr->event_size))); + MXS_ERROR("Slave %d is ahead of expected position %s@%lu. " + "Expected position %d", + slave->serverid, slave->binlogfile, + (unsigned long)slave->binlog_pos, + hdr->next_pos - hdr->event_size); } /* @@ -1792,13 +1750,13 @@ int action; /** * Write a raw event (the first 40 bytes at most) to a log file * - * @param file The logfile to write to - * @param msg A textual message to write before the packet - * @param ptr Pointer to the message buffer - * @param len Length of message packet + * @param priority The syslog priority of the message (LOG_ERR, LOG_WARNING, etc.) + * @param msg A textual message to write before the packet + * @param ptr Pointer to the message buffer + * @param len Length of message packet */ static void -blr_log_packet(logfile_id_t file, char *msg, uint8_t *ptr, int len) +blr_log_packet(int priority, char *msg, uint8_t *ptr, int len) { char buf[400] = ""; char *bufp; @@ -1809,10 +1767,9 @@ int i; for (i = 0; i < len && i < 40; i++) bufp += sprintf(bufp, "0x%02x ", ptr[i]); if (i < len) - skygw_log_write_flush(file, "%s...", buf); + MXS_LOG_MESSAGE(priority, "%s...", buf); else - skygw_log_write_flush(file, "%s", buf); - + MXS_LOG_MESSAGE(priority, "%s", buf); } /** @@ -1924,10 +1881,9 @@ int event_limit; /* error */ if (pos > end_pos) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Error: Reading saved events, the specified pos %llu " - "is ahead of current pos %lu for file %s", - pos, router->current_pos, router->binlog_name))); + MXS_ERROR("Reading saved events, the specified pos %llu " + "is ahead of current pos %lu for file %s", + pos, router->current_pos, router->binlog_name); return NULL; } @@ -1937,31 +1893,27 @@ int event_limit; switch (n) { case 0: - LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG, - "Reading saved events: reached end of binlog file at %llu.", pos))); + MXS_DEBUG("Reading saved events: reached end of binlog file at %llu.", pos); break; case -1: { char err_msg[STRERROR_BUFLEN]; - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: failed to read binlog " - "file %s at position %llu" - " (%s).", router->binlog_name, - pos, strerror_r(errno, err_msg, sizeof(err_msg))))); + MXS_ERROR("Reading saved events: failed to read binlog " + "file %s at position %llu" + " (%s).", router->binlog_name, + pos, strerror_r(errno, err_msg, sizeof(err_msg))); if (errno == EBADF) - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: bad file descriptor for file %s" - ", descriptor %d.", - router->binlog_name, router->binlog_fd))); + MXS_ERROR("Reading saved events: bad file descriptor for file %s" + ", descriptor %d.", + router->binlog_name, router->binlog_fd); break; } default: - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: short read when reading the header. " - "Expected 19 bytes but got %d bytes. " - "Binlog file is %s, position %llu", - n, router->binlog_name, pos))); + MXS_ERROR("Reading saved events: short read when reading the header. " + "Expected 19 bytes but got %d bytes. " + "Binlog file is %s, position %llu", + n, router->binlog_name, pos); break; } @@ -1979,20 +1931,18 @@ int event_limit; if (hdr->event_type > event_limit) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: invalid event type 0x%x. " - "Binlog file is %s, position %llu", - hdr->event_type, - router->binlog_name, pos))); + MXS_ERROR("Reading saved events: invalid event type 0x%x. " + "Binlog file is %s, position %llu", + hdr->event_type, + router->binlog_name, pos); return NULL; } if ((result = gwbuf_alloc(hdr->event_size)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: failed to allocate memory for binlog entry, " - "size %d at %llu.", - hdr->event_size, pos))); + MXS_ERROR("Reading saved events: failed to allocate memory for binlog entry, " + "size %d at %llu.", + hdr->event_size, pos); return NULL; } @@ -2006,24 +1956,21 @@ int event_limit; if (n == -1) { char err_msg[STRERROR_BUFLEN]; - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: the event at %llu in %s. " - "%s, expected %d bytes.", - pos, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg)), hdr->event_size - 19))); + MXS_ERROR("Reading saved events: the event at %llu in %s. " + "%s, expected %d bytes.", + pos, router->binlog_name, + strerror_r(errno, err_msg, sizeof(err_msg)), hdr->event_size - 19); } else { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: short read when reading " - "the event at %llu in %s. " - "Expected %d bytes got %d bytes.", - pos, router->binlog_name, hdr->event_size - 19, n))); + MXS_ERROR("Reading saved events: short read when reading " + "the event at %llu in %s. " + "Expected %d bytes got %d bytes.", + pos, router->binlog_name, hdr->event_size - 19, n); if (end_pos - pos < hdr->event_size) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Error: Reading saved events: binlog event " - "is close to the end of the binlog file, " - "current file size is %llu.", end_pos))); + MXS_ERROR("Reading saved events: binlog event " + "is close to the end of the binlog file, " + "current file size is %llu.", end_pos); } } @@ -2154,14 +2101,15 @@ char *event_desc = NULL; if (router->master_state == BLRM_BINLOGDUMP && router->lastEventReceived > 0) { if ((t_now - router->stats.lastReply) > (router->heartbeat + BLR_NET_LATENCY_WAIT_TIME)) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "ERROR: No event received from master %s:%d in heartbeat period (%lu seconds), last event (%s %d) received %lu seconds ago. Assuming connection is dead and reconnecting.", - router->service->dbref->server->name, - router->service->dbref->server->port, - router->heartbeat, - event_desc != NULL ? event_desc : "unknown", - router->lastEventReceived, - t_now - router->stats.lastReply))); + MXS_ERROR("No event received from master %s:%d in heartbeat period (%lu seconds), " + "last event (%s %d) received %lu seconds ago. Assuming connection is dead " + "and reconnecting.", + router->service->dbref->server->name, + router->service->dbref->server->port, + router->heartbeat, + event_desc != NULL ? event_desc : "unknown", + router->lastEventReceived, + t_now - router->stats.lastReply); return 0; } @@ -2201,33 +2149,27 @@ static void blr_log_identity(ROUTER_INSTANCE *router) { } /* Seen by the master */ - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: identity seen by the master: " - "server_id: %d, uuid: %s", - router->service->name, - router->serverid, (router->uuid == NULL ? "not available" : router->uuid)))); + MXS_NOTICE("%s: identity seen by the master: " + "server_id: %d, uuid: %s", + router->service->name, + router->serverid, (router->uuid == NULL ? "not available" : router->uuid)); /* Seen by the slaves */ /* MariaDB 5.5 and MariaDB don't have the MASTER_UUID var */ if (master_uuid == NULL) { - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: identity seen by the slaves: " - "server_id: %d, hostname: %s, MySQL version: %s", - router->service->name, - router->masterid, (master_hostname == NULL ? "not available" : master_hostname), - (master_version == NULL ? "not available" : master_version)))); + MXS_NOTICE("%s: identity seen by the slaves: " + "server_id: %d, hostname: %s, MySQL version: %s", + router->service->name, + router->masterid, (master_hostname == NULL ? "not available" : master_hostname), + (master_version == NULL ? "not available" : master_version)); } else { - LOGIF(LM, (skygw_log_write_flush( - LOGFILE_MESSAGE, - "%s: identity seen by the slaves: " - "server_id: %d, uuid: %s, hostname: %s, MySQL version: %s", - router->service->name, - router->masterid, master_uuid, - (master_hostname == NULL ? "not available" : master_hostname), - (master_version == NULL ? "not available" : master_version)))); + MXS_NOTICE("%s: identity seen by the slaves: " + "server_id: %d, uuid: %s, hostname: %s, MySQL version: %s", + router->service->name, + router->masterid, master_uuid, + (master_hostname == NULL ? "not available" : master_hostname), + (master_version == NULL ? "not available" : master_version)); } } diff --git a/server/modules/routing/binlog/blr_slave.c b/server/modules/routing/binlog/blr_slave.c index 0adbaef02..01a3d84ea 100644 --- a/server/modules/routing/binlog/blr_slave.c +++ b/server/modules/routing/binlog/blr_slave.c @@ -176,9 +176,8 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue) { if (slave->state < 0 || slave->state > BLRS_MAXSTATE) { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, "Invalid slave state machine state (%d) for binlog router.", - slave->state))); + MXS_ERROR("Invalid slave state machine state (%d) for binlog router.", + slave->state); gwbuf_consume(queue, gwbuf_length(queue)); return 0; } @@ -196,11 +195,9 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue) blr_slave_send_error_packet(slave, "Binlog router is not yet configured for replication", (unsigned int) 1597, NULL); - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "%s: Slave %s: Binlog router is not yet configured for replication", - router->service->name, - slave->dcb->remote))); + MXS_ERROR("%s: Slave %s: Binlog router is not yet configured for replication", + router->service->name, + slave->dcb->remote); dcb_close(slave->dcb); return 1; } @@ -215,11 +212,9 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue) blr_send_custom_error(slave->dcb, 1, 0, "MariaDB 10 Slave is required for Slave registration", "42000", 1064); - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "%s: Slave %s: a MariaDB 10 Slave is required for Slave registration", - router->service->name, - slave->dcb->remote))); + MXS_ERROR("%s: Slave %s: a MariaDB 10 Slave is required for Slave registration", + router->service->name, + slave->dcb->remote); dcb_close(slave->dcb); return 1; @@ -252,18 +247,15 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue) return blr_ping(router, slave, queue); break; case COM_QUIT: - LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG, - "COM_QUIT received from slave with server_id %d", - slave->serverid))); + MXS_DEBUG("COM_QUIT received from slave with server_id %d", + slave->serverid); break; default: blr_send_custom_error(slave->dcb, 1, 0, "You have an error in your SQL syntax; Check the syntax the MaxScale binlog router accepts.", "42000", 1064); - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Unexpected MySQL Command (%d) received from slave", - MYSQL_COMMAND(queue)))); + MXS_ERROR("Unexpected MySQL Command (%d) received from slave", + MYSQL_COMMAND(queue)); break; } return 0; @@ -355,13 +347,11 @@ extern char *strcasestr(); } } - LOGIF(LT, (skygw_log_write( - LOGFILE_TRACE, "Execute statement (truncated, it contains password)" - " from the slave '%s'", new_text))); + MXS_INFO("Execute statement (truncated, it contains password)" + " from the slave '%s'", new_text); free(new_text); } else { - LOGIF(LT, (skygw_log_write( - LOGFILE_TRACE, "Execute statement from the slave '%s'", query_text))); + MXS_INFO("Execute statement from the slave '%s'", query_text); } /* @@ -375,15 +365,14 @@ extern char *strcasestr(); if ((word = strtok_r(query_text, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete query.", - router->service->name))); + MXS_ERROR("%s: Incomplete query.", router->service->name); } else if (strcasecmp(word, "SELECT") == 0) { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete select query.", - router->service->name))); + MXS_ERROR("%s: Incomplete select query.", + router->service->name); } else if (strcasecmp(word, "UNIX_TIMESTAMP()") == 0) { @@ -485,8 +474,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete show query.", - router->service->name))); + MXS_ERROR("%s: Incomplete show query.", + router->service->name); } else if (strcasecmp(word, "WARNINGS") == 0) { @@ -502,9 +491,8 @@ extern char *strcasestr(); if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected VARIABLES in SHOW GLOBAL", - router->service->name))); + MXS_ERROR("%s: Expected VARIABLES in SHOW GLOBAL", + router->service->name); } else if (strcasecmp(word, "VARIABLES") == 0) { @@ -519,9 +507,8 @@ extern char *strcasestr(); return 1; } else - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected LIKE clause in SHOW GLOBAL VARIABLES.", - router->service->name))); + MXS_ERROR("%s: Expected LIKE clause in SHOW GLOBAL VARIABLES.", + router->service->name); } else if (strcasecmp(word, "STATUS") == 0) { @@ -536,9 +523,8 @@ extern char *strcasestr(); return 1; } else - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected LIKE clause in SHOW GLOBAL STATUS.", - router->service->name))); + MXS_ERROR("%s: Expected LIKE clause in SHOW GLOBAL STATUS.", + router->service->name); } } else if (strcasecmp(word, "VARIABLES") == 0) @@ -560,17 +546,15 @@ extern char *strcasestr(); return 1; } else - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected LIKE clause in SHOW VARIABLES.", - router->service->name))); + MXS_ERROR("%s: Expected LIKE clause in SHOW VARIABLES.", + router->service->name); } else if (strcasecmp(word, "MASTER") == 0) { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected SHOW MASTER STATUS command", - router->service->name))); + MXS_ERROR("%s: Expected SHOW MASTER STATUS command", + router->service->name); } else if (strcasecmp(word, "STATUS") == 0) { @@ -588,9 +572,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected SHOW SLAVE STATUS command", - router->service->name))); + MXS_ERROR("%s: Expected SHOW SLAVE STATUS command", + router->service->name); } else if (strcasecmp(word, "STATUS") == 0) { @@ -624,17 +607,16 @@ extern char *strcasestr(); return 1; } else - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected LIKE clause in SHOW STATUS.", - router->service->name))); + MXS_ERROR("%s: Expected LIKE clause in SHOW STATUS.", + router->service->name); } } else if (strcasecmp(query_text, "SET") == 0) { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete set command.", - router->service->name))); + MXS_ERROR("%s: Incomplete set command.", + router->service->name); } else if (strcasecmp(word, "@master_heartbeat_period") == 0) { @@ -694,8 +676,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Truncated SET NAMES command.", - router->service->name))); + MXS_ERROR("%s: Truncated SET NAMES command.", + router->service->name); } else if (strcasecmp(word, "latin1") == 0) { @@ -713,8 +695,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete RESET command.", - router->service->name))); + MXS_ERROR("%s: Incomplete RESET command.", + router->service->name); } else if (strcasecmp(word, "SLAVE") == 0) { @@ -731,7 +713,7 @@ extern char *strcasestr(); if (!current_master) { snprintf(error_string, BINLOG_ERROR_MSG_LEN, "error allocating memory for blr_master_get_config"); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error_string))); + MXS_ERROR("%s: %s", router->service->name, error_string); blr_slave_send_error_packet(slave, error_string, (unsigned int)1201, NULL); return 1; @@ -740,13 +722,15 @@ extern char *strcasestr(); /* get current data */ blr_master_get_config(router, current_master); - LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, "%s: 'RESET SLAVE executed'. Previous state MASTER_HOST='%s', MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, MASTER_USER='%s'", - router->service->name, - current_master->host, - current_master->port, - current_master->logfile, - current_master->pos, - current_master->user))); + MXS_NOTICE("%s: 'RESET SLAVE executed'. Previous state MASTER_HOST='%s', " + "MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, " + "MASTER_USER='%s'", + router->service->name, + current_master->host, + current_master->port, + current_master->logfile, + current_master->pos, + current_master->user); /* remove master.ini */ strncpy(path, router->binlogdir, PATH_MAX); @@ -759,7 +743,7 @@ extern char *strcasestr(); if (removed_cfg == -1) { char err_msg[STRERROR_BUFLEN]; snprintf(error_string, BINLOG_ERROR_MSG_LEN, "Error removing %s, %s, errno %u", path, strerror_r(errno, err_msg, sizeof(err_msg)), errno); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error_string))); + MXS_ERROR("%s: %s", router->service->name, error_string); } spinlock_acquire(&router->lock); @@ -790,8 +774,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete START command.", - router->service->name))); + MXS_ERROR("%s: Incomplete START command.", + router->service->name); } else if (strcasecmp(word, "SLAVE") == 0) { @@ -804,8 +788,7 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete STOP command.", - router->service->name))); + MXS_ERROR("%s: Incomplete STOP command.", router->service->name); } else if (strcasecmp(word, "SLAVE") == 0) { @@ -818,8 +801,7 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete CHANGE command.", - router->service->name))); + MXS_ERROR("%s: Incomplete CHANGE command.", router->service->name); } else if (strcasecmp(word, "MASTER") == 0) { @@ -840,7 +822,7 @@ extern char *strcasestr(); if (!current_master) { free(query_text); strcpy(error_string, "Error allocating memory for blr_master_get_config"); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error_string))); + MXS_ERROR("%s: %s", router->service->name, error_string); blr_slave_send_error_packet(slave, error_string, (unsigned int)1201, NULL); @@ -876,8 +858,8 @@ extern char *strcasestr(); spinlock_release(&router->lock); snprintf(error_string, BINLOG_ERROR_MSG_LEN, "Error writing into %s/master.ini: %s", router->binlogdir, error); - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: %s", - router->service->name, error_string))); + MXS_ERROR("%s: %s", + router->service->name, error_string); blr_slave_send_error_packet(slave, error_string, (unsigned int)1201, NULL); @@ -923,8 +905,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "%s: Incomplete DISCONNECT command.", - router->service->name))); + MXS_ERROR("%s: Incomplete DISCONNECT command.", + router->service->name); } else if (strcasecmp(word, "ALL") == 0) { @@ -935,9 +917,8 @@ extern char *strcasestr(); { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Expected DISCONNECT SERVER $server_id", - router->service->name))); + MXS_ERROR("%s: Expected DISCONNECT SERVER $server_id", + router->service->name); } else { int serverid = atoi(word); free(query_text); @@ -949,8 +930,7 @@ extern char *strcasestr(); free(query_text); query_text = strndup(qtext, query_len); - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, "Unexpected query from '%s'@'%s': %s", slave->dcb->user, slave->dcb->remote, query_text))); + MXS_ERROR("Unexpected query from '%s'@'%s': %s", slave->dcb->user, slave->dcb->remote, query_text); free(query_text); blr_slave_send_error(router, slave, "You have an error in your SQL syntax; Check the syntax the MaxScale binlog router accepts."); return 1; @@ -984,8 +964,7 @@ GWBUF *clone; } else { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Failed to clone server response to send to slave."))); + MXS_ERROR("Failed to clone server response to send to slave."); return 0; } } @@ -1713,20 +1692,16 @@ uint32_t chksum; binlognamelen = len - 11; if (binlognamelen > BINLOG_FNAMELEN) { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "blr_slave_binlog_dump truncating binlog filename " - "from %d to %d", - binlognamelen, BINLOG_FNAMELEN))); + MXS_ERROR("blr_slave_binlog_dump truncating binlog filename " + "from %d to %d", + binlognamelen, BINLOG_FNAMELEN); binlognamelen = BINLOG_FNAMELEN; } ptr += 4; // Skip length and sequence number if (*ptr++ != COM_BINLOG_DUMP) { - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "blr_slave_binlog_dump expected a COM_BINLOG_DUMP but received %d", - *(ptr-1)))); + MXS_ERROR("blr_slave_binlog_dump expected a COM_BINLOG_DUMP but received %d", + *(ptr-1)); return 0; } @@ -1737,12 +1712,10 @@ uint32_t chksum; strncpy(slave->binlogfile, (char *)ptr, binlognamelen); slave->binlogfile[binlognamelen] = 0; - LOGIF(LD, (skygw_log_write( - LOGFILE_DEBUG, - "%s: COM_BINLOG_DUMP: binlog name '%s', length %d, " - "from position %lu.", router->service->name, - slave->binlogfile, binlognamelen, - (unsigned long)slave->binlog_pos))); + MXS_DEBUG("%s: COM_BINLOG_DUMP: binlog name '%s', length %d, " + "from position %lu.", router->service->name, + slave->binlogfile, binlognamelen, + (unsigned long)slave->binlog_pos); slave->seqno = 1; @@ -1808,12 +1781,10 @@ uint32_t chksum; slave->state = BLRS_DUMPING; - LOGIF(LM, (skygw_log_write( - LOGFILE_MESSAGE, - "%s: Slave %s, server id %d requested binlog file %s from position %lu", - router->service->name, slave->dcb->remote, - slave->serverid, - slave->binlogfile, (unsigned long)slave->binlog_pos))); + MXS_NOTICE("%s: Slave %s, server id %d requested binlog file %s from position %lu", + router->service->name, slave->dcb->remote, + slave->serverid, + slave->binlogfile, (unsigned long)slave->binlog_pos); if (slave->binlog_pos != router->binlog_position || strcmp(slave->binlogfile, router->binlog_name) != 0) @@ -1949,11 +1920,10 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; poll_fake_write_event(slave->dcb); return rval; } - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Slave %s:%i, server-id %d, binlog '%s': blr_slave_catchup failed to open binlog file", - slave->dcb->remote, slave->port, slave->serverid, - slave->binlogfile))); + MXS_ERROR("Slave %s:%i, server-id %d, binlog '%s': blr_slave_catchup " + "failed to open binlog file", + slave->dcb->remote, slave->port, slave->serverid, + slave->binlogfile); slave->cstate &= ~CS_BUSY; slave->state = BLRS_ERRORED; @@ -1987,9 +1957,8 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; unsigned long beat1 = hkheartbeat; blr_close_binlog(router, slave->file); if (hkheartbeat - beat1 > 1) - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, "blr_close_binlog took %lu maxscale beats", - hkheartbeat - beat1))); + MXS_ERROR("blr_close_binlog took %lu maxscale beats", + hkheartbeat - beat1); blr_slave_rotate(router, slave, GWBUF_DATA(record)); beat1 = hkheartbeat; if ((slave->file = blr_open_binlog(router, slave->binlogfile)) == NULL) @@ -2005,13 +1974,12 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; poll_fake_write_event(slave->dcb); return rval; } - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Slave %s:%i, server-id %d, binlog '%s': blr_slave_catchup failed to open binlog file in rotate event", - slave->dcb->remote, - slave->port, - slave->serverid, - slave->binlogfile))); + MXS_ERROR("Slave %s:%i, server-id %d, binlog '%s': blr_slave_catchup " + "failed to open binlog file in rotate event", + slave->dcb->remote, + slave->port, + slave->serverid, + slave->binlogfile); slave->state = BLRS_ERRORED; @@ -2024,9 +1992,8 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; break; } if (hkheartbeat - beat1 > 1) - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, "blr_open_binlog took %lu beats", - hkheartbeat - beat1))); + MXS_ERROR("blr_open_binlog took %lu beats", + hkheartbeat - beat1); } slave->stats.n_bytes += gwbuf_length(head); written = slave->dcb->func.write(slave->dcb, head); @@ -2046,14 +2013,13 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; slave->stats.n_failed_read++; if (hdr.ok == SLAVE_POS_READ_ERR) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s Slave %s:%i, server-id %d, binlog '%s', %s", - router->service->name, - slave->dcb->remote, - slave->port, - slave->serverid, - slave->binlogfile, - read_errmsg))); + MXS_ERROR("%s Slave %s:%i, server-id %d, binlog '%s', %s", + router->service->name, + slave->dcb->remote, + slave->port, + slave->serverid, + slave->binlogfile, + read_errmsg); spinlock_acquire(&slave->catch_lock); @@ -2075,14 +2041,13 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; ROUTER_OBJECT *router_obj= router->service->router; - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Slave %s:%i, server-id %d, binlog '%s', %s", - router->service->name, - slave->dcb->remote, - slave->port, - slave->serverid, - slave->binlogfile, - read_errmsg))); + MXS_ERROR("%s: Slave %s:%i, server-id %d, binlog '%s', %s", + router->service->name, + slave->dcb->remote, + slave->port, + slave->serverid, + slave->binlogfile, + read_errmsg); /* * Close the slave session and socket @@ -2135,6 +2100,13 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; spinlock_release(&router->binlog_lock); state_change = 1; } + else + { + MXS_NOTICE("Execution entered branch were locks previously were NOT " + "released. Previously this would have caused a lock-up."); + spinlock_release(&slave->catch_lock); + spinlock_release(&router->binlog_lock); + } } if (state_change) @@ -2142,23 +2114,21 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; slave->stats.n_caughtup++; if (slave->stats.n_caughtup == 1) { - LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, - "%s: Slave %s:%d, server-id %d is up to date '%s', position %lu.", - router->service->name, - slave->dcb->remote, - slave->port, - slave->serverid, - slave->binlogfile, (unsigned long)slave->binlog_pos))); + MXS_NOTICE("%s: Slave %s:%d, server-id %d is up to date '%s', position %lu.", + router->service->name, + slave->dcb->remote, + slave->port, + slave->serverid, + slave->binlogfile, (unsigned long)slave->binlog_pos); } else if ((slave->stats.n_caughtup % 50) == 0) { - LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, - "%s: Slave %s:%d, server-id %d is up to date '%s', position %lu.", - router->service->name, - slave->dcb->remote, - slave->port, - slave->serverid, - slave->binlogfile, (unsigned long)slave->binlog_pos))); + MXS_NOTICE("%s: Slave %s:%d, server-id %d is up to date '%s', position %lu.", + router->service->name, + slave->dcb->remote, + slave->port, + slave->serverid, + slave->binlogfile, (unsigned long)slave->binlog_pos); } } } @@ -2178,13 +2148,12 @@ char read_errmsg[BINLOG_ERROR_MSG_LEN+1]; * but the new binlog file has not yet been created. Therefore * we ignore these issues during the rotate processing. */ - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Slave reached end of file for binlog file %s at %lu " - "which is not the file currently being downloaded. " - "Master binlog is %s, %lu. This may be caused by a " - "previous failure of the master.", - slave->binlogfile, (unsigned long)slave->binlog_pos, - router->binlog_name, router->binlog_position))); + MXS_ERROR("Slave reached end of file for binlog file %s at %lu " + "which is not the file currently being downloaded. " + "Master binlog is %s, %lu. This may be caused by a " + "previous failure of the master.", + slave->binlogfile, (unsigned long)slave->binlog_pos, + router->binlog_name, router->binlog_position); if (blr_slave_fake_rotate(router, slave)) { spinlock_acquire(&slave->catch_lock); @@ -2246,9 +2215,8 @@ ROUTER_INSTANCE *router = slave->router; } else { - LOGIF(LD, (skygw_log_write( - LOGFILE_DEBUG, "Ignored callback due to slave state %s", - blrs_states[slave->state]))); + MXS_DEBUG("Ignored callback due to slave state %s", + blrs_states[slave->state]); } } @@ -2385,13 +2353,12 @@ char err_msg[BINLOG_ERROR_MSG_LEN+1]; if ((record = blr_read_binlog(router, file, 4, &hdr, err_msg)) == NULL) { if (hdr.ok != SLAVE_POS_READ_OK) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Slave %s:%i, server-id %d, binlog '%s', blr_read_binlog failure: %s", - slave->dcb->remote, - slave->port, - slave->serverid, - slave->binlogfile, - err_msg))); + MXS_ERROR("Slave %s:%i, server-id %d, binlog '%s', blr_read_binlog failure: %s", + slave->dcb->remote, + slave->port, + slave->serverid, + slave->binlogfile, + err_msg); } blr_close_binlog(router, file); @@ -2610,12 +2577,12 @@ blr_slave_disconnect_server(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, int se { /* server_id found */ server_found = 1; - LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, "%s: Slave %s, server id %d, disconnected by %s@%s", - router->service->name, - sptr->dcb->remote, - server_id, - slave->dcb->user, - slave->dcb->remote))); + MXS_NOTICE("%s: Slave %s, server id %d, disconnected by %s@%s", + router->service->name, + sptr->dcb->remote, + server_id, + slave->dcb->user, + slave->dcb->remote); /* send server_id with disconnect state to client */ n = blr_slave_send_disconnected_server(router, slave, server_id, 1); @@ -2640,9 +2607,9 @@ blr_slave_disconnect_server(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, int se } if (n == 0) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "Error: gwbuf memory allocation in " - "DISCONNECT SERVER server_id [%d]", - sptr->serverid))); + MXS_ERROR("gwbuf memory allocation in " + "DISCONNECT SERVER server_id [%d]", + sptr->serverid); blr_slave_send_error(router, slave, "Memory allocation error for DISCONNECT SERVER"); } @@ -2690,9 +2657,9 @@ blr_slave_disconnect_all(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave) len = 5 + strlen(server_id) + strlen(state) + 1; if ((pkt = gwbuf_alloc(len)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "Error: gwbuf memory allocation in " - "DISCONNECT ALL for [%s], server_id [%d]", - sptr->dcb->remote, sptr->serverid))); + MXS_ERROR("gwbuf memory allocation in " + "DISCONNECT ALL for [%s], server_id [%d]", + sptr->dcb->remote, sptr->serverid); spinlock_release(&router->lock); @@ -2701,9 +2668,9 @@ blr_slave_disconnect_all(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave) return 1; } - LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, "%s: Slave %s, server id %d, disconnected by %s@%s", - router->service->name, - sptr->dcb->remote, sptr->serverid, slave->dcb->user, slave->dcb->remote))); + MXS_NOTICE("%s: Slave %s, server id %d, disconnected by %s@%s", + router->service->name, + sptr->dcb->remote, sptr->serverid, slave->dcb->user, slave->dcb->remote); ptr = GWBUF_DATA(pkt); encode_value(ptr, len - 4, 24); // Add length of data packet @@ -2870,15 +2837,14 @@ blr_stop_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave) spinlock_release(&router->lock); - LOGIF(LM, (skygw_log_write( - LOGFILE_MESSAGE, - "%s: STOP SLAVE executed by %s@%s. Disconnecting from master %s:%d, read up to log %s, pos %lu, transaction safe pos %lu", - router->service->name, - slave->dcb->user, - slave->dcb->remote, - router->service->dbref->server->name, - router->service->dbref->server->port, - router->binlog_name, router->current_pos, router->binlog_position))); + MXS_NOTICE("%s: STOP SLAVE executed by %s@%s. Disconnecting from master %s:%d, " + "read up to log %s, pos %lu, transaction safe pos %lu", + router->service->name, + slave->dcb->user, + slave->dcb->remote, + router->service->dbref->server->name, + router->service->dbref->server->port, + router->binlog_name, router->current_pos, router->binlog_position); if (router->trx_safe && router->pending_transaction) { char message[BINLOG_ERROR_MSG_LEN+1] = ""; @@ -2943,16 +2909,14 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave) truncate(file, router->last_safe_pos); /* Log it */ - LOGIF(LE, (skygw_log_write( - LOGFILE_ERROR, - "Warning: a transaction is still opened at pos %lu" - " File %s will be truncated. " - "Next binlog file is %s at pos %d, " - "START SLAVE is required again.", - router->last_safe_pos, - router->prevbinlog, - router->binlog_name, - 4))); + MXS_WARNING("A transaction is still opened at pos %lu" + " File %s will be truncated. " + "Next binlog file is %s at pos %d, " + "START SLAVE is required again.", + router->last_safe_pos, + router->prevbinlog, + router->binlog_name, + 4); spinlock_acquire(&router->lock); @@ -2983,16 +2947,15 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave) blr_start_master(router); - LOGIF(LM, (skygw_log_write( - LOGFILE_MESSAGE, - "%s: START SLAVE executed by %s@%s. Trying connection to master %s:%d, binlog %s, pos %lu, transaction safe pos %lu", - router->service->name, - slave->dcb->user, - slave->dcb->remote, - router->service->dbref->server->name, - router->service->dbref->server->port, - router->binlog_name, - router->current_pos, router->binlog_position))); + MXS_NOTICE("%s: START SLAVE executed by %s@%s. Trying connection to master %s:%d, " + "binlog %s, pos %lu, transaction safe pos %lu", + router->service->name, + slave->dcb->user, + slave->dcb->remote, + router->service->dbref->server->name, + router->service->dbref->server->port, + router->binlog_name, + router->current_pos, router->binlog_position); /* File path for router cached authentication data */ strcpy(path, router->binlogdir); @@ -3005,10 +2968,8 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave) if (loaded < 0) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error : Unable to load users for service %s", - router->service->name))); + MXS_ERROR("Unable to load users for service %s", + router->service->name); } else { /* update cached data */ if (loaded > 0) @@ -3096,7 +3057,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error if ((cmd_string = strdup(cmd_ptr + 2)) == NULL) { strncpy(error, "error allocating memory for statement parsing", BINLOG_ERROR_MSG_LEN); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error))); + MXS_ERROR("%s: %s", router->service->name, error); return -1; } @@ -3109,7 +3070,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error free(cmd_string); if (parse_ret) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s CHANGE MASTER TO parse error: %s", router->service->name, error))); + MXS_ERROR("%s CHANGE MASTER TO parse error: %s", router->service->name, error); blr_master_free_parsed_options(&change_master); @@ -3121,7 +3082,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error if (!current_master) { strncpy(error, "error allocating memory for blr_master_get_config", BINLOG_ERROR_MSG_LEN); - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error))); + MXS_ERROR("%s: %s", router->service->name, error); blr_master_free_parsed_options(&change_master); @@ -3170,7 +3131,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error strcpy(error, "Router is not configured for master connection, MASTER_LOG_FILE is required"); } - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error))); + MXS_ERROR("%s: %s", router->service->name, error); /* restore previous master_host and master_port */ blr_master_restore_config(router, current_master); @@ -3191,7 +3152,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error /* if errors returned */ if (strlen(error)) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error))); + MXS_ERROR("%s: %s", router->service->name, error); /* restore previous master_host and master_port */ blr_master_restore_config(router, current_master); @@ -3242,7 +3203,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error /* return an error or set new binlog name at pos 4 */ if (return_error) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error))); + MXS_ERROR("%s: %s", router->service->name, error); /* restore previous master_host and master_port */ blr_master_restore_config(router, current_master); @@ -3269,9 +3230,9 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error close(router->binlog_fd); router->binlog_fd = -1; - LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, "%s: New MASTER_LOG_FILE is [%s]", - router->service->name, - router->binlog_name))); + MXS_INFO("%s: New MASTER_LOG_FILE is [%s]", + router->service->name, + router->binlog_name); } } else { /** @@ -3305,7 +3266,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error /* log error and return */ if (return_error) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, "%s: %s", router->service->name, error))); + MXS_ERROR("%s: %s", router->service->name, error); /* restore previous master_host and master_port */ blr_master_restore_config(router, current_master); @@ -3329,27 +3290,31 @@ int blr_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error memset(router->binlog_name, '\0', sizeof(router->binlog_name)); strncpy(router->binlog_name, master_logfile, BINLOG_FNAMELEN); - LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, "%s: New MASTER_LOG_FILE is [%s]", - router->service->name, - router->binlog_name))); + MXS_INFO("%s: New MASTER_LOG_FILE is [%s]", + router->service->name, + router->binlog_name); } - LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, "%s: New MASTER_LOG_POS is [%lu]", - router->service->name, - router->current_pos))); + MXS_INFO("%s: New MASTER_LOG_POS is [%lu]", + router->service->name, + router->current_pos); } } /* Log config changes (without passwords) */ - LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, "%s: 'CHANGE MASTER TO executed'. Previous state MASTER_HOST='%s', MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, MASTER_USER='%s'. New state is MASTER_HOST='%s', MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, MASTER_USER='%s'", - router->service->name, - current_master->host,current_master->port, current_master->logfile, current_master->pos, current_master->user, - router->service->dbref->server->name, - router->service->dbref->server->port, - router->binlog_name, - router->current_pos, - router->user))); + MXS_NOTICE("%s: 'CHANGE MASTER TO executed'. Previous state " + "MASTER_HOST='%s', MASTER_PORT=%i, MASTER_LOG_FILE='%s', " + "MASTER_LOG_POS=%lu, MASTER_USER='%s'. New state is MASTER_HOST='%s', " + "MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, MASTER_USER='%s'", + router->service->name, + current_master->host, current_master->port, current_master->logfile, + current_master->pos, current_master->user, + router->service->dbref->server->name, + router->service->dbref->server->port, + router->binlog_name, + router->current_pos, + router->user); blr_master_free_config(current_master); @@ -3389,9 +3354,9 @@ blr_set_master_hostname(ROUTER_INSTANCE *router, char *hostname) { server_update_address(router->service->dbref->server, ptr); - LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, "%s: New MASTER_HOST is [%s]", - router->service->name, - router->service->dbref->server->name))); + MXS_INFO("%s: New MASTER_HOST is [%s]", + router->service->name, + router->service->dbref->server->name); return 1; } @@ -3418,9 +3383,9 @@ blr_set_master_port(ROUTER_INSTANCE *router, char *port) { if (new_port) { server_update_port(router->service->dbref->server, new_port); - LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, "%s: New MASTER_PORT is [%i]", - router->service->name, - router->service->dbref->server->port))); + MXS_INFO("%s: New MASTER_PORT is [%i]", + router->service->name, + router->service->dbref->server->port); return 1; } @@ -3654,9 +3619,9 @@ blr_set_master_user(ROUTER_INSTANCE *router, char *user) { } router->user = strdup(ptr); - LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, "%s: New MASTER_USER is [%s]", - router->service->name, - router->user))); + MXS_INFO("%s: New MASTER_USER is [%s]", + router->service->name, + router->user); return 1; } @@ -4088,9 +4053,8 @@ char *sep = " ,="; return -1; } else if (strcasecmp(word, "LIKE") == 0) { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Missing LIKE clause in SHOW [GLOBAL] VARIABLES.", - router->service->name))); + MXS_ERROR("%s: Missing LIKE clause in SHOW [GLOBAL] VARIABLES.", + router->service->name); return -1; } else if (strcasecmp(word, "'SERVER_ID'") == 0) { if (router->set_master_server_id) { @@ -4265,9 +4229,8 @@ char *sep = " ,="; return -1; } else if (strcasecmp(word, "LIKE") == 0) { if ((word = strtok_r(NULL, sep, &brkb)) == NULL) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "%s: Missing LIKE clause in SHOW [GLOBAL] STATUS.", - router->service->name))); + MXS_ERROR("%s: Missing LIKE clause in SHOW [GLOBAL] STATUS.", + router->service->name); return -1; } else if (strcasecmp(word, "'Uptime'") == 0) { char uptime[41]=""; @@ -4444,11 +4407,10 @@ time_t t_now = time(0); /* skip servers with state = 0 */ if ( (sptr->state == BLRS_DUMPING) && (sptr->heartbeat > 0) && ((t_now + 1 - sptr->lastReply) >= sptr->heartbeat) ) { - LOGIF(LM, (skygw_log_write( - LOGFILE_MESSAGE, "Sending Heartbeat to slave server-id %d in State %d, cstate %d. " - "Heartbeat interval is %d, last event time is %lu", - sptr->serverid, sptr->state, sptr->cstate, sptr->heartbeat, - (unsigned long)sptr->lastReply))); + MXS_NOTICE("Sending Heartbeat to slave server-id %d. " + "Heartbeat interval is %d, last event time is %lu", + sptr->serverid, sptr->heartbeat, + (unsigned long)sptr->lastReply); blr_slave_send_heartbeat(router, sptr); diff --git a/server/modules/routing/binlog/maxbinlogcheck.c b/server/modules/routing/binlog/maxbinlogcheck.c index 6706c0b65..f6d03ee13 100644 --- a/server/modules/routing/binlog/maxbinlogcheck.c +++ b/server/modules/routing/binlog/maxbinlogcheck.c @@ -129,8 +129,7 @@ int main(int argc, char **argv) { mxs_log_set_priority_enabled(LOG_DEBUG, debug_out); if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Error: Memory allocation failed for ROUTER_INSTANCE"))); + MXS_ERROR("Memory allocation failed for ROUTER_INSTANCE"); mxs_log_flush_sync(); mxs_log_finish(); @@ -152,9 +151,8 @@ int main(int argc, char **argv) { if (fd == -1) { - LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, - "Failed to open binlog file %s: %s", - path, strerror(errno)))); + MXS_ERROR("Failed to open binlog file %s: %s", + path, strerror(errno)); mxs_log_flush_sync(); mxs_log_finish(); @@ -175,14 +173,12 @@ int main(int argc, char **argv) { else strncpy(inst->binlog_name, path, BINLOG_FNAMELEN); - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "maxbinlogcheck %s", binlog_check_version))); + MXS_NOTICE("maxbinlogcheck %s", binlog_check_version); if (fstat(inst->binlog_fd, &statb) == 0) filelen = statb.st_size; - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Checking %s (%s), size %lu bytes", path, inst->binlog_name, filelen))); + MXS_NOTICE("Checking %s (%s), size %lu bytes", path, inst->binlog_name, filelen); /* read binary log */ ret = blr_read_events_all_events(inst, fix_file, debug_out); @@ -191,8 +187,7 @@ int main(int argc, char **argv) { mxs_log_flush_sync(); - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, - "Check retcode: %i, Binlog Pos = %lu", ret, inst->binlog_position))); + MXS_NOTICE("Check retcode: %i, Binlog Pos = %lu", ret, inst->binlog_position); mxs_log_flush_sync(); mxs_log_finish(); diff --git a/server/modules/routing/binlog/test/testbinlog.c b/server/modules/routing/binlog/test/testbinlog.c index 257994351..5ce86066c 100644 --- a/server/modules/routing/binlog/test/testbinlog.c +++ b/server/modules/routing/binlog/test/testbinlog.c @@ -124,8 +124,7 @@ int main(int argc, char **argv) { } if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) { - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Error: Memory allocation FAILED for ROUTER_INSTANCE"))); + MXS_ERROR("Memory allocation FAILED for ROUTER_INSTANCE"); mxs_log_flush_sync(); mxs_log_finish(); @@ -137,7 +136,7 @@ int main(int argc, char **argv) { inst->user = service->credentials.name; inst->password = service->credentials.authdata; - LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, "testbinlog v1.0"))); + MXS_NOTICE("testbinlog v1.0"); if (inst->fileroot == NULL) inst->fileroot = strdup(BINLOG_NAME_ROOT); diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index f69ec3e3b..a02f46c05 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -698,12 +698,12 @@ createInstance(SERVICE *service, char **options) router->rwsplit_config.rw_max_sescmd_history_size = 0; } - /** - * Set default value for max_slave_connections and for slave selection - * criteria. If parameter is set in config file max_slave_connections - * will be overwritten. + /** + * Set default value for max_slave_connections as 100%. This way + * LEAST_CURRENT_OPERATIONS allows us to balance evenly across all the + * configured slaves. */ - router->rwsplit_config.rw_max_slave_conn_count = CONFIG_MAX_SLAVE_CONN; + router->rwsplit_config.rw_max_slave_conn_count = nservers; if (router->rwsplit_config.rw_slave_select_criteria == UNDEFINED_CRITERIA) { @@ -1555,15 +1555,15 @@ void check_drop_tmp_table( if(router_cli_ses == NULL || querybuf == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameters passed: %p %p", - __FUNCTION__,router_cli_ses,querybuf); + MXS_ERROR("[%s] Error: NULL parameters passed: %p %p", + __FUNCTION__,router_cli_ses,querybuf); return; } if(router_cli_ses->rses_master_ref == NULL) { - skygw_log_write(LE,"[%s] Error: Master server reference is NULL.", - __FUNCTION__); + MXS_ERROR("[%s] Error: Master server reference is NULL.", + __FUNCTION__); return; } @@ -1572,9 +1572,9 @@ void check_drop_tmp_table( if(master_dcb == NULL || master_dcb->session == NULL) { - skygw_log_write(LE,"[%s] Error: Master server DBC is NULL. " - "This means that the connection to the master server is already " - "closed while a query is still being routed.",__FUNCTION__); + MXS_ERROR("[%s] Error: Master server DBC is NULL. " + "This means that the connection to the master server is already " + "closed while a query is still being routed.",__FUNCTION__); return; } @@ -1584,7 +1584,7 @@ void check_drop_tmp_table( if(data == NULL) { - skygw_log_write(LE,"[%s] Error: User data in master server DBC is NULL.",__FUNCTION__); + MXS_ERROR("[%s] Error: User data in master server DBC is NULL.",__FUNCTION__); return; } @@ -1646,15 +1646,15 @@ static skygw_query_type_t is_read_tmp_table( if(router_cli_ses == NULL || querybuf == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameters passed: %p %p", - __FUNCTION__,router_cli_ses,querybuf); + MXS_ERROR("[%s] Error: NULL parameters passed: %p %p", + __FUNCTION__,router_cli_ses,querybuf); return type; } if(router_cli_ses->rses_master_ref == NULL) { - skygw_log_write(LE,"[%s] Error: Master server reference is NULL.", - __FUNCTION__); + MXS_ERROR("[%s] Error: Master server reference is NULL.", + __FUNCTION__); return type; } @@ -1663,9 +1663,9 @@ static skygw_query_type_t is_read_tmp_table( if(master_dcb == NULL || master_dcb->session == NULL) { - skygw_log_write(LE,"[%s] Error: Master server DBC is NULL. " - "This means that the connection to the master server is already " - "closed while a query is still being routed.",__FUNCTION__); + MXS_ERROR("[%s] Error: Master server DBC is NULL. " + "This means that the connection to the master server is already " + "closed while a query is still being routed.",__FUNCTION__); return qtype; } CHK_DCB(master_dcb); @@ -1674,7 +1674,7 @@ static skygw_query_type_t is_read_tmp_table( if(data == NULL) { - skygw_log_write(LE,"[%s] Error: User data in master server DBC is NULL.",__FUNCTION__); + MXS_ERROR("[%s] Error: User data in master server DBC is NULL.",__FUNCTION__); return qtype; } @@ -1746,15 +1746,15 @@ static void check_create_tmp_table( if(router_cli_ses == NULL || querybuf == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameters passed: %p %p", - __FUNCTION__,router_cli_ses,querybuf); + MXS_ERROR("[%s] Error: NULL parameters passed: %p %p", + __FUNCTION__,router_cli_ses,querybuf); return; } if(router_cli_ses->rses_master_ref == NULL) { - skygw_log_write(LE,"[%s] Error: Master server reference is NULL.", - __FUNCTION__); + MXS_ERROR("[%s] Error: Master server reference is NULL.", + __FUNCTION__); return; } @@ -1763,9 +1763,9 @@ static void check_create_tmp_table( if(master_dcb == NULL || master_dcb->session == NULL) { - skygw_log_write(LE,"[%s] Error: Master server DCB is NULL. " - "This means that the connection to the master server is already " - "closed while a query is still being routed.",__FUNCTION__); + MXS_ERROR("[%s] Error: Master server DCB is NULL. " + "This means that the connection to the master server is already " + "closed while a query is still being routed.",__FUNCTION__); return; } @@ -1775,7 +1775,7 @@ static void check_create_tmp_table( if(data == NULL) { - skygw_log_write(LE,"[%s] Error: User data in master server DBC is NULL.",__FUNCTION__); + MXS_ERROR("[%s] Error: User data in master server DBC is NULL.",__FUNCTION__); return; } @@ -2099,8 +2099,8 @@ static bool route_single_stmt( packet_type = MYSQL_COM_UNDEFINED; rses->rses_load_active = false; route_target = TARGET_MASTER; - skygw_log_write_flush(LT, "> LOAD DATA LOCAL INFILE finished: " - "%lu bytes sent.", rses->rses_load_data_sent + gwbuf_length(querybuf)); + MXS_INFO("> LOAD DATA LOCAL INFILE finished: " + "%lu bytes sent.", rses->rses_load_data_sent + gwbuf_length(querybuf)); } else { @@ -2230,24 +2230,23 @@ static bool route_single_stmt( char* contentstr = strndup(data, MIN(len, RWSPLIT_TRACE_MSG_LEN)); char* qtypestr = skygw_get_qtype_str(qtype); - skygw_log_write(LOGFILE_TRACE, - "> Autocommit: %s, trx is %s, cmd: %s, type: %s, " - "stmt: %s%s %s", - (rses->rses_autocommit_enabled ? "[enabled]" : "[disabled]"), - (rses->rses_transaction_active ? "[open]" : "[not open]"), - STRPACKETTYPE(ptype), - (qtypestr == NULL ? "N/A" : qtypestr), - contentstr, - (querybuf->hint == NULL ? "" : ", Hint:"), - (querybuf->hint == NULL ? "" : STRHINTTYPE(querybuf->hint->type))); + MXS_INFO("> Autocommit: %s, trx is %s, cmd: %s, type: %s, " + "stmt: %s%s %s", + (rses->rses_autocommit_enabled ? "[enabled]" : "[disabled]"), + (rses->rses_transaction_active ? "[open]" : "[not open]"), + STRPACKETTYPE(ptype), + (qtypestr == NULL ? "N/A" : qtypestr), + contentstr, + (querybuf->hint == NULL ? "" : ", Hint:"), + (querybuf->hint == NULL ? "" : STRHINTTYPE(querybuf->hint->type))); free(contentstr); free(qtypestr); } else { - skygw_log_write(LT, "> Processing LOAD DATA LOCAL INFILE: " - "%lu bytes sent.", rses->rses_load_data_sent); + MXS_INFO("> Processing LOAD DATA LOCAL INFILE: " + "%lu bytes sent.", rses->rses_load_data_sent); } } /** @@ -3014,7 +3013,7 @@ static void bref_clear_state( { if(bref == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return; } if (state != BREF_WAITING_RESULT) @@ -3040,10 +3039,10 @@ static void bref_clear_state( ss_dassert(prev2 > 0); if(prev2 <= 0) { - skygw_log_write(LE,"[%s] Error: negative current operation count in backend %s:%u", - __FUNCTION__, - bref->bref_backend->backend_server->name, - bref->bref_backend->backend_server->port); + MXS_ERROR("[%s] Error: negative current operation count in backend %s:%u", + __FUNCTION__, + bref->bref_backend->backend_server->name, + bref->bref_backend->backend_server->port); } } } @@ -3055,7 +3054,7 @@ static void bref_set_state( { if(bref == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return; } if (state != BREF_WAITING_RESULT) @@ -3072,11 +3071,11 @@ static void bref_set_state( ss_dassert(prev1 >= 0); if(prev1 < 0) { - skygw_log_write(LE,"[%s] Error: negative number of connections waiting for " - "results in backend %s:%u", - __FUNCTION__, - bref->bref_backend->backend_server->name, - bref->bref_backend->backend_server->port); + MXS_ERROR("[%s] Error: negative number of connections waiting for " + "results in backend %s:%u", + __FUNCTION__, + bref->bref_backend->backend_server->name, + bref->bref_backend->backend_server->port); } /** Increase global operation count */ prev2 = atomic_add( @@ -3084,10 +3083,10 @@ static void bref_set_state( ss_dassert(prev2 >= 0); if(prev2 < 0) { - skygw_log_write(LE,"[%s] Error: negative current operation count in backend %s:%u", - __FUNCTION__, - bref->bref_backend->backend_server->name, - bref->bref_backend->backend_server->port); + MXS_ERROR("[%s] Error: negative current operation count in backend %s:%u", + __FUNCTION__, + bref->bref_backend->backend_server->name, + bref->bref_backend->backend_server->port); } } } @@ -3561,7 +3560,7 @@ static rses_property_t* rses_property_init( prop = (rses_property_t*)calloc(1, sizeof(rses_property_t)); if (prop == NULL) { - skygw_log_write(LE,"Error: Malloc returned NULL. (%s:%d)",__FILE__,__LINE__); + MXS_ERROR("Error: Malloc returned NULL. (%s:%d)",__FILE__,__LINE__); return NULL; } prop->rses_prop_type = prop_type; @@ -3582,7 +3581,7 @@ static void rses_property_done( { if(prop == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return; } CHK_RSES_PROP(prop); @@ -3622,12 +3621,12 @@ static int rses_property_add( { if(rses == NULL) { - skygw_log_write(LE,"Error: Router client session is NULL. (%s:%d)",__FILE__,__LINE__); + MXS_ERROR("Router client session is NULL. (%s:%d)",__FILE__,__LINE__); return -1; } if(prop == NULL) { - skygw_log_write(LE,"Error: Router client session property is NULL. (%s:%d)",__FILE__,__LINE__); + MXS_ERROR("Router client session property is NULL. (%s:%d)",__FILE__,__LINE__); return -1; } rses_property_t* p; @@ -3665,7 +3664,7 @@ static mysql_sescmd_t* rses_property_get_sescmd( if(prop == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return NULL; } @@ -3715,7 +3714,7 @@ static void mysql_sescmd_done( { if(sescmd == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return; } CHK_RSES_PROP(sescmd->my_sescmd_prop); @@ -3787,10 +3786,9 @@ static GWBUF* sescmd_cursor_process_replies( if(bref->reply_cmd != scmd->reply_cmd) { - skygw_log_write(LOGFILE_TRACE,"Backend " - "server '%s' response differs from master's response. " - "Closing connection.", - bref->bref_backend->backend_server->unique_name); + MXS_INFO("Backend server '%s' response differs from master's response. " + "Closing connection.", + bref->bref_backend->backend_server->unique_name); sescmd_cursor_set_active(scur,false); bref_clear_state(bref,BREF_QUERY_ACTIVE); bref_clear_state(bref,BREF_IN_USE); @@ -3813,8 +3811,8 @@ static GWBUF* sescmd_cursor_process_replies( /** Mark the rest session commands as replied */ scmd->my_sescmd_is_replied = true; scmd->reply_cmd = *((unsigned char*)replybuf->start + 4); - skygw_log_write(LT,"Master '%s' responded to a session command.", - bref->bref_backend->backend_server->unique_name); + MXS_INFO("Master '%s' responded to a session command.", + bref->bref_backend->backend_server->unique_name); int i; for(i=0;irses_nbackends;i++) @@ -3833,8 +3831,9 @@ static GWBUF* sescmd_cursor_process_replies( if(ses->rses_backend_ref[i].bref_dcb) dcb_close(ses->rses_backend_ref[i].bref_dcb); *reconnect = true; - skygw_log_write(LT,"Disabling slave %s:%d, result differs from master's result. Master: %d Slave: %d", - ses->rses_backend_ref[i].bref_backend->backend_server->name, + MXS_INFO("Disabling slave %s:%d, result differs from " + "master's result. Master: %d Slave: %d", + ses->rses_backend_ref[i].bref_backend->backend_server->name, ses->rses_backend_ref[i].bref_backend->backend_server->port, bref->reply_cmd, ses->rses_backend_ref[i].reply_cmd); @@ -3845,14 +3844,14 @@ static GWBUF* sescmd_cursor_process_replies( } else { - skygw_log_write(LT,"Slave '%s' responded before master to a session command. Result: %d", + MXS_INFO("Slave '%s' responded before master to a session command. Result: %d", bref->bref_backend->backend_server->unique_name, (int)bref->reply_cmd); if(bref->reply_cmd == 0xff) { SERVER* serv = bref->bref_backend->backend_server; - skygw_log_write(LE,"Error: Slave '%s' (%s:%u) failed to execute session command.", - serv->unique_name,serv->name,serv->port); + MXS_ERROR("Slave '%s' (%s:%u) failed to execute session command.", + serv->unique_name,serv->name,serv->port); } if(replybuf) while((replybuf = gwbuf_consume(replybuf,gwbuf_length(replybuf)))); @@ -3904,7 +3903,7 @@ static bool sescmd_cursor_is_active( if(sescmd_cursor == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return false; } ss_dassert(SPINLOCK_IS_LOCKED(&sescmd_cursor->scmd_cur_rses->rses_lock)); @@ -3934,7 +3933,7 @@ static GWBUF* sescmd_cursor_clone_querybuf( GWBUF* buf; if(scur == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return NULL; } ss_dassert(scur->scmd_cur_cmd != NULL); @@ -3952,7 +3951,7 @@ static bool sescmd_cursor_history_empty( if(scur == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return true; } CHK_SESCMD_CUR(scur); @@ -3976,7 +3975,7 @@ static void sescmd_cursor_reset( ROUTER_CLIENT_SES* rses; if(scur == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return; } CHK_SESCMD_CUR(scur); @@ -3997,7 +3996,7 @@ static bool execute_sescmd_history( sescmd_cursor_t* scur; if(bref == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return false; } CHK_BACKEND_REF(bref); @@ -4038,7 +4037,7 @@ static bool execute_sescmd_in_backend( GWBUF* buf; if(backend_ref == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return false; } if (BREF_IS_CLOSED(backend_ref)) @@ -4144,7 +4143,7 @@ static bool sescmd_cursor_next( if(scur == NULL) { - skygw_log_write(LE,"[%s] Error: NULL parameter.",__FUNCTION__); + MXS_ERROR("[%s] Error: NULL parameter.",__FUNCTION__); return false; } @@ -4396,9 +4395,10 @@ static bool route_session_write( 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(LM, "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."); + MXS_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; } @@ -4447,7 +4447,7 @@ static bool route_session_write( */ if((prop = rses_property_init(RSES_PROP_TYPE_SESCMD)) == NULL) { - skygw_log_write(LE,"Error: Router session property initialization failed"); + MXS_ERROR("Router session property initialization failed"); rses_end_locked_router_action(router_cli_ses); return false; } @@ -4456,7 +4456,7 @@ static bool route_session_write( /** Add sescmd property to router client session */ if(rses_property_add(router_cli_ses, prop) != 0) { - skygw_log_write(LE,"Error: Session property addition failed."); + MXS_ERROR("Session property addition failed."); rses_end_locked_router_action(router_cli_ses); return false; } @@ -4584,7 +4584,7 @@ static void rwsplit_process_router_options( { if ((value = strchr(options[i], '=')) == NULL) { - MXS_ERROR("router option \"%s\" for " + MXS_ERROR("Unsupported router option \"%s\" for " "readwritesplit router.", options[i]); } diff --git a/server/modules/routing/webserver.c b/server/modules/routing/webserver.c index af00a4e7b..3b94fa41b 100644 --- a/server/modules/routing/webserver.c +++ b/server/modules/routing/webserver.c @@ -334,8 +334,13 @@ char date[64] = ""; const char *fmt = "%a, %d %b %Y %H:%M:%S GMT"; time_t httpd_current_time = time(NULL); + struct tm tm; + char buffer[32]; // asctime_r documentation requires 26 - strftime(date, sizeof(date), fmt, localtime(&httpd_current_time)); + localtime_r(&http_current_time, &tm); + asctime_r(&tm, buffer); + + strftime(date, sizeof(date), fmt, buffer); dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: text/html\r\n", date, "MaxScale"); diff --git a/utils/skygw_debug.h b/utils/skygw_debug.h index 359d98cdd..7a4a40de6 100644 --- a/utils/skygw_debug.h +++ b/utils/skygw_debug.h @@ -52,14 +52,12 @@ #if defined(SS_DEBUG) && defined(LOG_ASSERT) #include -# define ss_dassert(exp) if(!(exp)){(skygw_log_write(LE,\ - "debug assert %s:%d\n", \ - (char*)__FILE__, \ - __LINE__));mxs_log_flush_sync();assert(exp);} -#define ss_info_dassert(exp,info) if(!(exp)){(skygw_log_write(LE,\ - "debug assert %s:%d %s\n", \ - (char*)__FILE__, \ - __LINE__,info));mxs_log_flush_sync();assert(exp);} +# define ss_dassert(exp) do { if(!(exp)){\ + MXS_ERROR("debug assert %s:%d\n", (char*)__FILE__, __LINE__);\ + mxs_log_flush_sync(); assert(exp);} } while (false) +#define ss_info_dassert(exp,info) do { if(!(exp)){\ + MXS_ERROR("debug assert %s:%d %s\n", (char*)__FILE__, __LINE__, info);\ + mxs_log_flush_sync();assert(exp);} } while (false) # define ss_debug(exp) exp # define ss_dfprintf fprintf # define ss_dfflush fflush diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index a082d1cf8..e04617cad 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -639,7 +639,7 @@ size_t snprint_timestamp( /** Generate timestamp */ t = time(NULL); - tm = *(localtime(&t)); + localtime_r(&t, &tm); snprintf(p_ts, MIN(tslen,timestamp_len), timestamp_formatstr, @@ -687,7 +687,7 @@ size_t snprint_timestamp_hp( /** Generate timestamp */ gettimeofday(&tv,NULL); - tm = *(localtime(&tv.tv_sec)); + localtime_r(&tv.tv_sec, &tm); usec = tv.tv_usec/1000; snprintf(p_ts, MIN(tslen,timestamp_len_hp), @@ -1709,7 +1709,7 @@ static bool file_write_header( t = (time_t *)malloc(sizeof(time_t)); tm = (struct tm *)malloc(sizeof(struct tm)); *t = time(NULL); - *tm = *localtime(t); + localtime_r(t, tm); CHK_FILE(file); header_buf1 = "\n\nMariaDB Corporation MaxScale\t";