From b4d81ffe272dbeeaa5eae00db932c28e2d9f84da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 6 Mar 2017 16:35:17 +0200 Subject: [PATCH 01/20] Use correct capability for schemarouter The router should use RCAP_TYPE_CONTIGUOUS_INPUT as it parses the statements. --- server/modules/routing/schemarouter/schemarouter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/modules/routing/schemarouter/schemarouter.c b/server/modules/routing/schemarouter/schemarouter.c index dc4f9c433..e4beff9d3 100644 --- a/server/modules/routing/schemarouter/schemarouter.c +++ b/server/modules/routing/schemarouter/schemarouter.c @@ -3318,11 +3318,13 @@ static rses_property_t* mysql_sescmd_get_property(mysql_sescmd_t* scmd) } /** - * Return RCAP_TYPE_STMT_INPUT. + * @brief Get router capabilities + * + * @return Always RCAP_TYPE_CONTIGUOUS_INPUT */ static uint64_t getCapabilities(MXS_ROUTER* instance) { - return RCAP_TYPE_STMT_INPUT; + return RCAP_TYPE_CONTIGUOUS_INPUT; } /** From dd07feda07808cf417181bdc8249de8f09fc01c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 6 Mar 2017 20:09:35 +0200 Subject: [PATCH 02/20] MXS-1025: Parse SAVEPOINT statements The various forms of the SAVEPOINT/RELEASE/ROLLBACK statements are now fully parsed. --- query_classifier/qc_sqlite/qc_sqlite.c | 11 +++++++++++ .../qc_sqlite/sqlite-src-3110100/src/parse.y | 19 +++++++++++++++++++ .../sqlite-src-3110100/tool/mkkeywordhash.c | 1 + query_classifier/test/maxscale.test | 9 ++++++++- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/query_classifier/qc_sqlite/qc_sqlite.c b/query_classifier/qc_sqlite/qc_sqlite.c index 71280297c..62f30dbe3 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.c +++ b/query_classifier/qc_sqlite/qc_sqlite.c @@ -1409,6 +1409,17 @@ void mxs_sqlite3Update(Parse* pParse, SrcList* pTabList, ExprList* pChanges, Exp exposed_sqlite3ExprDelete(pParse->db, pWhere); } +void mxs_sqlite3Savepoint(Parse *pParse, int op, Token *pName) +{ + QC_TRACE(); + + QC_SQLITE_INFO* info = this_thread.info; + ss_dassert(info); + + info->status = QC_QUERY_PARSED; + info->types = QUERY_TYPE_WRITE; +} + void maxscaleCollectInfoFromSelect(Parse* pParse, Select* pSelect) { QC_SQLITE_INFO* info = this_thread.info; diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y index 5b9f888f0..3b3b08d49 100644 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y @@ -83,6 +83,7 @@ extern void mxs_sqlite3DropTable(Parse*, SrcList*, int, int, int); extern void mxs_sqlite3EndTable(Parse*, Token*, Token*, u8, Select*, SrcList*); extern void mxs_sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int,ExprList*); extern void mxs_sqlite3RollbackTransaction(Parse*); +extern void mxs_sqlite3Savepoint(Parse *pParse, int op, Token *pName); extern int mxs_sqlite3Select(Parse*, Select*, SelectDest*); extern void mxs_sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); extern void mxs_sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); @@ -318,6 +319,22 @@ cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} %endif +%ifdef MAXSCALE +savepoint_opt ::= SAVEPOINT. +savepoint_opt ::= . +work_opt ::= WORK. +work_opt ::= . +cmd ::= SAVEPOINT nm(X). { + mxs_sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &X); +} +cmd ::= RELEASE savepoint_opt nm(X). { + mxs_sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X); +} +cmd ::= ROLLBACK work_opt TO savepoint_opt nm(X). { + mxs_sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X); +} +%endif +%ifndef MAXSCALE savepoint_opt ::= SAVEPOINT. savepoint_opt ::= . cmd ::= SAVEPOINT nm(X). { @@ -329,6 +346,7 @@ cmd ::= RELEASE savepoint_opt nm(X). { cmd ::= ROLLBACK trans_opt TO savepoint_opt nm(X). { sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X); } +%endif ///////////////////// The CREATE TABLE statement //////////////////////////// // @@ -580,6 +598,7 @@ columnid(A) ::= nm(X). { UNSIGNED VALUE VIEW /*VIRTUAL*/ /*WITH*/ + WORK %endif . %wildcard ANY. diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c b/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c index 5940f1c4d..7a6ce5782 100644 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c @@ -462,6 +462,7 @@ static Keyword aKeywordTable[] = { { "WHEN", "TK_WHEN", ALWAYS }, { "WHERE", "TK_WHERE", ALWAYS }, #ifdef MAXSCALE + { "WORK", "TK_WORK", ALWAYS }, { "WRITE", "TK_WRITE", ALWAYS }, #endif { "ZEROFILL", "TK_ZEROFILL", ALWAYS }, diff --git a/query_classifier/test/maxscale.test b/query_classifier/test/maxscale.test index 48fb14660..3f62a9f7d 100644 --- a/query_classifier/test/maxscale.test +++ b/query_classifier/test/maxscale.test @@ -54,4 +54,11 @@ SET autocommit=true; SET autocommit=FALSE; SET autocommit=Off; -LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE test.t1; \ No newline at end of file +LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE test.t1; + +SAVEPOINT id; +ROLLBACK WORK TO SAVEPOINT id; +ROLLBACK TO SAVEPOINT id; +ROLLBACK WORK TO id; +ROLLBACK TO id; +RELEASE SAVEPOINT id; From 4f8fdca6ae221e8a74df17fca3d3198c26f93ea7 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Tue, 7 Mar 2017 10:17:54 +0200 Subject: [PATCH 03/20] Update version to 2.0.5 --- VERSION.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.cmake b/VERSION.cmake index 0062fcaca..532c10512 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -5,7 +5,7 @@ set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version") set(MAXSCALE_VERSION_MINOR "0" CACHE STRING "Minor version") -set(MAXSCALE_VERSION_PATCH "4" CACHE STRING "Patch version") +set(MAXSCALE_VERSION_PATCH "5" CACHE STRING "Patch version") # This should only be incremented if a package is rebuilt set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number") From 60c69d0f7f461a1773a4e848e87fa3fcc7b0e421 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Tue, 7 Mar 2017 10:21:10 +0200 Subject: [PATCH 04/20] Update change log and release notes for 2.0.5 --- Documentation/Changelog.md | 1 + .../MaxScale-2.0.5-Release-Notes.md | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 Documentation/Release-Notes/MaxScale-2.0.5-Release-Notes.md diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index a1452dc96..821e0ecc4 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -11,6 +11,7 @@ as JSON objects (beta level functionality). For more details, please refer to: +* [MariaDB MaxScale 2.0.5 Release Notes](Release-Notes/MaxScale-2.0.5-Release-Notes.md) * [MariaDB MaxScale 2.0.4 Release Notes](Release-Notes/MaxScale-2.0.4-Release-Notes.md) * [MariaDB MaxScale 2.0.3 Release Notes](Release-Notes/MaxScale-2.0.3-Release-Notes.md) * [MariaDB MaxScale 2.0.2 Release Notes](Release-Notes/MaxScale-2.0.2-Release-Notes.md) diff --git a/Documentation/Release-Notes/MaxScale-2.0.5-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.0.5-Release-Notes.md new file mode 100644 index 000000000..becf7b416 --- /dev/null +++ b/Documentation/Release-Notes/MaxScale-2.0.5-Release-Notes.md @@ -0,0 +1,47 @@ +# MariaDB MaxScale 2.0.5 Release Notes + +Release 2.0.5 is a GA release. + +This document describes the changes in release 2.0.5, when compared to +release [2.0.4](MaxScale-2.0.4-Release-Notes.md). + +If you are upgrading from release 1.4, please also read the following +release notes: +[2.0.4](./MaxScale-2.0.4-Release-Notes.md), +[2.0.3](./MaxScale-2.0.3-Release-Notes.md), +[2.0.2](./MaxScale-2.0.2-Release-Notes.md), +[2.0.1](./MaxScale-2.0.1-Release-Notes.md) and +[2.0.0](./MaxScale-2.0.0-Release-Notes.md). + +For any problems you encounter, please submit a bug report at +[Jira](https://jira.mariadb.org). + +## Bug fixes + +[Here](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.0.5) +is a list of bugs fixed since the release of MaxScale 2.0.4. + +* [MXS-1130](https://jira.mariadb.org/browse/MXS-1130): Unexpected length encoding 'ff' encountered +* [MXS-1123](https://jira.mariadb.org/browse/MXS-1123): connect_timeout setting causes frequent disconnects +* [MXS-1081](https://jira.mariadb.org/browse/MXS-1081): Avro data file corruption +* [MXS-1025](https://jira.mariadb.org/browse/MXS-1025): qc_sqlite always reports " Statement was parsed, but not classified" + +## Known Issues and Limitations + +There are some limitations and known issues within this version of MaxScale. +For more information, please refer to the [Limitations](../About/Limitations.md) document. + +## Packaging + +RPM and Debian packages are provided for the Linux distributions supported +by MariaDB Enterprise. + +Packages can be downloaded [here](https://mariadb.com/resources/downloads). + +## Source Code + +The source code of MaxScale is tagged at GitHub with a tag, which is derived +from the version of MaxScale. For instance, the tag of version `X.Y.Z` of MaxScale +is `maxscale-X.Y.Z`. + +The source code is available [here](https://github.com/mariadb-corporation/MaxScale). From a7379d7ae2baa3fba82ae04a98ea3fa07c5a670f Mon Sep 17 00:00:00 2001 From: Esa Korhonen Date: Mon, 6 Mar 2017 19:10:57 +0200 Subject: [PATCH 05/20] MXS-1165 MaxInfo endless loop If one queried in MySQL MaxInfo 'show sessions' or 'show clients', MaxScale would go in an endless loop and finally crash when memory ran out. The reason is the rather confusing callback-based dcb- iterating code. Adding one line fixes the issue, although the iteration is still rather awkward with calling dcb_foreach for every session/ client. --- server/core/session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server/core/session.c b/server/core/session.c index f4de7b7d7..fff7f9832 100644 --- a/server/core/session.c +++ b/server/core/session.c @@ -769,6 +769,7 @@ sessionRowCallback(RESULTSET *set, void *data) SESSIONFILTER *cbdata = (SESSIONFILTER*)data; RESULT_ROW *row = NULL; + cbdata->current = 0; dcb_foreach(dcb_iter_cb, cbdata); if (cbdata->row) From 07ae37f1799a96ab05d605757def93c86f0cda7c Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Tue, 7 Mar 2017 11:49:30 +0200 Subject: [PATCH 06/20] Update commit/rollback rules Now that WORK is recognized as a parser token, the BEGIN and regular COMMIT and ROLLBACK rules should use them as well. --- .../qc_sqlite/sqlite-src-3110100/src/parse.y | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y index 6fa7afdd9..1f24bbfde 100644 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y @@ -313,10 +313,9 @@ cmdx ::= cmd. { sqlite3FinishCoding(pParse); } // %ifdef MAXSCALE -id_opt ::= . -id_opt ::= deferred_id. - -cmd ::= BEGIN id_opt. {mxs_sqlite3BeginTransaction(pParse, 0);} // BEGIN [WORK] +work_opt ::= WORK. +work_opt ::= . +cmd ::= BEGIN work_opt. {mxs_sqlite3BeginTransaction(pParse, 0);} // BEGIN [WORK] %endif %ifndef MAXSCALE cmd ::= BEGIN transtype(Y) trans_opt. {sqlite3BeginTransaction(pParse, Y);} @@ -330,9 +329,8 @@ transtype(A) ::= IMMEDIATE(X). {A = @X;} transtype(A) ::= EXCLUSIVE(X). {A = @X;} %endif %ifdef MAXSCALE -cmd ::= COMMIT id_opt. {mxs_sqlite3CommitTransaction(pParse);} -cmd ::= END id_opt. {mxs_sqlite3CommitTransaction(pParse);} -cmd ::= ROLLBACK id_opt. {mxs_sqlite3RollbackTransaction(pParse);} +cmd ::= COMMIT work_opt. {mxs_sqlite3CommitTransaction(pParse);} +cmd ::= ROLLBACK work_opt. {mxs_sqlite3RollbackTransaction(pParse);} %endif %ifndef MAXSCALE cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);} @@ -343,8 +341,6 @@ cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} %ifdef MAXSCALE savepoint_opt ::= SAVEPOINT. savepoint_opt ::= . -work_opt ::= WORK. -work_opt ::= . cmd ::= SAVEPOINT nm(X). { mxs_sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &X); } From e1da03ff210bdc3e6e651bd80cc3e4199ba655af Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Tue, 7 Mar 2017 13:06:07 +0200 Subject: [PATCH 07/20] Update version for 2.1.1 --- VERSION.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.cmake b/VERSION.cmake index 94e21be5a..8fb2cfc9c 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -5,7 +5,7 @@ set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version") set(MAXSCALE_VERSION_MINOR "1" CACHE STRING "Minor version") -set(MAXSCALE_VERSION_PATCH "0" CACHE STRING "Patch version") +set(MAXSCALE_VERSION_PATCH "1" CACHE STRING "Patch version") # This should only be incremented if a package is rebuilt set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number") From b1521e054521dfc1ae114ce72af98ed08cc41bf9 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Tue, 7 Mar 2017 15:45:29 +0200 Subject: [PATCH 08/20] Log the use of prepared statements If cache decisions should be logged, we log the presence of prepared statements as they currently are the primary source for the cache not caching. --- server/modules/filter/cache/cachefiltersession.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/modules/filter/cache/cachefiltersession.cc b/server/modules/filter/cache/cachefiltersession.cc index d1612293d..4d120002d 100644 --- a/server/modules/filter/cache/cachefiltersession.cc +++ b/server/modules/filter/cache/cachefiltersession.cc @@ -232,6 +232,20 @@ int CacheFilterSession::routeQuery(GWBUF* pPacket) } break; + case MYSQL_COM_STMT_PREPARE: + if (log_decisions()) + { + MXS_NOTICE("MYSQL_COM_STMT_PREPARE, ignoring."); + } + break; + + case MYSQL_COM_STMT_EXECUTE: + if (log_decisions()) + { + MXS_NOTICE("MYSQL_COM_STMT_EXECUTE, ignoring."); + } + break; + case MYSQL_COM_QUERY: if (should_consult_cache(pPacket)) { From 5c0ec3e3564b3653b58ef2e868364ae35a552c42 Mon Sep 17 00:00:00 2001 From: Esa Korhonen Date: Wed, 8 Mar 2017 09:50:53 +0200 Subject: [PATCH 09/20] Make hint.c/hint.h const correct Not a rigorous pass, just added const to the more obvious places. --- include/maxscale/hint.h | 12 ++++++------ server/core/hint.c | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/maxscale/hint.h b/include/maxscale/hint.h index 926649889..d91c3523a 100644 --- a/include/maxscale/hint.h +++ b/include/maxscale/hint.h @@ -50,11 +50,11 @@ typedef struct hint struct hint *next; /*< Another hint for this buffer */ } HINT; -extern HINT *hint_alloc(HINT_TYPE, void *, unsigned int); -extern HINT *hint_create_parameter(HINT *, char *, char *); -extern HINT *hint_create_route(HINT *, HINT_TYPE, char *); -extern void hint_free(HINT *); -extern HINT *hint_dup(HINT *); -bool hint_exists(HINT **, HINT_TYPE); +HINT *hint_alloc(HINT_TYPE, void *, unsigned int); +HINT *hint_create_parameter(HINT *, char *, const char *); +HINT *hint_create_route(HINT *, HINT_TYPE, const char *); +void hint_free(HINT *); +HINT *hint_dup(const HINT *); +bool hint_exists(HINT **, HINT_TYPE); MXS_END_DECLS diff --git a/server/core/hint.c b/server/core/hint.c index a72506903..dcb290f2b 100644 --- a/server/core/hint.c +++ b/server/core/hint.c @@ -38,11 +38,11 @@ * Note : Optimize this to use version numbering instead of copying memory */ HINT * -hint_dup(HINT *hint) +hint_dup(const HINT *hint) { - HINT *nlhead = NULL, *nltail = NULL, *ptr1, *ptr2; + const HINT *ptr1 = hint; + HINT *nlhead = NULL, *nltail = NULL, *ptr2; - ptr1 = hint; while (ptr1) { if ((ptr2 = (HINT *)MXS_MALLOC(sizeof(HINT))) == NULL) @@ -91,7 +91,7 @@ hint_dup(HINT *hint) * @return The result hint list */ HINT * -hint_create_route(HINT *head, HINT_TYPE type, char *data) +hint_create_route(HINT *head, HINT_TYPE type, const char *data) { HINT *hint; @@ -122,7 +122,7 @@ hint_create_route(HINT *head, HINT_TYPE type, char *data) * @return The result hint list */ HINT * -hint_create_parameter(HINT *head, char *pname, char *value) +hint_create_parameter(HINT *head, char *pname, const char *value) { HINT *hint; From 25350d6a080d30730a4f89c1a92a9e0ffe29e39a Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Wed, 8 Mar 2017 13:17:17 +0200 Subject: [PATCH 10/20] Update change log and release notes --- Documentation/Changelog.md | 5 +++ .../MaxScale-2.1.1-Release-Notes.md | 37 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index a063e96fb..eb6d1760f 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -14,8 +14,13 @@ * Named Server Filter now supports wildcards for source option. * Binlog Server can now be configured to encrypt binlog files. * New filters, _cache_, _ccrfilter_, _insertstream_, _masking_, and _maxrows_ are introduced. +* GSSAPI based authentication can be used +* Prepared statements are now in the database firewall filtered exactly like non-prepared + statements. +* The firewall filter can now filter based on function usage. For more details, please refer to: +* [MariaDB MaxScale 2.1.1 Release Notes](Release-Notes/MaxScale-2.1.1-Release-Notes.md) * [MariaDB MaxScale 2.1.0 Release Notes](Release-Notes/MaxScale-2.1.0-Release-Notes.md) ## MariaDB MaxScale 2.0 diff --git a/Documentation/Release-Notes/MaxScale-2.1.1-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.1.1-Release-Notes.md index 540f0b5a4..39d65b1a6 100644 --- a/Documentation/Release-Notes/MaxScale-2.1.1-Release-Notes.md +++ b/Documentation/Release-Notes/MaxScale-2.1.1-Release-Notes.md @@ -3,7 +3,11 @@ Release 2.1.1 is a Beta release. This document describes the changes in release 2.1.1, when compared to -release 2.1.0. +release [2.1.0](MaxScale-2.1.0-Release-Notes.md). + +If you are upgrading from release 2.0, please also read the following +release notes: +[2.1.0](./MaxScale-2.1.0-Release-Notes.md) For any problems you encounter, please consider submitting a bug report at [Jira](https://jira.mariadb.org). @@ -12,9 +16,20 @@ report at [Jira](https://jira.mariadb.org). ### Cache -The cache will now _also_ be used and populated in a transaction that is +* The cache will now _also_ be used and populated in a transaction that is _not_ explicitly read only, but only until the first statement that modifies the database is encountered. +* SELECT statements that refer to user or system variables are not cached. +* SELECT statements using functions whose result depend upon the current +user or context are not cached. Examples of such functions are `USER()`, +`RAND()` or `CURRENT_TIME()`. + +### Firewall Filter + +* Prepared statements are now treated exactly like non-prepared statements. +* Statements can now be accepted/rejected based upon function usage. + +*NOTE* Both of these features were available already in _2.1.0_. ## Dropped Features @@ -43,14 +58,28 @@ after a failover has been triggered. This makes it possible for external actors to recover the failed nodes without having to manually clear the maintenance mode. -For more information about the failover mode and how it works, read the +For more information about the failover mode and how it works, please read the [MySQL Monitor](../Monitors/MySQL-Monitor.md) documentation. +### GSSAPI + +_GASSAPI_ based authentication can now be used with MaxScale. + +For more information, please read the +[GSSAPI Authentication](../Authenticators/GSSAPI-Authenticator.md) documentation. + +NOTE This feature was available already in _2.1.0_. + ## Bug fixes [Here is a list of bugs fixed since the release of MaxScale 2.1.0.](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20resolution%20in%20(Fixed%2C%20Done)%20AND%20fixVersion%20%3D%202.1.1%20AND%20fixVersion%20NOT%20IN%20(2.1.0)) -* +* [MXS-1165](https://jira.mariadb.org/browse/MXS-1165) MaxInfo eat too much memory when getting list of session and client. +* [MXS-1143](https://jira.mariadb.org/browse/MXS-1143) Add support for new MariaDB 10.2 flags +* [MXS-1130](https://jira.mariadb.org/browse/MXS-1130) Unexpected length encoding 'ff' encountered +* [MXS-1081](https://jira.mariadb.org/browse/MXS-1081) Avro data file corruption +* [MXS-1077](https://jira.mariadb.org/browse/MXS-1077) Resource Leak +* [MXS-759](https://jira.mariadb.org/browse/MXS-759) Starting MaxScale from command line fails on CentOS 7 ## Known Issues and Limitations From 59754224738b04d362d26766dd32dba8a288fe51 Mon Sep 17 00:00:00 2001 From: Esa Korhonen Date: Thu, 2 Mar 2017 16:31:19 +0200 Subject: [PATCH 11/20] Change namedserverfilter to C++, reorder code, cleanup Functionality unchanged. --- .../filter/namedserverfilter/CMakeLists.txt | 2 +- ...edserverfilter.c => namedserverfilter.cpp} | 198 +++++++++--------- 2 files changed, 103 insertions(+), 97 deletions(-) rename server/modules/filter/namedserverfilter/{namedserverfilter.c => namedserverfilter.cpp} (95%) diff --git a/server/modules/filter/namedserverfilter/CMakeLists.txt b/server/modules/filter/namedserverfilter/CMakeLists.txt index bff955b19..890cda94d 100644 --- a/server/modules/filter/namedserverfilter/CMakeLists.txt +++ b/server/modules/filter/namedserverfilter/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(namedserverfilter SHARED namedserverfilter.c) +add_library(namedserverfilter SHARED namedserverfilter.cpp) target_link_libraries(namedserverfilter maxscale-common) set_target_properties(namedserverfilter PROPERTIES VERSION "1.1.0") install_module(namedserverfilter core) diff --git a/server/modules/filter/namedserverfilter/namedserverfilter.c b/server/modules/filter/namedserverfilter/namedserverfilter.cpp similarity index 95% rename from server/modules/filter/namedserverfilter/namedserverfilter.c rename to server/modules/filter/namedserverfilter/namedserverfilter.cpp index 6d2f6e864..112c8a7f5 100644 --- a/server/modules/filter/namedserverfilter/namedserverfilter.c +++ b/server/modules/filter/namedserverfilter/namedserverfilter.cpp @@ -11,23 +11,10 @@ * Public License. */ -#define MXS_MODULE_NAME "namedserverfilter" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - /** - * @file namedserverfilter.c - a very simple regular expression based filter - * that routes to a named server if a regular expression match is found. + * @file namedserverfilter.cpp - a very simple regular expression based filter + * that routes to a named server or server type if a regular expression match + * is found. * @verbatim * * A simple regular expression based query routing filter. @@ -38,19 +25,24 @@ * source= * user= * - * Date Who Description - * 22/01/2015 Mark Riddoch Written as example based on regex filter * @endverbatim */ -static MXS_FILTER *createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params); -static MXS_FILTER_SESSION *newSession(MXS_FILTER *instance, MXS_SESSION *session); -static void closeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session); -static void freeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session); -static void setDownstream(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, MXS_DOWNSTREAM *downstream); -static int routeQuery(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, GWBUF *queue); -static void diagnostic(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb); -static uint64_t getCapabilities(MXS_FILTER* instance); +#define MXS_MODULE_NAME "regexhintfilter" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include typedef struct source_host { @@ -71,15 +63,8 @@ typedef struct regex_t re; /* Compiled regex text */ } REGEXHINT_INSTANCE; -static bool validate_ip_address(const char *); -static int check_source_host(REGEXHINT_INSTANCE *, - const char *, - const struct sockaddr_in *); -static REGEXHINT_SOURCE_HOST *set_source_address(const char *); -static void free_instance(REGEXHINT_INSTANCE *); - /** - * The session structuee for this regex filter + * The session structure for this regexhint filter */ typedef struct { @@ -89,6 +74,24 @@ typedef struct int active; /* Is filter active */ } REGEXHINT_SESSION; +/* Api entrypoints */ +static MXS_FILTER *createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params); +static MXS_FILTER_SESSION *newSession(MXS_FILTER *instance, MXS_SESSION *session); +static void closeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session); +static void freeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session); +static void setDownstream(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, MXS_DOWNSTREAM *downstream); +static int routeQuery(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, GWBUF *queue); +static void diagnostic(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb); +static uint64_t getCapabilities(MXS_FILTER* instance); +/* End entrypoints */ + +static bool validate_ip_address(const char *); +static int check_source_host(REGEXHINT_INSTANCE *, + const char *, + const struct sockaddr_in *); +static REGEXHINT_SOURCE_HOST *set_source_address(const char *); +static void free_instance(REGEXHINT_INSTANCE *); + static const MXS_ENUM_VALUE option_values[] = { {"ignorecase", REG_ICASE}, @@ -97,62 +100,6 @@ static const MXS_ENUM_VALUE option_values[] = {NULL} }; -/** - * The module entry point routine. It is this routine that - * must populate the structure that is referred to as the - * "module object", this is a structure with the set of - * external entry points for this module. - * - * @return The module object - */ -MXS_MODULE* MXS_CREATE_MODULE() -{ - static MXS_FILTER_OBJECT MyObject = - { - createInstance, - newSession, - closeSession, - freeSession, - setDownstream, - NULL, // No Upstream requirement - routeQuery, - NULL, // No clientReply - diagnostic, - getCapabilities, - NULL, // No destroyInstance - }; - - static MXS_MODULE info = - { - MXS_MODULE_API_FILTER, - MXS_MODULE_GA, - MXS_FILTER_VERSION, - "A routing hint filter that uses regular expressions to direct queries", - "V1.1.0", - &MyObject, - NULL, /* Process init. */ - NULL, /* Process finish. */ - NULL, /* Thread init. */ - NULL, /* Thread finish. */ - { - {"match", MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED}, - {"server", MXS_MODULE_PARAM_SERVER, NULL, MXS_MODULE_OPT_REQUIRED}, - {"source", MXS_MODULE_PARAM_STRING}, - {"user", MXS_MODULE_PARAM_STRING}, - { - "options", - MXS_MODULE_PARAM_ENUM, - "ignorecase", - MXS_MODULE_OPT_NONE, - option_values - }, - {MXS_END_MODULE_PARAMS} - } - }; - - return &info; -} - /** * Create an instance of the filter for a particular service * within MaxScale. @@ -166,7 +113,8 @@ MXS_MODULE* MXS_CREATE_MODULE() static MXS_FILTER * createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params) { - REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE*)MXS_CALLOC(1, sizeof(REGEXHINT_INSTANCE)); + REGEXHINT_INSTANCE *my_instance = + (REGEXHINT_INSTANCE*)MXS_CALLOC(1, sizeof(REGEXHINT_INSTANCE)); if (my_instance) { @@ -224,7 +172,7 @@ newSession(MXS_FILTER *instance, MXS_SESSION *session) REGEXHINT_SESSION *my_session; const char *remote, *user; - if ((my_session = MXS_CALLOC(1, sizeof(REGEXHINT_SESSION))) != NULL) + if ((my_session = (REGEXHINT_SESSION*)MXS_CALLOC(1, sizeof(REGEXHINT_SESSION))) != NULL) { my_session->n_diverted = 0; my_session->n_undiverted = 0; @@ -507,14 +455,15 @@ static REGEXHINT_SOURCE_HOST *set_source_address(const char *input_host) int netmask = 32; int bytes = 0; struct sockaddr_in serv_addr; - REGEXHINT_SOURCE_HOST *source_host = MXS_CALLOC(1, sizeof(REGEXHINT_SOURCE_HOST)); + REGEXHINT_SOURCE_HOST *source_host = + (REGEXHINT_SOURCE_HOST*)MXS_CALLOC(1, sizeof(REGEXHINT_SOURCE_HOST)); if (!input_host || !source_host) { return NULL; } - if(!validate_ip_address(input_host)) + if (!validate_ip_address(input_host)) { MXS_WARNING("The given 'source' parameter source=%s" " is not a valid IP address: it will not be used.", @@ -554,11 +503,11 @@ static REGEXHINT_SOURCE_HOST *set_source_address(const char *input_host) } else { - *out++ = *p++; + *out++ = *p++; } } - *out ='\0'; + *out = '\0'; source_host->netmask = netmask; /* fill IPv4 data struct */ @@ -605,3 +554,60 @@ static void free_instance(REGEXHINT_INSTANCE *instance) MXS_FREE(instance->user); MXS_FREE(instance); } + + +/** + * The module entry point routine. It is this routine that + * must populate the structure that is referred to as the + * "module object", this is a structure with the set of + * external entry points for this module. + * + * @return The module object + */ +extern "C" MXS_MODULE* MXS_CREATE_MODULE() +{ + static MXS_FILTER_OBJECT MyObject = + { + createInstance, + newSession, + closeSession, + freeSession, + setDownstream, + NULL, // No Upstream requirement + routeQuery, + NULL, // No clientReply + diagnostic, + getCapabilities, + NULL, // No destroyInstance + }; + + static MXS_MODULE info = + { + MXS_MODULE_API_FILTER, + MXS_MODULE_GA, + MXS_FILTER_VERSION, + "A routing hint filter that uses regular expressions to direct queries", + "V1.1.0", + &MyObject, + NULL, /* Process init. */ + NULL, /* Process finish. */ + NULL, /* Thread init. */ + NULL, /* Thread finish. */ + { + {"match", MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED}, + {"server", MXS_MODULE_PARAM_SERVER, NULL, MXS_MODULE_OPT_REQUIRED}, + {"source", MXS_MODULE_PARAM_STRING}, + {"user", MXS_MODULE_PARAM_STRING}, + { + "options", + MXS_MODULE_PARAM_ENUM, + "ignorecase", + MXS_MODULE_OPT_NONE, + option_values + }, + {MXS_END_MODULE_PARAMS} + } + }; + + return &info; +} \ No newline at end of file From 55f038bc1ff62837f04d47c21b5d1989733dca2b Mon Sep 17 00:00:00 2001 From: Esa Korhonen Date: Fri, 3 Mar 2017 09:39:14 +0200 Subject: [PATCH 12/20] RegexHintFilter (namedserverfilter) now uses PCRE2 Also, changed the Filter struct to a class and moved code to class methods. Renamed to .cc. Modifications in progress. --- .../filter/namedserverfilter/CMakeLists.txt | 2 +- ...dserverfilter.cpp => namedserverfilter.cc} | 350 +++++++++++------- 2 files changed, 211 insertions(+), 141 deletions(-) rename server/modules/filter/namedserverfilter/{namedserverfilter.cpp => namedserverfilter.cc} (71%) diff --git a/server/modules/filter/namedserverfilter/CMakeLists.txt b/server/modules/filter/namedserverfilter/CMakeLists.txt index 890cda94d..1c253dc51 100644 --- a/server/modules/filter/namedserverfilter/CMakeLists.txt +++ b/server/modules/filter/namedserverfilter/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(namedserverfilter SHARED namedserverfilter.cpp) +add_library(namedserverfilter SHARED namedserverfilter.cc) target_link_libraries(namedserverfilter maxscale-common) set_target_properties(namedserverfilter PROPERTIES VERSION "1.1.0") install_module(namedserverfilter core) diff --git a/server/modules/filter/namedserverfilter/namedserverfilter.cpp b/server/modules/filter/namedserverfilter/namedserverfilter.cc similarity index 71% rename from server/modules/filter/namedserverfilter/namedserverfilter.cpp rename to server/modules/filter/namedserverfilter/namedserverfilter.cc index 112c8a7f5..50d0ac273 100644 --- a/server/modules/filter/namedserverfilter/namedserverfilter.cpp +++ b/server/modules/filter/namedserverfilter/namedserverfilter.cc @@ -12,7 +12,7 @@ */ /** - * @file namedserverfilter.cpp - a very simple regular expression based filter + * @file namedserverfilter.cc - a very simple regular expression based filter * that routes to a named server or server type if a regular expression match * is found. * @verbatim @@ -28,12 +28,11 @@ * @endverbatim */ -#define MXS_MODULE_NAME "regexhintfilter" +#define MXS_MODULE_NAME "RegexHintFilter" #include #include -#include #include #include @@ -42,7 +41,14 @@ #include #include #include +#include #include +#include + +using std::string; + +class RegexHintInst; +struct RegexHintSess_t; typedef struct source_host { @@ -54,25 +60,34 @@ typedef struct source_host /** * Instance structure */ -typedef struct +class RegexHintInst : public MXS_FILTER { +public: // will change to private later + string match; /* Regular expression to match */ + string server; /* Server to route to */ + string user; /* User name to restrict matches */ + REGEXHINT_SOURCE_HOST *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 */ - regex_t re; /* Compiled regex text */ -} REGEXHINT_INSTANCE; + pcre2_code* re; /* Compiled regex text */ + + RegexHintInst(string match, string server, string user, REGEXHINT_SOURCE_HOST* source, + pcre2_code* regex); + ~RegexHintInst(); + RegexHintSess_t* newSession(MXS_SESSION *session); + int routeQuery(RegexHintSess_t* session, GWBUF *queue); + void diagnostic(RegexHintSess_t* session, DCB *dcb); +}; /** * The session structure for this regexhint filter */ -typedef struct +typedef struct RegexHintSess_t { MXS_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; +} RegexHintSess; /* Api entrypoints */ static MXS_FILTER *createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params); @@ -86,20 +101,125 @@ static uint64_t getCapabilities(MXS_FILTER* instance); /* End entrypoints */ static bool validate_ip_address(const char *); -static int check_source_host(REGEXHINT_INSTANCE *, +static int check_source_host(RegexHintInst *, const char *, const struct sockaddr_in *); static REGEXHINT_SOURCE_HOST *set_source_address(const char *); -static void free_instance(REGEXHINT_INSTANCE *); +static void free_instance(RegexHintInst *); static const MXS_ENUM_VALUE option_values[] = { - {"ignorecase", REG_ICASE}, + {"ignorecase", PCRE2_CASELESS}, {"case", 0}, - {"extended", REG_EXTENDED}, + {"extended", PCRE2_EXTENDED}, // Ignore white space and # comments {NULL} }; +RegexHintInst::RegexHintInst(string match, string server, string user, + REGEXHINT_SOURCE_HOST* source, pcre2_code* regex) + : match(match), + server(server), + user(user), + source(source), + re(regex) +{} +RegexHintInst::~RegexHintInst() +{ + if (re) + { + pcre2_code_free(re); + } + if (source) + { + MXS_FREE(source); + } +} + +RegexHintSess_t* RegexHintInst::newSession(MXS_SESSION *session) +{ + RegexHintSess *my_session; + const char *remote, *user; + + if ((my_session = (RegexHintSess*)MXS_CALLOC(1, sizeof(RegexHintSess))) != NULL) + { + my_session->n_diverted = 0; + my_session->n_undiverted = 0; + my_session->active = 1; + + /* Check client IP against 'source' host option */ + if (this->source && this->source->address && + (remote = session_get_remote(session)) != NULL) + { + my_session->active = + check_source_host(this, remote, &session->client_dcb->ipv4); + } + + /* Check client user against 'user' option */ + if (this->user.length() && + (user = session_get_user(session)) && + strcmp(user, this->user.c_str())) + { + my_session->active = 0; + } + } + return my_session; +} + +int RegexHintInst::routeQuery(RegexHintSess_t* my_session, GWBUF *queue) +{ + char *sql; + + if (modutil_is_SQL(queue) && my_session->active) + { + if ((sql = modutil_get_SQL(queue)) != NULL) + { + int result = pcre2_match(this->re, (PCRE2_SPTR)sql, + 0, 0, 0, + NULL, NULL); + if (result == 0) + { + // Change hint_create_route() to take a const char* to remove copying. + char* zServer = MXS_STRDUP_A(this->server.c_str()); + queue->hint = + hint_create_route(queue->hint, HINT_ROUTE_TO_NAMED_SERVER, + zServer); + my_session->n_diverted++; + } + else + { + my_session->n_undiverted++; + } + MXS_FREE(sql); + } + } + return my_session->down.routeQuery(my_session->down.instance, + my_session->down.session, queue); +} + +void RegexHintInst::diagnostic(RegexHintSess_t* my_session, DCB *dcb) +{ + dcb_printf(dcb, "\t\tMatch and route: /%s/ -> %s\n", + match.c_str(), server.c_str()); + 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 (source) + { + dcb_printf(dcb, + "\t\tReplacement limited to connections from %s\n", + source->address); + } + if (user.length()) + { + dcb_printf(dcb, + "\t\tReplacement limit to user %s\n", + user.c_str()); + } +} /** * Create an instance of the filter for a particular service * within MaxScale. @@ -110,54 +230,77 @@ static const MXS_ENUM_VALUE option_values[] = * * @return The instance data for this new instance */ -static MXS_FILTER * +static MXS_FILTER* createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params) { - REGEXHINT_INSTANCE *my_instance = - (REGEXHINT_INSTANCE*)MXS_CALLOC(1, sizeof(REGEXHINT_INSTANCE)); + bool error = false; - if (my_instance) + REGEXHINT_SOURCE_HOST* source = NULL; + /* The cfg_param cannot be changed to string because set_source_address doesn't + copy the contents. */ + const char *cfg_param = config_get_string(params, "source"); + if (*cfg_param) { - REGEXHINT_SOURCE_HOST *source = NULL; - const char *cfg_param = config_get_string(params, "source"); - if (*cfg_param) + source = set_source_address(cfg_param); + if (!source) { - my_instance->source = set_source_address(cfg_param); - if (!my_instance->source) - { - MXS_ERROR("Failure setting 'source' from %s", - cfg_param); - - free_instance(my_instance); - my_instance = NULL; - return (MXS_FILTER *)my_instance; - } - } - - my_instance->match = MXS_STRDUP_A(config_get_string(params, "match")); - my_instance->server = MXS_STRDUP_A(config_get_string(params, "server")); - my_instance->user = config_copy_string(params, "user"); - bool error = false; - int cflags = config_get_enum(params, "options", option_values); - - if (regcomp(&my_instance->re, my_instance->match, cflags)) - { - MXS_ERROR("Invalid regular expression '%s'.", my_instance->match); - MXS_FREE(my_instance->match); - my_instance->match = NULL; + MXS_ERROR("Failure setting 'source' from %s", cfg_param); error = true; } - - if (error) - { - free_instance(my_instance); - my_instance = NULL; - } } - return (MXS_FILTER *) my_instance; + string match(config_get_string(params, "match")); + string server(config_get_string(params, "server")); + string user(config_get_string(params, "user")); + + int cflags = config_get_enum(params, "options", option_values); + int errorcode = -1; + PCRE2_SIZE error_offset = -1; + pcre2_code* regex = + pcre2_compile((PCRE2_SPTR) match.c_str(), PCRE2_ZERO_TERMINATED, cflags, + &errorcode, &error_offset, NULL); + + if (!regex) + { + error = true; + + char errorbuf[100]; //How long should this be?? + int err_msg_rval = pcre2_get_error_message(errorcode, (PCRE2_UCHAR*)errorbuf, + sizeof(errorbuf)); + MXS_ERROR("Invalid PCRE2 regular expression '%s' at position '%zu'.", + match.c_str(), error_offset); + MXS_ERROR("PCRE2 Error message: '%s'.", errorbuf); + if (err_msg_rval == PCRE2_ERROR_NOMEMORY) + { + MXS_ERROR("PCRE2 error buffer was too small to contain the complete" + "message."); + } + } + + if (error) + { + if (source) + { + MXS_FREE(source); + } + if (regex) + { + pcre2_code_free(regex); + } + return NULL; + } + else + { + RegexHintInst* instance = NULL; + MXS_EXCEPTION_GUARD(instance = + new RegexHintInst(match, server, user, source, regex)); + return instance; + } + } + + /** * Associate a new session with this instance of the filter. * @@ -168,34 +311,9 @@ createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params) static MXS_FILTER_SESSION * newSession(MXS_FILTER *instance, MXS_SESSION *session) { - REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance; - REGEXHINT_SESSION *my_session; - const char *remote, *user; - - if ((my_session = (REGEXHINT_SESSION*)MXS_CALLOC(1, sizeof(REGEXHINT_SESSION))) != NULL) - { - my_session->n_diverted = 0; - my_session->n_undiverted = 0; - my_session->active = 1; - - /* Check client IP against 'source' host option */ - if (my_instance->source && - my_instance->source->address && - (remote = session_get_remote(session)) != NULL) - { - my_session->active = check_source_host(my_instance, - remote, - &session->client_dcb->ipv4); - } - - /* Check client user against 'user' option */ - if (my_instance->user && (user = session_get_user(session)) - && strcmp(user, my_instance->user)) - { - my_session->active = 0; - } - } - + RegexHintInst* my_instance = static_cast(instance); + RegexHintSess* my_session = NULL; + MXS_EXCEPTION_GUARD(my_session = my_instance->newSession(session)); return (MXS_FILTER_SESSION*)my_session; } @@ -234,7 +352,7 @@ freeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session) static void setDownstream(MXS_FILTER *instance, MXS_FILTER_SESSION *session, MXS_DOWNSTREAM *downstream) { - REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) session; + RegexHintSess *my_session = (RegexHintSess *) session; my_session->down = *downstream; } @@ -255,30 +373,11 @@ setDownstream(MXS_FILTER *instance, MXS_FILTER_SESSION *session, MXS_DOWNSTREAM static int routeQuery(MXS_FILTER *instance, MXS_FILTER_SESSION *session, GWBUF *queue) { - REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance; - REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) session; - char *sql; - - if (modutil_is_SQL(queue) && my_session->active) - { - 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++; - } - MXS_FREE(sql); - } - } - return my_session->down.routeQuery(my_session->down.instance, - my_session->down.session, queue); + RegexHintInst *my_instance = static_cast(instance); + RegexHintSess *my_session = (RegexHintSess *) session; + int rval = 0; + MXS_EXCEPTION_GUARD(rval = my_instance->routeQuery(my_session, queue)); + return rval; } /** @@ -295,30 +394,10 @@ routeQuery(MXS_FILTER *instance, MXS_FILTER_SESSION *session, GWBUF *queue) static void diagnostic(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb) { - REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance; - REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) fsession; + RegexHintInst *my_instance = static_cast(instance); + RegexHintSess *my_session = (RegexHintSess *) 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->address); - } - if (my_instance->user) - { - dcb_printf(dcb, - "\t\tReplacement limit to user %s\n", - my_instance->user); - } } /** @@ -392,7 +471,7 @@ static bool validate_ip_address(const char *host) * @param ipv4 The client IPv4 struct * @return 1 for match, 0 otherwise */ -static int check_source_host(REGEXHINT_INSTANCE *instance, +static int check_source_host(RegexHintInst *instance, const char *remote, const struct sockaddr_in *ipv4) { @@ -541,18 +620,9 @@ static REGEXHINT_SOURCE_HOST *set_source_address(const char *input_host) * * @param instance The filter instance */ -static void free_instance(REGEXHINT_INSTANCE *instance) +static void free_instance(RegexHintInst *instance) { - if (instance->match) - { - regfree(&instance->re); - MXS_FREE(instance->match); - } - - MXS_FREE(instance->server); - MXS_FREE(instance->source); - MXS_FREE(instance->user); - MXS_FREE(instance); + MXS_EXCEPTION_GUARD(delete instance); } From d7e48f93bbebfb74989dd511bc08a9f277a1aa6e Mon Sep 17 00:00:00 2001 From: Esa Korhonen Date: Mon, 6 Mar 2017 14:15:36 +0200 Subject: [PATCH 13/20] NamedServerFilter PCRE2 matching and refactoring Change to modutil_extract_SQL(), add pcre2_data to filter session. The pattern is now jit-compiled for maximum speed. Move general pcre2 error printing to a function and macro. Add instance-level statistics so the filter always prints diagnostic info. Add a mention of PCRE2 to release notes. --- .../MaxScale-2.2.0-Release-Notes.md | 5 +- include/maxscale/pcre2.h | 13 + server/core/maxscale_pcre2.c | 23 ++ .../namedserverfilter/namedserverfilter.cc | 257 ++++++++++-------- 4 files changed, 179 insertions(+), 119 deletions(-) diff --git a/Documentation/Release-Notes/MaxScale-2.2.0-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.2.0-Release-Notes.md index 1d46825e4..d514b55a4 100644 --- a/Documentation/Release-Notes/MaxScale-2.2.0-Release-Notes.md +++ b/Documentation/Release-Notes/MaxScale-2.2.0-Release-Notes.md @@ -10,7 +10,10 @@ report at [Jira](https://jira.mariadb.org). ## Changed Features -### Blah +### NamedServerFilter + +This filter now uses the PCRE2-libarary to match queries. Previously, it used +the POSIX-version of PCRE2. ## Dropped Features diff --git a/include/maxscale/pcre2.h b/include/maxscale/pcre2.h index ca762e6d6..e9f990185 100644 --- a/include/maxscale/pcre2.h +++ b/include/maxscale/pcre2.h @@ -30,6 +30,13 @@ MXS_BEGIN_DECLS #include +/** + * Print an error message explaining an error code. + * @param errorcode value returned by pcre2 functions + */ +#define MXS_PCRE2_PRINT_ERROR(errorcode)\ + mxs_pcre2_print_error(errorcode, MXS_MODULE_NAME, __FILE__,__LINE__, __func__) + typedef enum { MXS_PCRE2_MATCH, @@ -41,5 +48,11 @@ mxs_pcre2_result_t mxs_pcre2_substitute(pcre2_code *re, const char *subject, const char *replace, char** dest, size_t* size); mxs_pcre2_result_t mxs_pcre2_simple_match(const char* pattern, const char* subject, int options, int* error); +/** + * Print an error message explaining an error code. Best used through the macro + * MXS_PCRE2_PRINT_ERROR + */ +void mxs_pcre2_print_error(int errorcode, const char *module_name, const char *filename, + int line_num, const char* func_name); MXS_END_DECLS diff --git a/server/core/maxscale_pcre2.c b/server/core/maxscale_pcre2.c index ab43e672d..6719e7810 100644 --- a/server/core/maxscale_pcre2.c +++ b/server/core/maxscale_pcre2.c @@ -26,6 +26,8 @@ #include #include +#include +#include /** * Utility wrapper for PCRE2 library function call pcre2_substitute. @@ -133,3 +135,24 @@ mxs_pcre2_result_t mxs_pcre2_simple_match(const char* pattern, const char* subje } return rval; } + +void mxs_pcre2_print_error(int errorcode, const char *module_name, const char *filename, + int line_num, const char* func_name) +{ + ss_dassert(module_name); + ss_dassert(filename); + ss_dassert(func_name); + + char errorbuf[100]; + int err_msg_rval = pcre2_get_error_message(errorcode, (PCRE2_UCHAR*)errorbuf, + sizeof(errorbuf)); + + mxs_log_message(LOG_ERR, module_name, filename, line_num, func_name, + "PCRE2 Error message: '%s'.", errorbuf); + if (err_msg_rval == PCRE2_ERROR_NOMEMORY) + { + mxs_log_message(LOG_ERR, module_name, filename, line_num, func_name, + "PCRE2 error buffer was too small to contain the complete" + "message."); + } +} diff --git a/server/modules/filter/namedserverfilter/namedserverfilter.cc b/server/modules/filter/namedserverfilter/namedserverfilter.cc index 50d0ac273..7f32371cf 100644 --- a/server/modules/filter/namedserverfilter/namedserverfilter.cc +++ b/server/modules/filter/namedserverfilter/namedserverfilter.cc @@ -28,10 +28,11 @@ * @endverbatim */ -#define MXS_MODULE_NAME "RegexHintFilter" +#define MXS_MODULE_NAME "namedserverfilter" #include +#include #include #include @@ -43,7 +44,6 @@ #include #include #include -#include using std::string; @@ -62,14 +62,22 @@ typedef struct source_host */ class RegexHintInst : public MXS_FILTER { -public: // will change to private later - string match; /* Regular expression to match */ - string server; /* Server to route to */ - string user; /* User name to restrict matches */ +private: + string m_match; /* Regular expression to match */ + string m_server; /* Server to route to */ + string m_user; /* User name to restrict matches */ - REGEXHINT_SOURCE_HOST *source; /* Source address to restrict matches */ - pcre2_code* re; /* Compiled regex text */ + REGEXHINT_SOURCE_HOST *m_source; /* Source address to restrict matches */ + pcre2_code* m_regex; /* Compiled regex text, can be used from multiple threads */ + /* Total statements diverted statistics. Unreliable due to non-locked but + * shared access. */ + volatile unsigned int m_total_diverted; + volatile unsigned int m_total_undiverted; + + int check_source_host(const char *remote, const struct sockaddr_in *ipv4); + +public: RegexHintInst(string match, string server, string user, REGEXHINT_SOURCE_HOST* source, pcre2_code* regex); ~RegexHintInst(); @@ -87,6 +95,8 @@ typedef struct RegexHintSess_t int n_diverted; /* No. of statements diverted */ int n_undiverted; /* No. of statements not diverted */ int active; /* Is filter active */ + pcre2_match_data *match_data; /* regex result container */ + bool regex_error_printed; } RegexHintSess; /* Api entrypoints */ @@ -101,9 +111,6 @@ static uint64_t getCapabilities(MXS_FILTER* instance); /* End entrypoints */ static bool validate_ip_address(const char *); -static int check_source_host(RegexHintInst *, - const char *, - const struct sockaddr_in *); static REGEXHINT_SOURCE_HOST *set_source_address(const char *); static void free_instance(RegexHintInst *); @@ -117,22 +124,18 @@ static const MXS_ENUM_VALUE option_values[] = RegexHintInst::RegexHintInst(string match, string server, string user, REGEXHINT_SOURCE_HOST* source, pcre2_code* regex) - : match(match), - server(server), - user(user), - source(source), - re(regex) + : m_match(match), + m_server(server), + m_user(user), + m_source(source), + m_regex(regex), + m_total_diverted(0), + m_total_undiverted(0) {} RegexHintInst::~RegexHintInst() { - if (re) - { - pcre2_code_free(re); - } - if (source) - { - MXS_FREE(source); - } + pcre2_code_free(m_regex); + MXS_FREE(m_source); } RegexHintSess_t* RegexHintInst::newSession(MXS_SESSION *session) @@ -144,20 +147,24 @@ RegexHintSess_t* RegexHintInst::newSession(MXS_SESSION *session) { my_session->n_diverted = 0; my_session->n_undiverted = 0; + my_session->regex_error_printed = false; my_session->active = 1; + /* It's best to generate match data from the pattern to avoid extra allocations + * during matching. If data creation fails, matching will fail as well. */ + my_session->match_data = pcre2_match_data_create_from_pattern(m_regex, NULL); /* Check client IP against 'source' host option */ - if (this->source && this->source->address && + if (m_source && m_source->address && (remote = session_get_remote(session)) != NULL) { my_session->active = - check_source_host(this, remote, &session->client_dcb->ipv4); + this->check_source_host(remote, &session->client_dcb->ipv4); } /* Check client user against 'user' option */ - if (this->user.length() && + if (m_user.length() && (user = session_get_user(session)) && - strcmp(user, this->user.c_str())) + (user != m_user)) { my_session->active = 0; } @@ -167,29 +174,41 @@ RegexHintSess_t* RegexHintInst::newSession(MXS_SESSION *session) int RegexHintInst::routeQuery(RegexHintSess_t* my_session, GWBUF *queue) { - char *sql; + char *sql = NULL; + int sql_len = 0; if (modutil_is_SQL(queue) && my_session->active) { - if ((sql = modutil_get_SQL(queue)) != NULL) + if (modutil_extract_SQL(queue, &sql, &sql_len)) { - int result = pcre2_match(this->re, (PCRE2_SPTR)sql, - 0, 0, 0, - NULL, NULL); - if (result == 0) + int result = pcre2_match(m_regex, (PCRE2_SPTR)sql, sql_len, 0, 0, + my_session->match_data, NULL); + if (result >= 0) { - // Change hint_create_route() to take a const char* to remove copying. - char* zServer = MXS_STRDUP_A(this->server.c_str()); + /* Have a match. No need to check if the regex matches the complete + * query, since the user can form the regex to enforce this. */ queue->hint = hint_create_route(queue->hint, HINT_ROUTE_TO_NAMED_SERVER, - zServer); + m_server.c_str()); my_session->n_diverted++; + m_total_diverted++; } - else + else if (result == PCRE2_ERROR_NOMATCH) { my_session->n_undiverted++; + m_total_undiverted++; + } + else if (result < 0) + { + // Print regex error only once per session + if (!my_session->regex_error_printed) + { + MXS_PCRE2_PRINT_ERROR(result); + } + my_session->regex_error_printed = true; + my_session->n_undiverted++; + m_total_undiverted++; } - MXS_FREE(sql); } } return my_session->down.routeQuery(my_session->down.instance, @@ -199,7 +218,11 @@ int RegexHintInst::routeQuery(RegexHintSess_t* my_session, GWBUF *queue) void RegexHintInst::diagnostic(RegexHintSess_t* my_session, DCB *dcb) { dcb_printf(dcb, "\t\tMatch and route: /%s/ -> %s\n", - match.c_str(), server.c_str()); + m_match.c_str(), m_server.c_str()); + dcb_printf(dcb, "\t\tTotal no. of queries diverted by filter (approx.): %d\n", + m_total_diverted); + dcb_printf(dcb, "\t\tTotal no. of queries not diverted by filter (approx.): %d\n", + m_total_undiverted); if (my_session) { dcb_printf(dcb, "\t\tNo. of queries diverted by filter: %d\n", @@ -207,19 +230,72 @@ void RegexHintInst::diagnostic(RegexHintSess_t* my_session, DCB *dcb) dcb_printf(dcb, "\t\tNo. of queries not diverted by filter: %d\n", my_session->n_undiverted); } - if (source) + if (m_source) { dcb_printf(dcb, "\t\tReplacement limited to connections from %s\n", - source->address); + m_source->address); } - if (user.length()) + if (m_user.length()) { dcb_printf(dcb, "\t\tReplacement limit to user %s\n", - user.c_str()); + m_user.c_str()); } } + +/** + * Check whether the client IP + * matches the configured 'source' host + * which can have up to three % wildcards + * + * @param remote The clientIP + * @param ipv4 The client IPv4 struct + * @return 1 for match, 0 otherwise + */ +int RegexHintInst::check_source_host(const char *remote, const struct sockaddr_in *ipv4) +{ + int ret = 0; + struct sockaddr_in check_ipv4; + + memcpy(&check_ipv4, ipv4, sizeof(check_ipv4)); + + switch (m_source->netmask) + { + case 32: + ret = strcmp(m_source->address, remote) == 0 ? 1 : 0; + break; + case 24: + /* Class C check */ + check_ipv4.sin_addr.s_addr &= 0x00FFFFFF; + break; + case 16: + /* Class B check */ + check_ipv4.sin_addr.s_addr &= 0x0000FFFF; + break; + case 8: + /* Class A check */ + check_ipv4.sin_addr.s_addr &= 0x000000FF; + break; + default: + break; + } + + ret = (m_source->netmask < 32) ? + (check_ipv4.sin_addr.s_addr == m_source->ipv4.sin_addr.s_addr) : + ret; + + if (ret) + { + MXS_INFO("Client IP %s matches host source %s%s", + remote, + m_source->netmask < 32 ? "with wildcards " : "", + m_source->address); + } + + return ret; +} + /** * Create an instance of the filter for a particular service * within MaxScale. @@ -253,28 +329,27 @@ createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params) string server(config_get_string(params, "server")); string user(config_get_string(params, "user")); - int cflags = config_get_enum(params, "options", option_values); + int pcre_ops = config_get_enum(params, "options", option_values); int errorcode = -1; PCRE2_SIZE error_offset = -1; pcre2_code* regex = - pcre2_compile((PCRE2_SPTR) match.c_str(), PCRE2_ZERO_TERMINATED, cflags, + pcre2_compile((PCRE2_SPTR) match.c_str(), match.length(), pcre_ops, &errorcode, &error_offset, NULL); - - if (!regex) + if (regex) + { + // Try to compile even further for faster matching + if (pcre2_jit_compile(regex, PCRE2_JIT_COMPLETE) < 0) + { + MXS_NOTICE("PCRE2 JIT compilation of pattern '%s' failed, " + "falling back to normal compilation.", match.c_str()); + } + } + else { error = true; - - char errorbuf[100]; //How long should this be?? - int err_msg_rval = pcre2_get_error_message(errorcode, (PCRE2_UCHAR*)errorbuf, - sizeof(errorbuf)); - MXS_ERROR("Invalid PCRE2 regular expression '%s' at position '%zu'.", + MXS_ERROR("Invalid PCRE2 regular expression '%s' (position '%zu').", match.c_str(), error_offset); - MXS_ERROR("PCRE2 Error message: '%s'.", errorbuf); - if (err_msg_rval == PCRE2_ERROR_NOMEMORY) - { - MXS_ERROR("PCRE2 error buffer was too small to contain the complete" - "message."); - } + MXS_PCRE2_PRINT_ERROR(errorcode); } if (error) @@ -338,7 +413,9 @@ closeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session) static void freeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session) { - MXS_FREE(session); + RegexHintSess_t* my_session = (RegexHintSess_t*)session; + pcre2_match_data_free(my_session->match_data); + MXS_FREE(my_session); return; } @@ -396,8 +473,7 @@ diagnostic(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb) { RegexHintInst *my_instance = static_cast(instance); RegexHintSess *my_session = (RegexHintSess *) fsession; - - + my_instance->diagnostic(my_session, dcb); } /** @@ -461,61 +537,6 @@ static bool validate_ip_address(const char *host) } } -/** - * Check whether the client IP - * matches the configured 'source' host - * which can have up to three % wildcards - * - * @param instance The filter instance - * @param remote The clientIP - * @param ipv4 The client IPv4 struct - * @return 1 for match, 0 otherwise - */ -static int check_source_host(RegexHintInst *instance, - const char *remote, - const struct sockaddr_in *ipv4) -{ - int ret = 0; - struct sockaddr_in check_ipv4; - - memcpy(&check_ipv4, ipv4, sizeof(check_ipv4)); - - switch (instance->source->netmask) - { - case 32: - ret = strcmp(instance->source->address, remote) == 0 ? 1 : 0; - break; - case 24: - /* Class C check */ - check_ipv4.sin_addr.s_addr &= 0x00FFFFFF; - break; - case 16: - /* Class B check */ - check_ipv4.sin_addr.s_addr &= 0x0000FFFF; - break; - case 8: - /* Class A check */ - check_ipv4.sin_addr.s_addr &= 0x000000FF; - break; - default: - break; - } - - ret = (instance->source->netmask < 32) ? - (check_ipv4.sin_addr.s_addr == instance->source->ipv4.sin_addr.s_addr) : - ret; - - if (ret) - { - MXS_INFO("Client IP %s matches host source %s%s", - remote, - instance->source->netmask < 32 ? "with wildcards " : "", - instance->source->address); - } - - return ret; -} - /** * Set the 'source' option into a proper struct * @@ -680,4 +701,4 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE() }; return &info; -} \ No newline at end of file +} From c18f94b31bc544df5fd5190629702afd4669ebf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 8 Mar 2017 15:53:49 +0200 Subject: [PATCH 14/20] Get socket family from struct sockaddr_storage The struct sockaddr_storage has a member variable that tells the socket family. --- server/core/dcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/core/dcb.c b/server/core/dcb.c index f0b9802b3..5c40e8f9d 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -2862,7 +2862,7 @@ dcb_accept(DCB *listener) client_dcb->fd = c_sock; // get client address - if (((struct sockaddr *)&client_conn)->sa_family == AF_UNIX) + if (client_conn.ss_family == AF_UNIX) { // client address client_dcb->remote = MXS_STRDUP_A("localhost_from_socket"); From a925be4e2a05af23f660291b12a486e0a9ac7802 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Wed, 8 Mar 2017 17:18:06 +0200 Subject: [PATCH 15/20] Turn off error in qc_sqlite built GCC on CentOS6 thinks there is an array-bounds error in the sqlite code. As that code is outside our hands, it is easiest to instruct GCC not to treat it as an error. --- query_classifier/qc_sqlite/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/query_classifier/qc_sqlite/CMakeLists.txt b/query_classifier/qc_sqlite/CMakeLists.txt index 159e792f2..d09745a1b 100644 --- a/query_classifier/qc_sqlite/CMakeLists.txt +++ b/query_classifier/qc_sqlite/CMakeLists.txt @@ -16,6 +16,9 @@ include_directories(${CMAKE_BINARY_DIR}/sqlite-bld-3110100/tsrc) include_directories(${CMAKE_BINARY_DIR}/sqlite-bld-3110100) include_directories(${MARIADB_CONNECTOR_INCLUDE_DIR}) +# GCC thinks there is an array-bounds error in sqlite code. +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=array-bounds") + add_library(qc_sqlite SHARED qc_sqlite.c qc_sqlite3.c builtin_functions.c) add_dependencies(qc_sqlite maxscale_sqlite) add_definitions(-DMAXSCALE -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT -DSQLITE_OMIT_ATTACH -DSQLITE_OMIT_REINDEX -DSQLITE_OMIT_AUTOVACUUM -DSQLITE_OMIT_PRAGMA) From fd2df3a863fcbacfee348f7c782e2a46f756d70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 8 Mar 2017 20:03:45 +0200 Subject: [PATCH 16/20] Always open files with configured block size If the Avro file already exists, it should be opened with the configured block size instead of the default block size of 16 kilobytes. --- server/modules/routing/avro/avro_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/modules/routing/avro/avro_file.c b/server/modules/routing/avro/avro_file.c index 41ef968f3..4d9819f0d 100644 --- a/server/modules/routing/avro/avro_file.c +++ b/server/modules/routing/avro/avro_file.c @@ -122,7 +122,7 @@ AVRO_TABLE* avro_table_alloc(const char* filepath, const char* json_schema, size if (access(filepath, F_OK) == 0) { - rc = avro_file_writer_open(filepath, &table->avro_file); + rc = avro_file_writer_open_bs(filepath, &table->avro_file, block_size); } else { From d764bb9e1f35266803cba95561b118b829fdfba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 9 Mar 2017 07:45:29 +0200 Subject: [PATCH 17/20] MXS-1178: Fix master_accept_reads The order of the servers in the service definition could break the master_accept_reads functionality. When the first server defined in the service is a slave, it will always be picked as the first candidate for reads. The master would only be considered as a candidate for reads if no previous candidate was available. For this reason, the master_accept_reads only worked when the first server in the list was the master. --- server/modules/routing/readwritesplit/readwritesplit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index dc67558a0..339ba6b39 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -1236,7 +1236,8 @@ static bool get_dcb(DCB **p_dcb, ROUTER_CLIENT_SES *rses, backend_type_t btype, * backend and update assign it to new candidate if * necessary. */ - else if (SERVER_IS_SLAVE(&server)) + else if (SERVER_IS_SLAVE(&server) || + (rses->rses_config.rw_master_reads && SERVER_IS_MASTER(&server))) { if (max_rlag == MAX_RLAG_UNDEFINED || (b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE && From 84a6848f10af80d847a9e75bd53970d5709d05c4 Mon Sep 17 00:00:00 2001 From: Timofey Turenko Date: Mon, 20 Feb 2017 13:41:51 +0200 Subject: [PATCH 18/20] Add build information to --version-full If the Jenkins build information is available, print it in the full version output. --- CMakeLists.txt | 7 +++++++ server/core/gateway.c | 12 ++++++++++++ server/include/version.h.in | 3 +++ 3 files changed, 22 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f29db5dd3..fe46a7232 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,13 @@ if(${MAXSCALE_VERSION} MATCHES "-stable") endif() endif() +# Copy cmake_flags, JENKINS_BUILD_TAG, source and value evironmental variables +# into cmake variables. These are used by the build system to store information +# about the packages being built. +set(MAXSCALE_SOURCE "$ENV{source} $ENV{value}") +set(MAXSCALE_CMAKE_FLAGS "$ENV{cmake_flags}") +set(MAXSCALE_JENKINS_BUILD_TAG "$ENV{BUILD_TAG}") + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/server/include) configure_file(${CMAKE_SOURCE_DIR}/server/include/version.h.in ${CMAKE_BINARY_DIR}/server/include/version.h @ONLY) configure_file(${CMAKE_SOURCE_DIR}/server/include/gwdirs.h.in ${CMAKE_BINARY_DIR}/server/include/gwdirs.h @ONLY) diff --git a/server/core/gateway.c b/server/core/gateway.c index a87fba03b..0177d2321 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -1341,6 +1341,18 @@ int main(int argc, char **argv) case 'V': rc = EXIT_SUCCESS; printf("MaxScale %s - %s\n", MAXSCALE_VERSION, maxscale_commit); + if (strcmp(MAXSCALE_SOURCE, " ") != 0) + { + printf("Source: %s\n", MAXSCALE_SOURCE); + } + if (strcmp(MAXSCALE_CMAKE_FLAGS, "") != 0) + { + printf("CMake flags: %s\n", MAXSCALE_CMAKE_FLAGS); + } + if (strcmp(MAXSCALE_JENKINS_BUILD_TAG, "") != 0) + { + printf("Jenkins build: %s\n", MAXSCALE_JENKINS_BUILD_TAG); + } goto return_main; case 'l': diff --git a/server/include/version.h.in b/server/include/version.h.in index c15fa862d..3e17ebe04 100644 --- a/server/include/version.h.in +++ b/server/include/version.h.in @@ -1,2 +1,5 @@ #define MAXSCALE_VERSION "@MAXSCALE_VERSION@" #define MAXSCALE_COMMIT "@MAXSCALE_COMMIT@" +#define MAXSCALE_SOURCE "@MAXSCALE_SOURCE@" +#define MAXSCALE_CMAKE_FLAGS "@MAXSCALE_CMAKE_FLAGS@" +#define MAXSCALE_JENKINS_BUILD_TAG "@MAXSCALE_JENKINS_BUILD_TAG@" From e1a1959bc23ed423e8f957c0dcc8ae1e1e8044c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 7 Mar 2017 12:18:53 +0200 Subject: [PATCH 19/20] Replace strerror_r with mxs_strerror The mxs_strerror function requires no local buffer, thus making it simpler and cleaner to use. --- avro/maxavro_file.c | 15 ++-- avro/maxavro_record.c | 3 +- server/core/buffer.c | 4 +- server/core/config.c | 10 +-- server/core/config_runtime.c | 9 +-- server/core/dcb.c | 49 ++++-------- server/core/externcmd.c | 3 +- server/core/gateway.cc | 50 ++++-------- server/core/hashtable.c | 6 +- server/core/listener.c | 9 +-- server/core/log_manager.cc | 18 ++--- server/core/monitor.c | 18 ++--- server/core/poll.c | 15 ++-- server/core/secrets.c | 39 ++++------ server/core/server.c | 9 +-- server/core/service.c | 9 +-- server/core/skygw_utils.cc | 78 +++++++------------ server/core/utils.c | 18 ++--- .../CDCPlainAuth/cdc_plain_auth.c | 6 +- server/modules/filter/cache/rules.cc | 4 +- .../storage/storage_rocksdb/rocksdbstorage.cc | 12 +-- server/modules/filter/dbfwfilter/dbfwfilter.c | 6 +- server/modules/filter/masking/maskingrules.cc | 4 +- server/modules/filter/qlafilter/qlafilter.c | 6 +- .../MySQL/MySQLBackend/mysql_backend.c | 8 +- server/modules/protocol/maxscaled/maxscaled.c | 4 +- server/modules/routing/avrorouter/avro.c | 7 +- .../modules/routing/avrorouter/avro_client.c | 3 +- server/modules/routing/avrorouter/avro_file.c | 14 ++-- server/modules/routing/binlogrouter/blr.c | 9 +-- .../modules/routing/binlogrouter/blr_file.c | 49 +++++------- .../modules/routing/binlogrouter/blr_master.c | 11 +-- .../modules/routing/binlogrouter/blr_slave.c | 6 +- 33 files changed, 174 insertions(+), 337 deletions(-) diff --git a/avro/maxavro_file.c b/avro/maxavro_file.c index aabb5ba0c..2a1a98213 100644 --- a/avro/maxavro_file.c +++ b/avro/maxavro_file.c @@ -27,9 +27,8 @@ static bool maxavro_read_sync(FILE *file, uint8_t* sync) if (ferror(file)) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read file sync marker: %d, %s", errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } else if (feof(file)) { @@ -52,8 +51,7 @@ bool maxavro_verify_block(MAXAVRO_FILE *file) { if (ferror(file->file)) { - char err[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Failed to read file: %d %s", errno, strerror_r(errno, err, sizeof(err))); + MXS_ERROR("Failed to read file: %d %s", errno, mxs_strerror(errno)); } else if (rc > 0 || !feof(file->file)) { @@ -181,9 +179,8 @@ bool maxavro_read_datablock_start(MAXAVRO_FILE* file) if (pos == -1) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read datablock start: %d, %s", errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } else { @@ -421,9 +418,8 @@ GWBUF* maxavro_file_binary_header(MAXAVRO_FILE *file) { if (ferror(file->file)) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read binary header: %d, %s", errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } else if (feof(file->file)) { @@ -444,9 +440,8 @@ GWBUF* maxavro_file_binary_header(MAXAVRO_FILE *file) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read binary header: %d, %s", errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } return rval; diff --git a/avro/maxavro_record.c b/avro/maxavro_record.c index 586e3bcb8..65707c339 100644 --- a/avro/maxavro_record.c +++ b/avro/maxavro_record.c @@ -325,9 +325,8 @@ GWBUF* maxavro_record_read_binary(MAXAVRO_FILE *file) { if (ferror(file->file)) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read %ld bytes: %d, %s", data_size, errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); file->last_error = MAXAVRO_ERR_IO; } gwbuf_free(rval); diff --git a/server/core/buffer.c b/server/core/buffer.c index ddf3e24bf..817c86c5f 100644 --- a/server/core/buffer.c +++ b/server/core/buffer.c @@ -94,9 +94,7 @@ gwbuf_alloc(unsigned int size) retblock: if (rval == NULL) { - char errbuf[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Memory allocation failed due to %s.", - strerror_r(errno, errbuf, sizeof(errbuf))); + MXS_ERROR("Memory allocation failed due to %s.", mxs_strerror(errno)); } #if defined(BUFFER_TRACE) else diff --git a/server/core/config.c b/server/core/config.c index c6405f1a3..360457d3c 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -541,9 +541,8 @@ static bool is_directory(const char *dir) } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_WARNING("Could not access %s, not reading: %s", - dir, strerror_r(errno, errbuf, sizeof(errbuf))); + dir, mxs_strerror(errno)); } } else @@ -2365,9 +2364,7 @@ bool config_has_duplicate_sections(const char* filename, DUPLICATE_CONTEXT* cont } else { - char errbuf[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Failed to open file '%s': %s", filename, - strerror_r(errno, errbuf, sizeof(errbuf))); + MXS_ERROR("Failed to open file '%s': %s", filename, mxs_strerror(errno)); rval = true; } } @@ -3255,9 +3252,8 @@ static bool check_path_parameter(const MXS_MODULE_PARAM *params, const char *val } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Bad path parameter '%s' (absolute path '%s'): %d, %s", value, - buf, errno, strerror_r(errno, err, sizeof(err))); + buf, errno, mxs_strerror(errno)); } } else diff --git a/server/core/config_runtime.c b/server/core/config_runtime.c index b572c72fe..7d15cc634 100644 --- a/server/core/config_runtime.c +++ b/server/core/config_runtime.c @@ -176,9 +176,8 @@ bool runtime_destroy_server(SERVER *server) { if (errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove persisted server configuration '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else { @@ -542,9 +541,8 @@ bool runtime_destroy_listener(SERVICE *service, const char *name) { if (errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove persisted listener configuration '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else { @@ -618,9 +616,8 @@ bool runtime_destroy_monitor(MXS_MONITOR *monitor) { if (errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove persisted monitor configuration '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else { diff --git a/server/core/dcb.c b/server/core/dcb.c index 943350804..2fe402f98 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -537,14 +537,13 @@ dcb_process_victim_queue(int threadid) { int eno = errno; errno = 0; - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("%lu [dcb_process_victim_queue] Error : Failed to close " "socket %d on dcb %p due error %d, %s.", pthread_self(), dcb->fd, dcb, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } else { @@ -868,7 +867,6 @@ dcb_bytes_readable(DCB *dcb) if (-1 == ioctl(dcb->fd, FIONREAD, &bytesavailable)) { - char errbuf[MXS_STRERROR_BUFLEN]; /* */ MXS_ERROR("%lu [dcb_read] Error : ioctl FIONREAD for dcb %p in " "state %s fd %d failed due error %d, %s.", @@ -877,7 +875,7 @@ dcb_bytes_readable(DCB *dcb) STRDCBSTATE(dcb->state), dcb->fd, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); /* */ return -1; } @@ -946,7 +944,6 @@ dcb_basic_read(DCB *dcb, int bytesavailable, int maxbytes, int nreadtotal, int * * This is a fatal error which should cause shutdown. * Todo shutdown if memory allocation fails. */ - char errbuf[MXS_STRERROR_BUFLEN]; /* */ MXS_ERROR("%lu [dcb_read] Error : Failed to allocate read buffer " "for dcb %p fd %d, due %d, %s.", @@ -954,7 +951,7 @@ dcb_basic_read(DCB *dcb, int bytesavailable, int maxbytes, int nreadtotal, int * dcb, dcb->fd, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); /* */ *nsingleread = -1; } @@ -967,7 +964,6 @@ dcb_basic_read(DCB *dcb, int bytesavailable, int maxbytes, int nreadtotal, int * { if (errno != 0 && errno != EAGAIN && errno != EWOULDBLOCK) { - char errbuf[MXS_STRERROR_BUFLEN]; /* */ MXS_ERROR("%lu [dcb_read] Error : Read failed, dcb %p in state " "%s fd %d, due %d, %s.", @@ -976,7 +972,7 @@ dcb_basic_read(DCB *dcb, int bytesavailable, int maxbytes, int nreadtotal, int * STRDCBSTATE(dcb->state), dcb->fd, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); /* */ } gwbuf_free(buffer); @@ -1076,7 +1072,6 @@ dcb_basic_read_SSL(DCB *dcb, int *nsingleread) * This is a fatal error which should cause shutdown. * Todo shutdown if memory allocation fails. */ - char errbuf[MXS_STRERROR_BUFLEN]; /* */ MXS_ERROR("%lu [dcb_read] Error : Failed to allocate read buffer " "for dcb %p fd %d, due %d, %s.", @@ -1084,7 +1079,7 @@ dcb_basic_read_SSL(DCB *dcb, int *nsingleread) dcb, dcb->fd, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); /* */ *nsingleread = -1; return NULL; @@ -1175,9 +1170,7 @@ dcb_log_errors_SSL (DCB *dcb, const char *called_by, int ret) { int local_errno = errno; MXS_ERROR("SSL error caused by TCP error %d %s", - local_errno, - strerror_r(local_errno, errbuf, sizeof(errbuf)) - ); + local_errno, mxs_strerror(local_errno)); } else { @@ -1278,7 +1271,6 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno) { if (eno == EPIPE) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_DEBUG("%lu [dcb_write] Write to dcb " "%p in state %s fd %d failed " "due errno %d, %s", @@ -1287,7 +1279,7 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno) STRDCBSTATE(dcb->state), dcb->fd, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } } @@ -1297,7 +1289,6 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno) eno != EAGAIN && eno != EWOULDBLOCK) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Write to dcb %p in " "state %s fd %d failed due " "errno %d, %s", @@ -1305,7 +1296,7 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno) STRDCBSTATE(dcb->state), dcb->fd, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } @@ -1331,12 +1322,11 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno) } if (dolog) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_DEBUG("%lu [dcb_write] Writing to %s socket failed due %d, %s.", pthread_self(), DCB_ROLE_CLIENT_HANDLER == dcb->dcb_role ? "client" : "backend server", eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } } } @@ -2097,13 +2087,12 @@ gw_write(DCB *dcb, GWBUF *writeq, bool *stop_writing) saved_errno != EPIPE) #endif { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Write to %s %s in state %s failed due errno %d, %s", DCB_STRTYPE(dcb), dcb->remote, STRDCBSTATE(dcb->state), - saved_errno, strerror_r(saved_errno, errbuf, sizeof(errbuf))); + saved_errno, mxs_strerror(saved_errno)); MXS_DEBUG("Write to %s %s in state %s failed due errno %d, %s (at %p, fd %d)", DCB_STRTYPE(dcb), dcb->remote, STRDCBSTATE(dcb->state), - saved_errno, strerror_r(saved_errno, errbuf, sizeof(errbuf)), + saved_errno, mxs_strerror(saved_errno), dcb, dcb->fd); } } @@ -2677,7 +2666,6 @@ dcb_accept(DCB *listener) int sendbuf; struct sockaddr_storage client_conn; socklen_t optlen = sizeof(sendbuf); - char errbuf[MXS_STRERROR_BUFLEN]; if ((c_sock = dcb_accept_one_connection(listener, (struct sockaddr *)&client_conn)) >= 0) { @@ -2691,7 +2679,7 @@ dcb_accept(DCB *listener) if (setsockopt(c_sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, optlen) != 0) { MXS_ERROR("Failed to set socket options. Error %d: %s", - errno, strerror_r(errno, errbuf, sizeof(errbuf))); + errno, mxs_strerror(errno)); } sendbuf = MXS_CLIENT_SO_RCVBUF; @@ -2699,7 +2687,7 @@ dcb_accept(DCB *listener) if (setsockopt(c_sock, SOL_SOCKET, SO_RCVBUF, &sendbuf, optlen) != 0) { MXS_ERROR("Failed to set socket options. Error %d: %s", - errno, strerror_r(errno, errbuf, sizeof(errbuf))); + errno, mxs_strerror(errno)); } setnonblocking(c_sock); @@ -2826,7 +2814,6 @@ dcb_accept_one_connection(DCB *listener, struct sockaddr *client_conn) if (c_sock == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; /* Did not get a file descriptor */ if (eno == EAGAIN || eno == EWOULDBLOCK) { @@ -2848,14 +2835,14 @@ dcb_accept_one_connection(DCB *listener, struct sockaddr *client_conn) MXS_DEBUG("%lu [dcb_accept_one_connection] Error %d, %s. ", pthread_self(), eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); /* Log an error the first time this happens */ if (i == 0) { MXS_ERROR("Error %d, %s. Failed to accept new client connection.", eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } nanosecs = (long long)1000000 * 100 * i * i; ts1.tv_sec = nanosecs / 1000000000; @@ -2871,7 +2858,7 @@ dcb_accept_one_connection(DCB *listener, struct sockaddr *client_conn) */ MXS_ERROR("Failed to accept new client connection due to %d, %s.", eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); break; } } @@ -3117,10 +3104,8 @@ dcb_set_socket_option(int sockfd, int level, int optname, void *optval, socklen_ { if (setsockopt(sockfd, level, optname, optval, optlen) != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to set socket options. Error %d: %s", - errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + errno, mxs_strerror(errno)); return -1; } return 0; diff --git a/server/core/externcmd.c b/server/core/externcmd.c index 8df3619bc..4a7bd1423 100644 --- a/server/core/externcmd.c +++ b/server/core/externcmd.c @@ -179,9 +179,8 @@ int externcmd_execute(EXTERNCMD* cmd) if (pid < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to execute command '%s', fork failed: [%d] %s", - cmd->argv[0], errno, strerror_r(errno, errbuf, sizeof(errbuf))); + cmd->argv[0], errno, mxs_strerror(errno)); rval = -1; } else if (pid == 0) diff --git a/server/core/gateway.cc b/server/core/gateway.cc index cc7d68e2a..964f145a8 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -349,9 +349,8 @@ sigchld_handler (int i) if ((child = wait(&exit_status)) == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to wait child process: %d %s", - errno, strerror_r(errno, errbuf, sizeof(errbuf))); + errno, mxs_strerror(errno)); } else { @@ -464,11 +463,10 @@ static int signal_set(int sig, void (*handler)(int)) if (err < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed call sigaction() in %s due to %d, %s.", program_invocation_short_name, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); rc = 1; } @@ -500,9 +498,8 @@ static bool create_datadir(const char* base, char* datadir) } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Cannot create data directory '%s': %d %s\n", - datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + datadir, errno, mxs_strerror(errno)); } } } @@ -510,9 +507,8 @@ static bool create_datadir(const char* base, char* datadir) { if (len < PATH_MAX) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "Error: Cannot create data directory '%s': %d %s\n", - datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + datadir, errno, mxs_strerror(errno)); } else { @@ -538,9 +534,8 @@ int ntfw_cb(const char* filename, { int eno = errno; errno = 0; - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove the data directory %s of MaxScale due to %d, %s.", - datadir, eno, strerror_r(eno, errbuf, sizeof(errbuf))); + datadir, eno, mxs_strerror(eno)); } return rc; } @@ -730,22 +725,20 @@ static void print_log_n_stderr( { if (mxs_log_init(NULL, get_logdir(), MXS_LOG_TARGET_FS)) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("%s%s%s%s", logstr, eno == 0 ? "" : " (", - eno == 0 ? "" : strerror_r(eno, errbuf, sizeof(errbuf)), + eno == 0 ? "" : mxs_strerror(eno), eno == 0 ? "" : ")"); } } if (do_stderr) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Error: %s%s%s%s\n", fprstr, eno == 0 ? "" : " (", - eno == 0 ? "" : strerror_r(eno, errbuf, sizeof(errbuf)), + eno == 0 ? "" : mxs_strerror(eno), eno == 0 ? "" : ")"); } } @@ -1807,9 +1800,8 @@ int main(int argc, char **argv) } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Cannot create data directory '%s': %d %s\n", - datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + datadir, errno, mxs_strerror(errno)); goto return_main; } @@ -2126,12 +2118,11 @@ static void unlink_pidfile(void) { if (unlink(pidfile)) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "MaxScale failed to remove pidfile %s: error %d, %s\n", pidfile, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); } } } @@ -2587,36 +2578,32 @@ static int set_user(const char* user) pwname = getpwnam(user); if (pwname == NULL) { - char errbuf[MXS_STRERROR_BUFLEN]; printf("Error: Failed to retrieve user information for '%s': %d %s\n", - user, errno, errno == 0 ? "User not found" : strerror_r(errno, errbuf, sizeof(errbuf))); + user, errno, errno == 0 ? "User not found" : mxs_strerror(errno)); return -1; } rval = setgid(pwname->pw_gid); if (rval != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; printf("Error: Failed to change group to '%d': %d %s\n", - pwname->pw_gid, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + pwname->pw_gid, errno, mxs_strerror(errno)); return rval; } rval = setuid(pwname->pw_uid); if (rval != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; printf("Error: Failed to change user to '%s': %d %s\n", - pwname->pw_name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + pwname->pw_name, errno, mxs_strerror(errno)); return rval; } if (prctl(PR_GET_DUMPABLE) == 0) { if (prctl(PR_SET_DUMPABLE , 1) == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; printf("Error: Failed to set dumpable flag on for the process '%s': %d %s\n", - pwname->pw_name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + pwname->pw_name, errno, mxs_strerror(errno)); return -1; } } @@ -2660,14 +2647,13 @@ static bool change_cwd() if (chdir(get_logdir()) != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to change working directory to '%s': %d, %s. " "Trying to change working directory to '/'.", - get_logdir(), errno, strerror_r(errno, errbuf, sizeof (errbuf))); + get_logdir(), errno, mxs_strerror(errno)); if (chdir("/") != 0) { MXS_ERROR("Failed to change working directory to '/': %d, %s", - errno, strerror_r(errno, errbuf, sizeof (errbuf))); + errno, mxs_strerror(errno)); rval = false; } else @@ -2719,8 +2705,7 @@ static bool daemonize(void) if (pid < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; - fprintf(stderr, "fork() error %s\n", strerror_r(errno, errbuf, sizeof(errbuf))); + fprintf(stderr, "fork() error %s\n", mxs_strerror(errno)); exit(1); } @@ -2732,8 +2717,7 @@ static bool daemonize(void) if (setsid() < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; - fprintf(stderr, "setsid() error %s\n", strerror_r(errno, errbuf, sizeof(errbuf))); + fprintf(stderr, "setsid() error %s\n", mxs_strerror(errno)); exit(1); } return false; diff --git a/server/core/hashtable.c b/server/core/hashtable.c index 1b830eb26..8e583d252 100644 --- a/server/core/hashtable.c +++ b/server/core/hashtable.c @@ -746,9 +746,8 @@ hashtable_save(HASHTABLE *table, const char *filename, } if (write(fd, &rval, sizeof(rval)) == -1) // Write zero counter, will be overrwriten at end { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to write hashtable item count: %d, %s", errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } if ((iter = hashtable_iterator(table)) != NULL) { @@ -776,9 +775,8 @@ hashtable_save(HASHTABLE *table, const char *filename, { if (write(fd, &rval, sizeof(rval)) == -1) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to write hashtable item count: %d, %s", errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } } diff --git a/server/core/listener.c b/server/core/listener.c index 6fdf71eff..7d0d1969c 100644 --- a/server/core/listener.c +++ b/server/core/listener.c @@ -399,9 +399,8 @@ static bool create_listener_config(const SERV_LISTENER *listener, const char *fi if (file == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open file '%s' when serializing listener '%s': %d, %s", - filename, listener->name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, listener->name, errno, mxs_strerror(errno)); return false; } @@ -487,9 +486,8 @@ bool listener_serialize(const SERV_LISTENER *listener) if (unlink(filename) == -1 && errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove temporary listener configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else if (create_listener_config(listener, filename)) { @@ -506,9 +504,8 @@ bool listener_serialize(const SERV_LISTENER *listener) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to rename temporary listener configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } } diff --git a/server/core/log_manager.cc b/server/core/log_manager.cc index b106c4fba..da9583749 100644 --- a/server/core/log_manager.cc +++ b/server/core/log_manager.cc @@ -1608,9 +1608,8 @@ static bool logfile_write_header(skygw_file_t* file) if ((header_items != 1) || (line_items != 1)) { - char errbuf[MXS_STRERROR_BUFLEN]; LOG_ERROR("MaxScale Log: Writing header failed due to %d, %s\n", - errno, strerror_r(errno, errbuf, sizeof(errbuf))); + errno, mxs_strerror(errno)); written = false; } @@ -1785,15 +1784,13 @@ static bool check_file_and_path(const char* filename, bool* writable) { if (file_is_symlink(filename)) { - char errbuf[MXS_STRERROR_BUFLEN]; LOG_ERROR("MaxScale Log: Error, Can't access file pointed to by %s due to %d, %s.\n", - filename, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, errno, mxs_strerror(errno)); } else { - char errbuf[MXS_STRERROR_BUFLEN]; LOG_ERROR("MaxScale Log: Error, Can't access %s due to %d, %s.\n", - filename, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, errno, mxs_strerror(errno)); } if (writable) @@ -1890,9 +1887,8 @@ static bool logfile_init(logfile_t* logfile, if (mkdir(dir, S_IRWXU | S_IRWXG) != 0 && (errno != EEXIST)) { - char errbuf[MXS_STRERROR_BUFLEN]; LOG_ERROR("MaxScale Log: Error, creating directory %s failed due to %d, %s.\n", - dir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + dir, errno, mxs_strerror(errno)); succ = false; goto return_with_succ; @@ -2075,9 +2071,8 @@ static bool logfile_write_footer(skygw_file_t* file, const char* suffix) if ((header_items != 1) || (line_items != 1)) { - char errbuf[MXS_STRERROR_BUFLEN]; LOG_ERROR("MaxScale Log: Writing footer failed due to %d, %s\n", - errno, strerror_r(errno, errbuf, sizeof(errbuf))); + errno, mxs_strerror(errno)); written = false; } @@ -2203,10 +2198,9 @@ static bool thr_flush_file(logmanager_t *lm, filewriter_t *fwr) if (err) { // TODO: Log this to syslog. - char errbuf[MXS_STRERROR_BUFLEN]; LOG_ERROR("MaxScale Log: Error, writing to the log-file %s failed due to %d, %s. " "Disabling writing to the log.\n", - lf->lf_full_file_name, err, strerror_r(err, errbuf, sizeof(errbuf))); + lf->lf_full_file_name, err, mxs_strerror(err)); mxs_log_set_maxlog_enabled(false); } diff --git a/server/core/monitor.c b/server/core/monitor.c index d2d392e03..1b3b8341d 100644 --- a/server/core/monitor.c +++ b/server/core/monitor.c @@ -1276,9 +1276,8 @@ static bool create_monitor_server_config(const MXS_MONITOR *monitor, const char if (file == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open file '%s' when serializing monitor '%s': %d, %s", - filename, monitor->name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, monitor->name, errno, mxs_strerror(errno)); return false; } @@ -1315,9 +1314,8 @@ static bool create_monitor_config(const MXS_MONITOR *monitor, const char *filena if (file == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open file '%s' when serializing monitor '%s': %d, %s", - filename, monitor->name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, monitor->name, errno, mxs_strerror(errno)); return false; } @@ -1350,9 +1348,8 @@ bool monitor_serialize_servers(const MXS_MONITOR *monitor) if (unlink(filename) == -1 && errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove temporary monitor configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else if (create_monitor_server_config(monitor, filename)) { @@ -1369,9 +1366,8 @@ bool monitor_serialize_servers(const MXS_MONITOR *monitor) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to rename temporary monitor configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } } @@ -1387,9 +1383,8 @@ bool monitor_serialize(const MXS_MONITOR *monitor) if (unlink(filename) == -1 && errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove temporary monitor configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else if (create_monitor_config(monitor, filename)) { @@ -1406,9 +1401,8 @@ bool monitor_serialize(const MXS_MONITOR *monitor) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to rename temporary monitor configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } } diff --git a/server/core/poll.c b/server/core/poll.c index e57b93371..75fee3d27 100644 --- a/server/core/poll.c +++ b/server/core/poll.c @@ -239,9 +239,8 @@ poll_init() { if ((epoll_fd[i] = epoll_create(MAX_EVENTS)) == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("FATAL: Could not create epoll instance: %s", - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); exit(-1); } } @@ -930,13 +929,12 @@ process_pollq(int thread_id, struct epoll_event *event) } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_DEBUG("%lu [poll_waitevents] " "EPOLLOUT due %d, %s. " "dcb %p, fd %i", pthread_self(), eno, - strerror_r(eno, errbuf, sizeof(errbuf)), + mxs_strerror(eno), dcb, dcb->fd); } @@ -988,12 +986,11 @@ process_pollq(int thread_id, struct epoll_event *event) int eno = gw_getsockerrno(dcb->fd); if (eno != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_DEBUG("%lu [poll_waitevents] " "EPOLLERR due %d, %s.", pthread_self(), eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } ts_stats_increment(pollStats.n_error, thread_id); @@ -1006,7 +1003,6 @@ process_pollq(int thread_id, struct epoll_event *event) if (ev & EPOLLHUP) { ss_debug(int eno = gw_getsockerrno(dcb->fd)); - ss_debug(char errbuf[MXS_STRERROR_BUFLEN]); MXS_DEBUG("%lu [poll_waitevents] " "EPOLLHUP on dcb %p, fd %d. " "Errno %d, %s.", @@ -1014,7 +1010,7 @@ process_pollq(int thread_id, struct epoll_event *event) dcb, dcb->fd, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); ts_stats_increment(pollStats.n_hup, thread_id); if ((dcb->flags & DCBF_HUNG) == 0) { @@ -1031,7 +1027,6 @@ process_pollq(int thread_id, struct epoll_event *event) if (ev & EPOLLRDHUP) { ss_debug(int eno = gw_getsockerrno(dcb->fd)); - ss_debug(char errbuf[MXS_STRERROR_BUFLEN]); MXS_DEBUG("%lu [poll_waitevents] " "EPOLLRDHUP on dcb %p, fd %d. " "Errno %d, %s.", @@ -1039,7 +1034,7 @@ process_pollq(int thread_id, struct epoll_event *event) dcb, dcb->fd, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); ts_stats_increment(pollStats.n_hup, thread_id); if ((dcb->flags & DCBF_HUNG) == 0) diff --git a/server/core/secrets.c b/server/core/secrets.c index b5e1b23e7..3f75596d0 100644 --- a/server/core/secrets.c +++ b/server/core/secrets.c @@ -93,9 +93,8 @@ secrets_readKeys(const char* path) } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("The provided path \"%s\" does not exist or cannot be accessed. " - "Error: %d, %s.", path, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + "Error: %d, %s.", path, errno, mxs_strerror(errno)); return NULL; } @@ -115,22 +114,20 @@ secrets_readKeys(const char* path) { if (!reported) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_NOTICE("Encrypted password file %s can't be accessed " "(%s). Password encryption is not used.", secret_file, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); reported = 1; } } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Access for secrets file " "[%s] failed. Error %d, %s.", secret_file, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); } return NULL; } @@ -141,12 +138,11 @@ secrets_readKeys(const char* path) { int eno = errno; errno = 0; - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed opening secret " "file [%s]. Error %d, %s.", secret_file, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); return NULL; } @@ -157,12 +153,11 @@ secrets_readKeys(const char* path) int eno = errno; errno = 0; close(fd); - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("fstat for secret file %s " "failed. Error %d, %s.", secret_file, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); return NULL; } @@ -171,12 +166,11 @@ secrets_readKeys(const char* path) int eno = errno; errno = 0; close(fd); - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Secrets file %s has " "incorrect size. Error %d, %s.", secret_file, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); return NULL; } if (secret_stats.st_mode != (S_IRUSR | S_IFREG)) @@ -206,14 +200,13 @@ secrets_readKeys(const char* path) errno = 0; close(fd); MXS_FREE(keys); - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Read from secrets file " "%s failed. Read %ld, expected %d bytes. Error %d, %s.", secret_file, len, (int)sizeof(MAXKEYS), eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); return NULL; } @@ -223,12 +216,11 @@ secrets_readKeys(const char* path) int eno = errno; errno = 0; MXS_FREE(keys); - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed closing the " "secrets file %s. Error %d, %s.", secret_file, eno, - strerror_r(eno, errbuf, sizeof(errbuf))); + mxs_strerror(eno)); return NULL; } ss_dassert(keys != NULL); @@ -271,22 +263,20 @@ int secrets_write_keys(const char *dir) /* Open for writing | Create | Truncate the file for writing */ if ((fd = open(secret_file, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR)) < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("failed opening secret " "file [%s]. Error %d, %s.", secret_file, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); return 1; } /* Open for writing | Create | Truncate the file for writing */ if ((randfd = open("/dev/random", O_RDONLY)) < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("failed opening /dev/random. Error %d, %s.", errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); close(fd); return 1; } @@ -306,12 +296,11 @@ int secrets_write_keys(const char *dir) /* Write data */ if (write(fd, &key, sizeof(key)) < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("failed writing into " "secret file [%s]. Error %d, %s.", secret_file, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); close(fd); return 1; } @@ -319,22 +308,20 @@ int secrets_write_keys(const char *dir) /* close file */ if (close(fd) < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("failed closing the " "secret file [%s]. Error %d, %s.", secret_file, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); } if (chmod(secret_file, S_IRUSR) < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("failed to change the permissions of the" "secret file [%s]. Error %d, %s.", secret_file, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); } return 0; diff --git a/server/core/server.c b/server/core/server.c index 9df8ccc6f..7fa5cb5a4 100644 --- a/server/core/server.c +++ b/server/core/server.c @@ -1119,9 +1119,8 @@ static bool create_server_config(const SERVER *server, const char *filename) if (file == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open file '%s' when serializing server '%s': %d, %s", - filename, server->unique_name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, server->unique_name, errno, mxs_strerror(errno)); return false; } @@ -1230,9 +1229,8 @@ bool server_serialize(const SERVER *server) if (unlink(filename) == -1 && errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove temporary server configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else if (create_server_config(server, filename)) { @@ -1249,9 +1247,8 @@ bool server_serialize(const SERVER *server) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to rename temporary server configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } } diff --git a/server/core/service.c b/server/core/service.c index 26e1e71a4..df6b2d168 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -2217,9 +2217,8 @@ static bool create_service_config(const SERVICE *service, const char *filename) if (file == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open file '%s' when serializing service '%s': %d, %s", - filename, service->name, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + filename, service->name, errno, mxs_strerror(errno)); return false; } @@ -2258,9 +2257,8 @@ bool service_serialize_servers(const SERVICE *service) if (unlink(filename) == -1 && errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to remove temporary service configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } else if (create_service_config(service, filename)) { @@ -2277,9 +2275,8 @@ bool service_serialize_servers(const SERVICE *service) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to rename temporary service configuration at '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); + filename, errno, mxs_strerror(errno)); } } diff --git a/server/core/skygw_utils.cc b/server/core/skygw_utils.cc index 2ac4a429c..87853bb10 100644 --- a/server/core/skygw_utils.cc +++ b/server/core/skygw_utils.cc @@ -56,10 +56,9 @@ int skygw_rwlock_rdlock(skygw_rwlock_t* rwlock) else { rwlock->srw_rwlock_thr = 0; - char errbuf[MXS_STRERROR_BUFLEN]; ss_dfprintf(stderr, "* pthread_rwlock_rdlock : %s\n", - strerror_r(err, errbuf, sizeof (errbuf))); + mxs_strerror(err)); } return err; } @@ -75,10 +74,9 @@ int skygw_rwlock_wrlock(skygw_rwlock_t* rwlock) else { rwlock->srw_rwlock_thr = 0; - char errbuf[MXS_STRERROR_BUFLEN]; ss_dfprintf(stderr, "* pthread_rwlock_wrlock : %s\n", - strerror_r(err, errbuf, sizeof (errbuf))); + mxs_strerror(err)); } return err; } @@ -93,9 +91,8 @@ int skygw_rwlock_unlock(skygw_rwlock_t* rwlock) } else { - char errbuf[MXS_STRERROR_BUFLEN]; ss_dfprintf(stderr, "* pthread_rwlock_unlock : %s\n", - strerror_r(err, errbuf, sizeof (errbuf))); + mxs_strerror(err)); } return err; } @@ -106,9 +103,8 @@ int skygw_rwlock_destroy(skygw_rwlock_t* rwlock) /** Lock */ if ((err = pthread_rwlock_wrlock(rwlock->srw_rwlock)) != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Error : pthread_rwlock_wrlock failed due to %d, %s.\n", - err, strerror_r(err, errbuf, sizeof (errbuf))); + err, mxs_strerror(err)); goto retblock; } /** Clean the struct */ @@ -118,9 +114,8 @@ int skygw_rwlock_destroy(skygw_rwlock_t* rwlock) /** Destroy */ if ((err = pthread_rwlock_destroy(rwlock->srw_rwlock)) != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Error : pthread_rwlock_destroy failed due to %d,%s\n", - err, strerror_r(err, errbuf, sizeof (errbuf))); + err, mxs_strerror(err)); } else { @@ -150,9 +145,8 @@ int skygw_rwlock_init(skygw_rwlock_t** rwlock) if (err != 0) { free(rwl); - char errbuf[MXS_STRERROR_BUFLEN]; ss_dfprintf(stderr, "* Creating pthread_rwlock failed : %s\n", - strerror_r(err, errbuf, sizeof (errbuf))); + mxs_strerror(err)); goto return_err; } *rwlock = rwl; @@ -348,9 +342,8 @@ int skygw_thread_start(skygw_thread_t* thr) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Starting file writer thread failed due error, %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); goto return_err; } @@ -524,9 +517,8 @@ simple_mutex_t* simple_mutex_init(simple_mutex_t* mutexptr, const char* name) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Initializing simple mutex %s failed due error %d, %s\n", - name, err, strerror_r(errno, errbuf, sizeof (errbuf))); + name, err, mxs_strerror(errno)); perror("simple_mutex : "); /** Write zeroes if flat, free otherwise. */ @@ -564,9 +556,8 @@ int simple_mutex_done(simple_mutex_t* sm) if (err != 0) { perror("simple_mutex : "); - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Destroying simple mutex %s failed due %d, %s\n", - sm->sm_name, err, strerror_r(errno, errbuf, sizeof (errbuf))); + sm->sm_name, err, mxs_strerror(errno)); goto return_err; } #endif @@ -611,9 +602,8 @@ int simple_mutex_lock(simple_mutex_t* sm, bool block) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Locking simple mutex %s failed due error, %d, %s\n", - sm->sm_name, err, strerror_r(errno, errbuf, sizeof (errbuf))); + sm->sm_name, err, mxs_strerror(errno)); perror("simple_mutex : "); } else @@ -640,9 +630,8 @@ int simple_mutex_unlock(simple_mutex_t* sm) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Unlocking simple mutex %s failed due error %d, %s\n", - sm->sm_name, err, strerror_r(errno, errbuf, sizeof (errbuf))); + sm->sm_name, err, mxs_strerror(errno)); perror("simple_mutex : "); } else @@ -674,9 +663,8 @@ skygw_message_t* skygw_message_init(void) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Initializing pthread mutex failed due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); free(mes); mes = NULL; goto return_mes; @@ -685,9 +673,8 @@ skygw_message_t* skygw_message_init(void) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Initializing pthread cond var failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); pthread_mutex_destroy(&mes->mes_mutex); free(mes); mes = NULL; @@ -714,18 +701,16 @@ void skygw_message_done(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Destroying cond var failed due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } ss_dassert(err == 0); err = pthread_mutex_destroy(&(mes->mes_mutex)); if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Destroying pthread mutex failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } ss_dassert(err == 0); free(mes); @@ -741,9 +726,8 @@ skygw_mes_rc_t skygw_message_send(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Locking pthread mutex failed, due to error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); goto return_mes_rc; } mes->mes_sent = true; @@ -755,17 +739,15 @@ skygw_mes_rc_t skygw_message_send(skygw_message_t* mes) } else { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Signaling pthread cond var failed, due to error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } err = pthread_mutex_unlock(&(mes->mes_mutex)); if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Unlocking pthread mutex failed, due to error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } return_mes_rc: @@ -781,9 +763,8 @@ void skygw_message_wait(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Locking pthread mutex failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } ss_dassert(err == 0); @@ -793,9 +774,8 @@ void skygw_message_wait(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Locking pthread cond wait failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } } mes->mes_sent = false; @@ -803,9 +783,8 @@ void skygw_message_wait(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Unlocking pthread mutex failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); } ss_dassert(err == 0); } @@ -819,9 +798,8 @@ void skygw_message_reset(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Locking pthread mutex failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); goto return_mes_rc; } ss_dassert(err == 0); @@ -830,9 +808,8 @@ void skygw_message_reset(skygw_message_t* mes) if (err != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Unlocking pthread mutex failed, due error %d, %s\n", - err, strerror_r(errno, errbuf, sizeof (errbuf))); + err, mxs_strerror(errno)); goto return_mes_rc; } return_mes_rc: @@ -932,9 +909,8 @@ skygw_file_t* skygw_file_init(const char* fname, { int eno = errno; errno = 0; - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Opening file %s failed due %d, %s.\n", - file->sf_fname, eno, strerror_r(eno, errbuf, sizeof (errbuf))); + file->sf_fname, eno, mxs_strerror(eno)); free(file); file = NULL; goto return_file; @@ -956,9 +932,8 @@ skygw_file_t* skygw_file_init(const char* fname, { int eno = errno; errno = 0; - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "failed to create symlink %s -> %s due %d, %s. Exiting.", - fname, symlinkname, eno, strerror_r(eno, errbuf, sizeof (errbuf))); + fname, symlinkname, eno, mxs_strerror(eno)); free(file); file = NULL; goto return_file; @@ -992,9 +967,8 @@ void skygw_file_close(skygw_file_t* file) if ((err = fclose(file->sf_file)) != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "* Closing file %s failed due to %d, %s.\n", - file->sf_fname, errno, strerror_r(errno, errbuf, sizeof (errbuf))); + file->sf_fname, errno, mxs_strerror(errno)); } else { diff --git a/server/core/utils.c b/server/core/utils.c index 1c60ca56c..400e50cbd 100644 --- a/server/core/utils.c +++ b/server/core/utils.c @@ -102,21 +102,19 @@ int setnonblocking(int fd) if ((fl = fcntl(fd, F_GETFL, 0)) == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Can't GET fcntl for %i, errno = %d, %s.", fd, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); return 1; } if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Can't SET fcntl for %i, errno = %d, %s", fd, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); return 1; } return 0; @@ -391,18 +389,16 @@ static bool mkdir_all_internal(char *path, mode_t mask) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to create directory '%s': %d, %s", - path, errno, strerror_r(errno, err, sizeof(err))); + path, errno, mxs_strerror(errno)); } } } } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to create directory '%s': %d, %s", - path, errno, strerror_r(errno, err, sizeof(err))); + path, errno, mxs_strerror(errno)); } } else @@ -711,9 +707,8 @@ char* replace_literal(char* haystack, const char* needle, const char* replacemen if (search_re == NULL) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "Regex memory allocation failed : %s\n", - strerror_r(errno, errbuf, sizeof (errbuf))); + mxs_strerror(errno)); newstr = haystack; goto retblock; } @@ -724,9 +719,8 @@ char* replace_literal(char* haystack, const char* needle, const char* replacemen if (newstr == NULL) { - char errbuf[MXS_STRERROR_BUFLEN]; fprintf(stderr, "Regex memory allocation failed : %s\n", - strerror_r(errno, errbuf, sizeof (errbuf))); + mxs_strerror(errno)); free(search_re); free(newstr); newstr = haystack; diff --git a/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.c b/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.c index 327062fb5..8f266853c 100644 --- a/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.c +++ b/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.c @@ -114,8 +114,7 @@ static bool cdc_add_new_user(const MODULECMD_ARG *args) } else { - char err[MXS_STRERROR_BUFLEN]; - char *real_err = strerror_r(errno, err, sizeof(err)); + const char *real_err = mxs_strerror(errno); MXS_NOTICE("Failed to write to file '%s': %s", path, real_err); modulecmd_set_error("Failed to write to file '%s': %s", path, real_err); } @@ -124,8 +123,7 @@ static bool cdc_add_new_user(const MODULECMD_ARG *args) } else { - char err[MXS_STRERROR_BUFLEN]; - char *real_err = strerror_r(errno, err, sizeof(err)); + const char *real_err = mxs_strerror(errno); MXS_NOTICE("Failed to open file '%s': %s", path, real_err); modulecmd_set_error("Failed to open file '%s': %s", path, real_err); } diff --git a/server/modules/filter/cache/rules.cc b/server/modules/filter/cache/rules.cc index a9925476a..d8356132b 100644 --- a/server/modules/filter/cache/rules.cc +++ b/server/modules/filter/cache/rules.cc @@ -231,10 +231,8 @@ CACHE_RULES *cache_rules_load(const char *path, uint32_t debug) } else { - char errbuf[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Could not open rules file %s for reading: %s", - path, strerror_r(errno, errbuf, sizeof(errbuf))); + path, mxs_strerror(errno)); } return rules; diff --git a/server/modules/filter/cache/storage/storage_rocksdb/rocksdbstorage.cc b/server/modules/filter/cache/storage/storage_rocksdb/rocksdbstorage.cc index 4ae20f84d..3fb8fc61b 100644 --- a/server/modules/filter/cache/storage/storage_rocksdb/rocksdbstorage.cc +++ b/server/modules/filter/cache/storage/storage_rocksdb/rocksdbstorage.cc @@ -70,8 +70,7 @@ bool deletePath(const string& path) } else { - char errbuf[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Could not stat: %s", strerror_r(errno, errbuf, sizeof(errbuf))); + MXS_ERROR("Could not stat: %s", mxs_strerror(errno)); } } else @@ -98,10 +97,9 @@ bool deletePath(const string& path) case FTS_DNR: case FTS_ERR: { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Error while traversing %s: %s", pCurrent->fts_accpath, - strerror_r(pCurrent->fts_errno, errbuf, sizeof(errbuf))); + mxs_strerror(pCurrent->fts_errno)); rv = false; } break; @@ -125,11 +123,10 @@ bool deletePath(const string& path) case FTS_DEFAULT: if (remove(pCurrent->fts_accpath) < 0) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Could not remove '%s', the cache directory may need to " "be deleted manually: %s", pCurrent->fts_accpath, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); rv = false; } break; @@ -261,10 +258,9 @@ RocksDBStorage* RocksDBStorage::Create(const char* zName, } else if (errno != EEXIST) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to create storage directory %s: %s", storageDirectory.c_str(), - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); ok = false; } diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.c b/server/modules/filter/dbfwfilter/dbfwfilter.c index c16bf4ed1..3d6102879 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.c +++ b/server/modules/filter/dbfwfilter/dbfwfilter.c @@ -734,9 +734,8 @@ bool dbfw_reload_rules(const MODULECMD_ARG *argv) } else { - char err[MXS_STRERROR_BUFLEN]; modulecmd_set_error("Failed to read rules at '%s': %d, %s", filename, - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); rval = false; } @@ -1483,9 +1482,8 @@ static bool process_rule_file(const char* filename, RULE** rules, HASHTABLE **us } else { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open rule file '%s': %d, %s", filename, errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); } diff --git a/server/modules/filter/masking/maskingrules.cc b/server/modules/filter/masking/maskingrules.cc index 77c8881ae..6c220e600 100644 --- a/server/modules/filter/masking/maskingrules.cc +++ b/server/modules/filter/masking/maskingrules.cc @@ -783,10 +783,8 @@ auto_ptr MaskingRules::load(const char* zPath) } else { - char errbuf[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Could not open rules file %s for reading: %s", - zPath, strerror_r(errno, errbuf, sizeof(errbuf))); + zPath, mxs_strerror(errno)); } return sRules; diff --git a/server/modules/filter/qlafilter/qlafilter.c b/server/modules/filter/qlafilter/qlafilter.c index 463b8459d..b8a92e2a4 100644 --- a/server/modules/filter/qlafilter/qlafilter.c +++ b/server/modules/filter/qlafilter/qlafilter.c @@ -327,11 +327,10 @@ createInstance(const char *name, char **options, MXS_CONFIG_PARAMETER *params) if (my_instance->unified_fp == NULL) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Opening output file for qla " "filter failed due to %d, %s", errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); error = true; } MXS_FREE(filename); @@ -427,11 +426,10 @@ newSession(MXS_FILTER *instance, MXS_SESSION *session) if (my_session->fp == NULL) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Opening output file for qla " "filter failed due to %d, %s", errno, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); MXS_FREE(my_session->filename); MXS_FREE(my_session); my_session = NULL; diff --git a/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c b/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c index 6080ae7cc..f2414859a 100644 --- a/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c +++ b/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c @@ -1119,16 +1119,15 @@ static int gw_error_backend_event(DCB *dcb) if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *) & len) == 0 && error != 0) { - char errstring[MXS_STRERROR_BUFLEN]; if (dcb->state != DCB_STATE_POLLING) { MXS_ERROR("DCB in state %s got error '%s'.", STRDCBSTATE(dcb->state), - strerror_r(error, errstring, sizeof(errstring))); + mxs_strerror(errno)); } else { MXS_ERROR("Error '%s' in session that is not ready for routing.", - strerror_r(error, errstring, sizeof(errstring))); + mxs_strerror(errno)); } } } @@ -1168,10 +1167,9 @@ static int gw_backend_hangup(DCB *dcb) { if (error != 0 && session->state != SESSION_STATE_STOPPING) { - char errstring[MXS_STRERROR_BUFLEN]; MXS_ERROR("Hangup in session that is not ready for routing, " "Error reported is '%s'.", - strerror_r(error, errstring, sizeof(errstring))); + mxs_strerror(errno)); } } } diff --git a/server/modules/protocol/maxscaled/maxscaled.c b/server/modules/protocol/maxscaled/maxscaled.c index 895ab00df..28914a7bc 100644 --- a/server/modules/protocol/maxscaled/maxscaled.c +++ b/server/modules/protocol/maxscaled/maxscaled.c @@ -150,10 +150,8 @@ static bool authenticate_socket(MAXSCALED *protocol, DCB *dcb) } else { - char errbuf[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Could not get socket family of client connection: %s", - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); } return authenticated; diff --git a/server/modules/routing/avrorouter/avro.c b/server/modules/routing/avrorouter/avro.c index 33899c51b..86ba44c52 100644 --- a/server/modules/routing/avrorouter/avro.c +++ b/server/modules/routing/avrorouter/avro.c @@ -1129,7 +1129,6 @@ static bool ensure_dir_ok(const char* path, int mode) if (path) { - char err[MXS_STRERROR_BUFLEN]; char resolved[PATH_MAX + 1]; const char *rp = realpath(path, resolved); @@ -1150,19 +1149,19 @@ static bool ensure_dir_ok(const char* path, int mode) else { MXS_ERROR("Failed to access directory '%s': %d, %s", rp, - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); } } else { MXS_ERROR("Failed to create directory '%s': %d, %s", rp, - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); } } else { MXS_ERROR("Failed to resolve real path name for '%s': %d, %s", path, - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); } } diff --git a/server/modules/routing/avrorouter/avro_client.c b/server/modules/routing/avrorouter/avro_client.c index 6bdc8490e..9f8fca5ac 100644 --- a/server/modules/routing/avrorouter/avro_client.c +++ b/server/modules/routing/avrorouter/avro_client.c @@ -868,9 +868,8 @@ GWBUF* read_avro_json_schema(const char *avrofile, const char* dir) } else { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open file '%s': %d, %s", buffer, errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } } return rval; diff --git a/server/modules/routing/avrorouter/avro_file.c b/server/modules/routing/avrorouter/avro_file.c index df94e53b5..3091eed83 100644 --- a/server/modules/routing/avrorouter/avro_file.c +++ b/server/modules/routing/avrorouter/avro_file.c @@ -70,9 +70,8 @@ bool avro_open_binlog(const char *binlogdir, const char *file, int *dest) { if (errno != ENOENT) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open binlog file %s: %d, %s", path, errno, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); } return false; } @@ -166,7 +165,6 @@ bool avro_save_conversion_state(AVRO_INSTANCE *router) { FILE *config_file; char filename[PATH_MAX + 1]; - char err_msg[MXS_STRERROR_BUFLEN]; snprintf(filename, sizeof(filename), "%s/"AVRO_PROGRESS_FILE".tmp", router->avrodir); @@ -176,7 +174,7 @@ bool avro_save_conversion_state(AVRO_INSTANCE *router) if (config_file == NULL) { MXS_ERROR("Failed to open file '%s': %d, %s", filename, - errno, strerror_r(errno, err_msg, sizeof(err_msg))); + errno, mxs_strerror(errno)); return false; } @@ -195,7 +193,7 @@ bool avro_save_conversion_state(AVRO_INSTANCE *router) if (rc == -1) { MXS_ERROR("Failed to rename file '%s' to '%s': %d, %s", filename, newname, - errno, strerror_r(errno, err_msg, sizeof(err_msg))); + errno, mxs_strerror(errno)); return false; } @@ -425,11 +423,10 @@ static GWBUF* read_event_data(AVRO_INSTANCE *router, REP_HEADER* hdr, uint64_t p { if (n == -1) { - char err_msg[MXS_STRERROR_BUFLEN]; MXS_ERROR("Error reading the event at %lu in %s. " "%s, expected %d bytes.", pos, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg)), + mxs_strerror(errno), hdr->event_size - BINLOG_EVENT_HDR_LEN); } else @@ -519,10 +516,9 @@ avro_binlog_end_t avro_read_all_events(AVRO_INSTANCE *router) break; case -1: { - char err_msg[BLRM_STRERROR_R_MSG_SIZE + 1] = ""; MXS_ERROR("Failed to read binlog file %s at position %llu (%s).", router->binlog_name, pos, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); if (errno == EBADF) MXS_ERROR("Bad file descriptor in read binlog for file %s" diff --git a/server/modules/routing/binlogrouter/blr.c b/server/modules/routing/binlogrouter/blr.c index 53c933d58..a3d229a9b 100644 --- a/server/modules/routing/binlogrouter/blr.c +++ b/server/modules/routing/binlogrouter/blr.c @@ -653,12 +653,11 @@ createInstance(SERVICE *service, char **options) mkdir_rval = mkdir(inst->binlogdir, 0700); if (mkdir_rval == -1) { - char err_msg[MXS_STRERROR_BUFLEN]; 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))); + mxs_strerror(errno)); free_instance(inst); return NULL; @@ -1788,8 +1787,7 @@ errorReply(MXS_ROUTER *instance, getsockopt(router->master->fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0 && error != 0) { - char errbuf[MXS_STRERROR_BUFLEN]; - sprintf(msg, "%s ", strerror_r(error, errbuf, sizeof(errbuf))); + sprintf(msg, "%s ", mxs_strerror(error)); } else { @@ -2622,10 +2620,9 @@ int blr_parse_key_file(ROUTER_INSTANCE *router) if (!file) { - char errbuf[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to open KEY file '%s': %s", router->encryption.key_management_filename, - strerror_r(errno, errbuf, sizeof(errbuf))); + mxs_strerror(errno)); return -1; } diff --git a/server/modules/routing/binlogrouter/blr_file.c b/server/modules/routing/binlogrouter/blr_file.c index 35a8bf077..89527a4c8 100644 --- a/server/modules/routing/binlogrouter/blr_file.c +++ b/server/modules/routing/binlogrouter/blr_file.c @@ -307,10 +307,9 @@ blr_file_init(ROUTER_INSTANCE *router) root_len = strlen(router->fileroot); if ((dirp = opendir(path)) == NULL) { - char err_msg[BLRM_STRERROR_R_MSG_SIZE]; MXS_ERROR("%s: Unable to read the binlog directory %s, %s.", router->service->name, router->binlogdir, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); return 0; } while ((dp = readdir(dirp)) != NULL) @@ -433,20 +432,20 @@ blr_file_create(ROUTER_INSTANCE *router, char *file) else { MXS_ERROR("%s: Failed to write magic string to created binlog file %s, %s.", - router->service->name, path, strerror_r(errno, err_msg, sizeof(err_msg))); + router->service->name, path, mxs_strerror(errno)); close(fd); if (!unlink(path)) { MXS_ERROR("%s: Failed to delete file %s, %s.", - router->service->name, path, strerror_r(errno, err_msg, sizeof(err_msg))); + router->service->name, path, mxs_strerror(errno)); } } } else { MXS_ERROR("%s: Failed to create binlog file %s, %s.", - router->service->name, path, strerror_r(errno, err_msg, sizeof(err_msg))); + router->service->name, path, mxs_strerror(errno)); } return created; @@ -577,19 +576,18 @@ blr_write_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint32_t size, /* Check write operation result*/ if (n != size) { - char err_msg[MXS_STRERROR_BUFLEN]; MXS_ERROR("%s: Failed to write binlog record at %lu of %s, %s. " "Truncating to previous record.", router->service->name, router->binlog_position, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); /* Remove any partial event that was written */ if (ftruncate(router->binlog_fd, router->binlog_position)) { MXS_ERROR("%s: Failed to truncate binlog record at %lu of %s, %s. ", router->service->name, router->binlog_position, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); } return 0; } @@ -836,9 +834,8 @@ blr_read_binlog(ROUTER_INSTANCE *router, break; case -1: { - char err_msg[MXS_STRERROR_BUFLEN]; snprintf(errmsg, BINLOG_ERROR_MSG_LEN, "Failed to read binlog file '%s'; (%s), event at %lu", - file->binlogname, strerror_r(errno, err_msg, sizeof(err_msg)), pos); + file->binlogname, mxs_strerror(errno), pos); if (errno == EBADF) { @@ -899,10 +896,9 @@ blr_read_binlog(ROUTER_INSTANCE *router, break; case -1: { - char err_msg[MXS_STRERROR_BUFLEN]; snprintf(errmsg, BINLOG_ERROR_MSG_LEN, "Failed to reread header in binlog file '%s'; (%s), event at %lu", - file->binlogname, strerror_r(errno, err_msg, sizeof(err_msg)), pos); + file->binlogname, mxs_strerror(errno), pos); if (errno == EBADF) { @@ -983,13 +979,12 @@ blr_read_binlog(ROUTER_INSTANCE *router, if (n == -1) { - char err_msg[MXS_STRERROR_BUFLEN]; snprintf(errmsg, BINLOG_ERROR_MSG_LEN, "Error reading the binlog event at %lu in binlog file '%s';" "(%s), expected %d bytes.", pos, file->binlogname, - strerror_r(errno, err_msg, sizeof(err_msg)), + mxs_strerror(errno), hdr->event_size - BINLOG_EVENT_HDR_LEN); } else @@ -1199,9 +1194,8 @@ blr_cache_response(ROUTER_INSTANCE *router, char *response, GWBUF *buf) } if (write(fd, GWBUF_DATA(buf), GWBUF_LENGTH(buf)) == -1) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to write cached response: %d, %s", - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); } close(fd); @@ -1257,9 +1251,8 @@ blr_cache_read_response(ROUTER_INSTANCE *router, char *response) } if (read(fd, GWBUF_DATA(buf), statb.st_size) == -1) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read cached response: %d, %s", - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); } close(fd); return buf; @@ -1438,10 +1431,9 @@ blr_read_events_all_events(ROUTER_INSTANCE *router, break; case -1: { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to read binlog file %s at position %llu" " (%s).", router->binlog_name, pos, - strerror_r(errno, err, sizeof(err))); + mxs_strerror(errno)); if (errno == EBADF) { @@ -1657,11 +1649,10 @@ blr_read_events_all_events(ROUTER_INSTANCE *router, { if (n == -1) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Error reading the event at %llu in %s. " "%s, expected %d bytes.", pos, router->binlog_name, - strerror_r(errno, err, sizeof(err)), + mxs_strerror(errno), hdr.event_size - BINLOG_EVENT_HDR_LEN); } else @@ -2443,7 +2434,6 @@ blr_file_write_master_config(ROUTER_INSTANCE *router, char *error) char filename[len + sizeof('/') + sizeof(MASTER_INI)]; // sizeof includes NULL char tmp_file[len + sizeof('/') + sizeof(MASTER_INI) + sizeof('.') + sizeof(TMP)]; - char err_msg[MXS_STRERROR_BUFLEN]; char *ssl_ca; char *ssl_cert; char *ssl_key; @@ -2457,7 +2447,7 @@ blr_file_write_master_config(ROUTER_INSTANCE *router, char *error) if (config_file == NULL) { snprintf(error, BINLOG_ERROR_MSG_LEN, "%s, errno %u", - strerror_r(errno, err_msg, sizeof(err_msg)), errno); + mxs_strerror(errno), errno); return 2; } @@ -2465,7 +2455,7 @@ blr_file_write_master_config(ROUTER_INSTANCE *router, char *error) { fclose(config_file); snprintf(error, BINLOG_ERROR_MSG_LEN, "%s, errno %u", - strerror_r(errno, err_msg, sizeof(err_msg)), errno); + mxs_strerror(errno), errno); return 2; } @@ -2517,14 +2507,14 @@ blr_file_write_master_config(ROUTER_INSTANCE *router, char *error) if (rc == -1) { snprintf(error, BINLOG_ERROR_MSG_LEN, "%s, errno %u", - strerror_r(errno, err_msg, sizeof(err_msg)), errno); + mxs_strerror(errno), errno); return 3; } if (chmod(filename, S_IRUSR | S_IWUSR) < 0) { snprintf(error, BINLOG_ERROR_MSG_LEN, "%s, errno %u", - strerror_r(errno, err_msg, sizeof(err_msg)), errno); + mxs_strerror(errno), errno); return 3; } @@ -2724,12 +2714,11 @@ blr_write_special_event(ROUTER_INSTANCE *router, uint32_t file_offset, uint32_t /* Write the event */ if ((n = pwrite(router->binlog_fd, new_event, event_size, router->last_written)) != event_size) { - char err_msg[MXS_STRERROR_BUFLEN]; MXS_ERROR("%s: Failed to write %s special binlog record at %lu of %s, %s. " "Truncating to previous record.", router->service->name, new_event_desc, (unsigned long)file_offset, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); /* Remove any partial event that was written */ if (ftruncate(router->binlog_fd, router->binlog_position)) @@ -2737,7 +2726,7 @@ blr_write_special_event(ROUTER_INSTANCE *router, uint32_t file_offset, uint32_t MXS_ERROR("%s: Failed to truncate %s special binlog record at %lu of %s, %s. ", router->service->name, new_event_desc, (unsigned long)file_offset, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); } MXS_FREE(new_event); return 0; diff --git a/server/modules/routing/binlogrouter/blr_master.c b/server/modules/routing/binlogrouter/blr_master.c index 0b5599ec5..fff85b4f3 100644 --- a/server/modules/routing/binlogrouter/blr_master.c +++ b/server/modules/routing/binlogrouter/blr_master.c @@ -2015,11 +2015,10 @@ GWBUF break; case -1: { - char err_msg[MXS_STRERROR_BUFLEN]; 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))); + pos, mxs_strerror(errno)); if (errno == EBADF) { @@ -2075,11 +2074,10 @@ GWBUF { if (n == -1) { - char err_msg[MXS_STRERROR_BUFLEN]; 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); + mxs_strerror(errno), hdr->event_size - 19); } else { @@ -2327,12 +2325,11 @@ blr_write_data_into_binlog(ROUTER_INSTANCE *router, uint32_t data_len, uint8_t * if ((n = pwrite(router->binlog_fd, buf, data_len, router->last_written)) != data_len) { - char err_msg[MXS_STRERROR_BUFLEN]; MXS_ERROR("%s: Failed to write binlog record at %lu of %s, %s. " "Truncating to previous record.", router->service->name, router->binlog_position, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); /* Remove any partial event that was written */ if (ftruncate(router->binlog_fd, router->binlog_position)) @@ -2340,7 +2337,7 @@ blr_write_data_into_binlog(ROUTER_INSTANCE *router, uint32_t data_len, uint8_t * MXS_ERROR("%s: Failed to truncate binlog record at %lu of %s, %s. ", router->service->name, router->last_written, router->binlog_name, - strerror_r(errno, err_msg, sizeof(err_msg))); + mxs_strerror(errno)); } return 0; } diff --git a/server/modules/routing/binlogrouter/blr_slave.c b/server/modules/routing/binlogrouter/blr_slave.c index 342c4a482..86bd857e2 100644 --- a/server/modules/routing/binlogrouter/blr_slave.c +++ b/server/modules/routing/binlogrouter/blr_slave.c @@ -1008,10 +1008,9 @@ blr_slave_query(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue) if (removed_cfg == -1) { - char err_msg[MXS_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); + mxs_strerror(errno), errno); MXS_ERROR("%s: %s", router->service->name, error_string); } @@ -3677,9 +3676,8 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave) /* Truncate previous binlog file to last_safe pos */ if (truncate(file, router->last_safe_pos) == -1) { - char err[MXS_STRERROR_BUFLEN]; MXS_ERROR("Failed to truncate file: %d, %s", - errno, strerror_r(errno, err, sizeof(err))); + errno, mxs_strerror(errno)); } /* Log it */ From d82f4ad6dc23fefae85d8c1d48dab69f830f658e Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Thu, 9 Mar 2017 09:44:48 +0200 Subject: [PATCH 20/20] Prevent ignoring return value error When strtol[l] is used for verifying that a string represents a number, we are not interested in the actual value. --- server/core/config.c | 61 ++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/server/core/config.c b/server/core/config.c index c6405f1a3..433a4734c 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -3306,40 +3306,51 @@ bool config_param_is_valid(const MXS_MODULE_PARAM *params, const char *key, break; case MXS_MODULE_PARAM_INT: - strtol(value, &endptr, 10); - if (endptr != value && *endptr == '\0') { - valid = true; + errno = 0; + long int v = strtol(value, &endptr, 10); + (void)v; // error: ignoring return value of 'strtol' + if ((errno == 0) && (endptr != value) && (*endptr == '\0')) + { + valid = true; + } } break; case MXS_MODULE_PARAM_SIZE: - strtoll(value, &endptr, 10); - if (endptr != value) { - switch (*endptr) + errno = 0; + long long int v = strtoll(value, &endptr, 10); + (void)v; // error: ignoring return value of 'strtoll' + if (errno == 0) { - case 'T': - case 't': - case 'G': - case 'g': - case 'M': - case 'm': - case 'K': - case 'k': - if (*(endptr + 1) == '\0' || - ((*(endptr + 1) == 'i' || *(endptr + 1) == 'I') && *(endptr + 2) == '\0')) + if (endptr != value) { - valid = true; + switch (*endptr) + { + case 'T': + case 't': + case 'G': + case 'g': + case 'M': + case 'm': + case 'K': + case 'k': + if (*(endptr + 1) == '\0' || + ((*(endptr + 1) == 'i' || *(endptr + 1) == 'I') && *(endptr + 2) == '\0')) + { + valid = true; + } + break; + + case '\0': + valid = true; + break; + + default: + break; + } } - break; - - case '\0': - valid = true; - break; - - default: - break; } } break;