From 856d5130404b29d8f391e05b15a82776dbdf93e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 15 Jun 2018 01:12:24 +0300 Subject: [PATCH 1/2] MXS-1924: Enable WAL mode for sqlite The mysqlauth SQLite database is now opened in WAL mode if possible. This should prevent lockups of the database when the list of users is updated. Also moved the starting of the SQLite transaction one level up to also include the delete part in it. This should further reduce the effects of updating users. --- .../modules/authenticator/MySQLAuth/dbusers.c | 7 ++-- .../authenticator/MySQLAuth/mysql_auth.c | 40 +++++++++++++------ .../authenticator/MySQLAuth/mysql_auth.h | 3 +- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/server/modules/authenticator/MySQLAuth/dbusers.c b/server/modules/authenticator/MySQLAuth/dbusers.c index af8bc6f68..72c43c10d 100644 --- a/server/modules/authenticator/MySQLAuth/dbusers.c +++ b/server/modules/authenticator/MySQLAuth/dbusers.c @@ -776,8 +776,6 @@ int get_users_from_server(MYSQL *con, SERVER_REF *server, SERVICE *service, SERV if (result) { - start_sqlite_transaction(instance->handle); - MYSQL_ROW row; while ((row = mysql_fetch_row(result))) @@ -804,8 +802,6 @@ int get_users_from_server(MYSQL *con, SERVER_REF *server, SERVICE *service, SERV } } - commit_sqlite_transaction(instance->handle); - mysql_free_result(result); } } @@ -874,6 +870,7 @@ static int get_users(SERV_LISTENER *listener, bool skip_local) /** Delete the old users */ MYSQL_AUTH *instance = (MYSQL_AUTH*)listener->auth_instance; + start_sqlite_transaction(instance->handle); delete_mysql_users(instance->handle); SERVER_REF *server = service->dbref; @@ -921,6 +918,8 @@ static int get_users(SERV_LISTENER *listener, bool skip_local) } } + commit_sqlite_transaction(instance->handle); + MXS_FREE(dpwd); if (no_active_servers) diff --git a/server/modules/authenticator/MySQLAuth/mysql_auth.c b/server/modules/authenticator/MySQLAuth/mysql_auth.c index 672abd1d1..53b23363a 100644 --- a/server/modules/authenticator/MySQLAuth/mysql_auth.c +++ b/server/modules/authenticator/MySQLAuth/mysql_auth.c @@ -129,25 +129,41 @@ static void get_database_path(SERV_LISTENER *port, char *dest, size_t size) static bool open_instance_database(const char *path, sqlite3 **handle) { + bool rval = true; + if (sqlite3_open_v2(path, handle, db_flags, NULL) != SQLITE_OK) { MXS_ERROR("Failed to open SQLite3 handle."); - return false; + rval = false; } - - char *err; - - if (sqlite3_exec(*handle, users_create_sql, NULL, NULL, &err) != SQLITE_OK || - sqlite3_exec(*handle, databases_create_sql, NULL, NULL, &err) != SQLITE_OK || - sqlite3_exec(*handle, pragma_sql, NULL, NULL, &err) != SQLITE_OK) + else { - MXS_ERROR("Failed to create database: %s", err); - sqlite3_free(err); - sqlite3_close_v2(*handle); - return false; + char *err; + + if (sqlite3_exec(*handle, users_create_sql, NULL, NULL, &err) != SQLITE_OK || + sqlite3_exec(*handle, databases_create_sql, NULL, NULL, &err) != SQLITE_OK) + { + MXS_ERROR("Failed to create database: %s", err); + sqlite3_free(err); + sqlite3_close_v2(*handle); + rval = false; + } + else if (sqlite3_exec(*handle, pragma_sql, NULL, NULL, &err) != SQLITE_OK) + { + sqlite3_free(err); + MXS_NOTICE("Could not open SQLite database in WAL mode, using in-memory mode"); + + if (sqlite3_exec(*handle, old_pragma_sql, NULL, NULL, &err) != SQLITE_OK) + { + MXS_ERROR("Failed to set in-memory mode: %s", err); + sqlite3_free(err); + sqlite3_close_v2(*handle); + rval = false; + } + } } - return true; + return rval; } static bool open_client_database(const char *path, sqlite3 **handle) diff --git a/server/modules/authenticator/MySQLAuth/mysql_auth.h b/server/modules/authenticator/MySQLAuth/mysql_auth.h index ae289e202..2de5926f5 100644 --- a/server/modules/authenticator/MySQLAuth/mysql_auth.h +++ b/server/modules/authenticator/MySQLAuth/mysql_auth.h @@ -58,7 +58,8 @@ static const char databases_create_sql[] = "CREATE TABLE IF NOT EXISTS " MYSQLAUTH_DATABASES_TABLE_NAME "(db varchar(255))"; /** PRAGMA configuration options for SQLite */ -static const char pragma_sql[] = "PRAGMA JOURNAL_MODE=MEMORY"; +static const char pragma_sql[] = "PRAGMA journal_mode=WAL"; +static const char old_pragma_sql[] = "PRAGMA journal_mode=MEMORY"; /** Query that checks if there's a grant for the user being authenticated */ static const char mysqlauth_validate_user_query[] = From 4cc4deeaf157a80030c96c607b1fe1fb5a5b3312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sun, 13 May 2018 21:25:16 +0300 Subject: [PATCH 2/2] MXS-1843: Test log throtting in a unique directory This rules out external influence as a reason for the test failure. --- server/core/test/testlogthrottling.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/server/core/test/testlogthrottling.cc b/server/core/test/testlogthrottling.cc index 685d8ea7b..12db4cfbb 100644 --- a/server/core/test/testlogthrottling.cc +++ b/server/core/test/testlogthrottling.cc @@ -34,7 +34,8 @@ using std::string; namespace { -const char LOGNAME[] = "/tmp/maxscale.log"; +const char LOGNAME[] = "maxscale.log"; +static string logfile; const size_t N_THREADS = 4; sem_t u_semstart; @@ -109,7 +110,7 @@ bool run(const MXS_LOG_THROTTLING& throttling, int priority, size_t n_generate, mxs_log_set_throttling(&throttling); // Causes message to be logged. mxs_log_flush_sync(); - ifstream in(LOGNAME); + ifstream in(logfile); in.seekg(0, ios_base::end); THREAD_ARG args[N_THREADS]; @@ -166,9 +167,13 @@ int main(int argc, char* argv[]) rc = sem_init(&u_semfinish, 0, 0); ensure(rc == 0); - unlink(LOGNAME); - if (mxs_log_init(NULL, "/tmp", MXS_LOG_TARGET_FS)) + char tmpbuf[] = "/tmp/maxscale_test_logthrottling_XXXXXX"; + char* logdir = mkdtemp(tmpbuf); + ensure(logdir); + logfile.assign(string{logdir} + '/' + LOGNAME); + + if (mxs_log_init(NULL, logdir, MXS_LOG_TARGET_FS)) { MXS_LOG_THROTTLING t; @@ -265,5 +270,10 @@ int main(int argc, char* argv[]) rc = EXIT_FAILURE; } + // A crude method to remove all files but it works + string cmd = "rm -r "; + cmd += logdir; + system(cmd.c_str()); + return rc; }