From c5870cbaba9f99022238ac44df60fd3ffb79b208 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Thu, 20 Aug 2020 13:04:02 +0300 Subject: [PATCH] MXS-3121 Expose statement currently being classified Intended to be used from fatal signal handlers. As the statement will be returned only while classification is in process, if a statement is returned, it is an indication that the crash was caused by the classification. --- include/maxscale/query_classifier.h | 30 +++++++++++++++++++ .../qc_mysqlembedded/qc_mysqlembedded.cc | 9 +++++- query_classifier/qc_sqlite/qc_sqlite.cc | 17 ++++++++++- server/core/query_classifier.cc | 8 +++++ 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/include/maxscale/query_classifier.h b/include/maxscale/query_classifier.h index 4a5c78751..41c10c98d 100644 --- a/include/maxscale/query_classifier.h +++ b/include/maxscale/query_classifier.h @@ -469,6 +469,19 @@ typedef struct query_classifier * @return QC_RESULT_OK if @c options is valid, otherwise QC_RESULT_ERROR. */ int32_t (* qc_set_options)(uint32_t options); + + /** + * Return statement currently being classified. + * + * @param ppStmp Pointer to pointer that on return will point to the + * statement being classified. + * @param pLen Pointer to value that on return will contain the length + * of the returned string. + * + * @return QC_RESULT_OK if a statement was returned (i.e. a statement is being + * classified), QC_RESULT_ERROR otherwise. + */ + int32_t (* qc_get_current_stmt)(const char** ppStmt, size_t* pLen); } QUERY_CLASSIFIER; /** @@ -996,4 +1009,21 @@ uint32_t qc_get_options(); */ bool qc_set_options(uint32_t options); +/** + * Return statement currently being classified. + * + * @param ppStmp Pointer to pointer that on return will point to the + * statement being classified. + * @param pLen Pointer to value that on return will contain the length + * of the returned string. + * + * @return True, if a statement was returned (i.e. a statement is being + * classified), false otherwise. + * + * @note A string /may/ be returned /only/ when this function is called from + * a signal handler that is called due to the classifier causing + * a crash. + */ +bool qc_get_current_stmt(const char** ppStmt, size_t* pLen); + MXS_END_DECLS diff --git a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc index 4599ed0d2..7fb77fe20 100644 --- a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc +++ b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc @@ -3648,6 +3648,12 @@ int32_t qc_mysql_set_options(uint32_t options) return rv; } +int32_t qc_mysql_get_current_stmt(const char** ppStmt, size_t* pLen) +{ + return QC_RESULT_ERROR; +} + + /** * EXPORTS */ @@ -3684,7 +3690,8 @@ extern "C" nullptr, // qc_info_dup not supported. nullptr, // qc_info_close not supported. qc_mysql_get_options, - qc_mysql_set_options + qc_mysql_set_options, + qc_mysql_get_current_stmt }; static MXS_MODULE info = diff --git a/query_classifier/qc_sqlite/qc_sqlite.cc b/query_classifier/qc_sqlite/qc_sqlite.cc index 864c48683..5ac743ccc 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.cc +++ b/query_classifier/qc_sqlite/qc_sqlite.cc @@ -5359,6 +5359,20 @@ int32_t qc_sqlite_set_options(uint32_t options) return rv; } +int32_t qc_sqlite_get_current_stmt(const char** ppStmt, size_t* pLen) +{ + int32_t rv = QC_RESULT_ERROR; + + if (this_thread.pInfo && this_thread.pInfo->m_pQuery && (this_thread.pInfo->m_nQuery != 0)) + { + *ppStmt = this_thread.pInfo->m_pQuery; + *pLen = this_thread.pInfo->m_nQuery; + rv = QC_RESULT_OK; + } + + return rv; +} + /** * EXPORTS */ @@ -5395,7 +5409,8 @@ extern "C" qc_sqlite_info_dup, qc_sqlite_info_close, qc_sqlite_get_options, - qc_sqlite_set_options + qc_sqlite_set_options, + qc_sqlite_get_current_stmt }; static MXS_MODULE info = diff --git a/server/core/query_classifier.cc b/server/core/query_classifier.cc index 14e9fda2e..425167f60 100644 --- a/server/core/query_classifier.cc +++ b/server/core/query_classifier.cc @@ -1313,6 +1313,14 @@ bool qc_set_options(uint32_t options) return rv == QC_RESULT_OK; } +bool qc_get_current_stmt(const char** ppStmt, size_t* pLen) +{ + QC_TRACE(); + mxb_assert(this_unit.classifier); + + return this_unit.classifier->qc_get_current_stmt(ppStmt, pLen) == QC_RESULT_OK; +} + void qc_get_cache_properties(QC_CACHE_PROPERTIES* properties) { properties->max_size = this_unit.cache_max_size();