From 03391748ee12ef484fe75b8ba5f32068404f3087 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Thu, 5 Jan 2017 16:17:50 +0200 Subject: [PATCH] Call [process|thread] [init|finish] functions of modules The process initialization function was also renamed from init to process_init. --- include/maxscale/modinfo.h | 4 +- server/core/gateway.cc | 175 +++++++++++++++++++++++++++++++++++-- 2 files changed, 168 insertions(+), 11 deletions(-) diff --git a/include/maxscale/modinfo.h b/include/maxscale/modinfo.h index c78daaace..b8a5ada92 100644 --- a/include/maxscale/modinfo.h +++ b/include/maxscale/modinfo.h @@ -120,13 +120,13 @@ typedef struct mxs_module * * @return 0 on success, non-zero on failure. */ - int (*init)(); + int (*process_init)(); /** * If non-NULL, this function is called once at process shutdown, provided * the call to @c init succeeded. */ - void (*finish)(); + void (*process_finish)(); /** * If non-NULL, this function is called once at the startup of every new thread. diff --git a/server/core/gateway.cc b/server/core/gateway.cc index ae7ef0bde..c42c9fdb3 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -185,6 +185,10 @@ static bool change_cwd(); static void log_exit_status(); static bool daemonize(); static bool sniff_configuration(const char* filepath); +static bool modules_process_init(); +static void modules_process_finish(); +static bool modules_thread_init(); +static void modules_thread_finish(); /** SSL multi-threading functions and structures */ @@ -970,26 +974,35 @@ static void usage(void) */ void worker_thread_main(void* arg) { - if (qc_thread_init()) + if (modules_thread_init()) { - /** Init mysql thread context for use with a mysql handle and a parser */ - if (mysql_thread_init() == 0) + if (qc_thread_init()) { - poll_waitevents(arg); + /** Init mysql thread context for use with a mysql handle and a parser */ + if (mysql_thread_init() == 0) + { + poll_waitevents(arg); - /** Release mysql thread context */ - mysql_thread_end(); + /** Release mysql thread context */ + mysql_thread_end(); + } + else + { + MXS_ERROR("Could not perform thread initialization for MySQL. Exiting thread."); + } + + qc_thread_end(); } else { - MXS_ERROR("Could not perform thread initialization for MySQL. Exiting thread."); + MXS_ERROR("Could not perform thread initialization for query classifier. Exiting thread."); } - qc_thread_end(); + modules_thread_finish(); } else { - MXS_ERROR("Could not perform thread initialization for query classifier. Exiting thread."); + MXS_ERROR("Could not perform thread initialization for all modules. Thread exits."); } } @@ -1945,6 +1958,15 @@ int main(int argc, char **argv) poll_init(); dcb_global_init(); + + /* Init MaxScale modules */ + if (!modules_process_init()) + { + MXS_ERROR("Failed to initialize all modules at startup. Exiting."); + rc = MAXSCALE_BADCONFIG; + goto return_main; + } + /** * Init mysql thread context for main thread as well. Needed when users * are queried from backends. @@ -2058,6 +2080,9 @@ int main(int argc, char **argv) /*< Stop all the monitors */ monitorStopAll(); + /*< Call finish on all modules. */ + modules_process_finish(); + log_exit_status(); MXS_NOTICE("MaxScale is shutting down."); /** Release mysql thread context*/ @@ -2807,3 +2832,135 @@ static bool sniff_configuration(const char* filepath) return rv == 0; } + +/** + * Calls init on all loaded modules. + * + * @return True, if all modules were successfully initialized. + */ +static bool modules_process_init() +{ + bool initialized = false; + + MXS_MODULE_ITERATOR i = mxs_module_iterator_get(NULL); + MXS_MODULE* module = NULL; + + while ((module = mxs_module_iterator_get_next(&i)) != NULL) + { + if (module->process_init) + { + int rc = (module->process_init)(); + + if (rc != 0) + { + break; + } + } + } + + if (module) + { + // If module is non-NULL it means that the initialization failed for + // that module. We now need to call finish on all modules that were + // successfully initialized. + MXS_MODULE* failed_module = module; + i = mxs_module_iterator_get(NULL); + + while ((module = mxs_module_iterator_get_next(&i)) != failed_module) + { + if (module->process_finish) + { + (module->process_finish)(); + } + } + } + else + { + initialized = true; + } + + return initialized; +} + +/** + * Calls process_finish on all loaded modules. + */ +static void modules_process_finish() +{ + MXS_MODULE_ITERATOR i = mxs_module_iterator_get(NULL); + MXS_MODULE* module = NULL; + + while ((module = mxs_module_iterator_get_next(&i)) != NULL) + { + if (module->process_finish) + { + (module->process_finish)(); + } + } +} + +/** + * Calls thread_init on all loaded modules. + * + * @return True, if all modules were successfully initialized. + */ +static bool modules_thread_init() +{ + bool initialized = false; + + MXS_MODULE_ITERATOR i = mxs_module_iterator_get(NULL); + MXS_MODULE* module = NULL; + + while ((module = mxs_module_iterator_get_next(&i)) != NULL) + { + if (module->thread_init) + { + int rc = (module->thread_init)(); + + if (rc != 0) + { + break; + } + } + } + + if (module) + { + // If module is non-NULL it means that the initialization failed for + // that module. We now need to call finish on all modules that were + // successfully initialized. + MXS_MODULE* failed_module = module; + i = mxs_module_iterator_get(NULL); + + while ((module = mxs_module_iterator_get_next(&i)) != failed_module) + { + if (module->thread_finish) + { + (module->thread_finish)(); + } + } + } + else + { + initialized = true; + } + + return initialized; +} + +/** + * Calls thread_finish on all loaded modules. + */ +static void modules_thread_finish() +{ + MXS_MODULE_ITERATOR i = mxs_module_iterator_get(NULL); + MXS_MODULE* module = NULL; + + while ((module = mxs_module_iterator_get_next(&i)) != NULL) + { + if (module->thread_finish) + { + (module->thread_finish)(); + } + } +}