diff --git a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc index a15d5c298..a8cdb9727 100644 --- a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc +++ b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc @@ -1812,33 +1812,6 @@ char datadir_arg[OPTIONS_DATADIR_SIZE]; char language_arg[OPTIONS_LANGUAGE_SIZE]; -bool create_datadir(const char* base, char* datadir) -{ - bool created = false; - - if (snprintf(datadir, PATH_MAX, "%s/data%d", base, getpid()) < PATH_MAX) - { - int rc = mkdir(datadir, 0777); - - if ((rc == 0) || (errno == EEXIST)) - { - created = true; - } - else - { - char errbuf[STRERROR_BUFLEN]; - fprintf(stderr, "MaxScale: error: Cannot create data directory '%s': %d %s\n", - datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); - } - } - else - { - fprintf(stderr, "MaxScale: error: Too long data directory: %s/data%d.", base, getpid()); - } - - return created; -} - void configure_options(const char* datadir, const char* langdir) { int rv; @@ -1861,7 +1834,6 @@ void configure_options(const char* datadir, const char* langdir) bool qc_init(void) { bool inited = false; - char datadir[PATH_MAX]; if (strlen(get_langdir()) >= PATH_MAX) { @@ -1869,25 +1841,22 @@ bool qc_init(void) } else { - if (create_datadir(get_datadir(), datadir)) + configure_options(get_process_datadir(), get_langdir()); + + int argc = N_OPTIONS; + char** argv = const_cast(server_options); + char** groups = const_cast(server_groups); + + int rc = mysql_library_init(argc, argv, groups); + + if (rc != 0) { - configure_options(datadir, get_langdir()); - - int argc = N_OPTIONS; - char** argv = const_cast(server_options); - char** groups = const_cast(server_groups); - - int rc = mysql_library_init(argc, argv, groups); - - if (rc != 0) - { - MXS_ERROR("mysql_library_init() failed. Error code: %d", rc); - } - else - { - MXS_NOTICE("Query classifier initialized."); - inited = true; - } + MXS_ERROR("mysql_library_init() failed. Error code: %d", rc); + } + else + { + MXS_NOTICE("Query classifier initialized."); + inited = true; } } diff --git a/server/core/gateway.c b/server/core/gateway.c index e0d11c71f..5c4192275 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -439,7 +439,54 @@ static int signal_set(int sig, void (*handler)(int)) return rc; } +/** + * @brief Create the data directory for this process + * + * This will prevent conflicts when multiple MaxScale instances are run on the + * same machine. + * @param base Base datadir path + * @param datadir The result where the process specific datadir is stored + * @return True if creation was successful and false on error + */ +static bool create_datadir(const char* base, char* datadir) +{ + bool created = false; + int len = 0; + if ((len = snprintf(datadir, PATH_MAX, "%s", base)) < PATH_MAX && + (mkdir(datadir, 0777) == 0 || errno == EEXIST)) + { + if ((len = snprintf(datadir, PATH_MAX, "%s/data%d", base, getpid())) < PATH_MAX) + { + if ((mkdir(datadir, 0777) == 0) || (errno == EEXIST)) + { + created = true; + } + else + { + char errbuf[STRERROR_BUFLEN]; + MXS_ERROR("Cannot create data directory '%s': %d %s\n", + datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + } + } + } + else + { + if (len < PATH_MAX) + { + char errbuf[STRERROR_BUFLEN]; + fprintf(stderr, "Error: Cannot create data directory '%s': %d %s\n", + datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + } + else + { + MXS_ERROR("Data directory pathname exceeds the maximum allowed pathname " + "length: %s/data%d.", base, getpid()); + } + } + + return created; +} /** * Cleanup the temporary data directory we created for the gateway @@ -456,23 +503,28 @@ int ntfw_cb(const char* filename, int eno = errno; errno = 0; char errbuf[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))); + MXS_ERROR("Failed to remove the data directory %s of MaxScale due to %d, %s.", + datadir, eno, strerror_r(eno, errbuf, sizeof(errbuf))); } return rc; } -void datadir_cleanup() +/** + * @brief Clean up the data directory + * + * This removes the process specific datadir which is currently only used by + * the embedded library. In the future this directory could contain other + * temporary files and relocating this to to, for example, /tmp/ could make sense. + */ +void cleanup_process_datadir() { int depth = 1; int flags = FTW_CHDIR|FTW_DEPTH|FTW_MOUNT; + const char *proc_datadir = get_process_datadir(); - if (datadir[0] != 0 && access(datadir, F_OK) == 0) + if (strcmp(proc_datadir, get_datadir()) != 0 && access(proc_datadir, F_OK) == 0) { - nftw(datadir, ntfw_cb, depth, flags); + nftw(proc_datadir, ntfw_cb, depth, flags); } } @@ -1235,7 +1287,7 @@ int main(int argc, char **argv) ssize_t log_flush_timeout_ms = 0; sigset_t sigpipe_mask; sigset_t saved_mask; - void (*exitfunp[4])(void) = { mxs_log_finish, datadir_cleanup, write_footer, NULL }; + void (*exitfunp[4])(void) = { mxs_log_finish, cleanup_process_datadir, write_footer, NULL }; *syslog_enabled = 1; *maxlog_enabled = 1; @@ -1718,23 +1770,20 @@ int main(int argc, char **argv) } /* - * Set a data directory for the mysqld library, we use - * a unique directory name to avoid clauses if multiple - * instances of the gateway are being run on the same - * machine. + * Set the data directory for the mysqld library. We use + * a unique directory name to avoid conflicts if multiple + * instances of MaxScale are being run on the same machine. */ - - snprintf(datadir, PATH_MAX, "%s", get_datadir()); - datadir[PATH_MAX] = '\0'; - if (mkdir(datadir, 0777) != 0){ - - if (errno != EEXIST){ - char errbuf[STRERROR_BUFLEN]; - fprintf(stderr, - "Error: Cannot create data directory '%s': %d %s\n", - datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); - goto return_main; - } + if (create_datadir(get_datadir(), datadir)) + { + set_process_datadir(datadir); + } + else + { + char errbuf[STRERROR_BUFLEN]; + MXS_ERROR("Cannot create data directory '%s': %d %s\n", + datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf))); + goto return_main; } if (!daemon_mode) @@ -1946,7 +1995,7 @@ int main(int argc, char **argv) qc_end(); utils_end(); - datadir_cleanup(); + cleanup_process_datadir(); MXS_NOTICE("MaxScale shutdown completed."); unload_all_modules(); diff --git a/server/core/gwdirs.c b/server/core/gwdirs.c index 970ec603f..9b28ccc73 100644 --- a/server/core/gwdirs.c +++ b/server/core/gwdirs.c @@ -85,6 +85,17 @@ void set_datadir(char* param) maxscaledatadir = param; } +/** + * Set the data directory + * @param str Path to directory + */ +void set_process_datadir(char* param) +{ + free(processdatadir); + clean_up_pathname(param); + processdatadir = param; +} + /** * Set the library directory. Modules will be loaded from here. * @param str Path to directory @@ -127,14 +138,23 @@ char* get_cachedir() } /** - * Get the service cache directory - * @return The path to the cache directory + * Get the MaxScale data directory + * @return The path to the data directory */ char* get_datadir() { return maxscaledatadir ? maxscaledatadir : (char*) default_datadir; } +/** + * Get the process specific data directory + * @return The path to the process specific directory + */ +char* get_process_datadir() +{ + return processdatadir ? processdatadir : (char*) default_datadir; +} + /** * Get the configuration file directory * @return The path to the configuration file directory diff --git a/server/include/gwdirs.h.in b/server/include/gwdirs.h.in index 440cd56b3..61a624790 100644 --- a/server/include/gwdirs.h.in +++ b/server/include/gwdirs.h.in @@ -35,7 +35,7 @@ static const char* default_configdir = "/etc"; * uses /run for PID files.*/ static const char* default_piddir = "@MAXSCALE_VARDIR@/run/maxscale"; static const char* default_logdir = "@MAXSCALE_VARDIR@/log/maxscale"; -static const char* default_datadir = "@MAXSCALE_VARDIR@/lib/maxscale/data"; +static const char* default_datadir = "@MAXSCALE_VARDIR@/lib/maxscale"; static const char* default_libdir = "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_LIBDIR@"; static const char* default_cachedir = "@MAXSCALE_VARDIR@/cache/maxscale"; static const char* default_langdir = "@MAXSCALE_VARDIR@/lib/maxscale"; @@ -45,13 +45,15 @@ static char* configdir = NULL; static char* logdir = NULL; static char* libdir = NULL; static char* cachedir = NULL; -static char* maxscaledatadir = NULL; +static char* maxscaledatadir = NULL; /*< The data directory */ +static char* processdatadir = NULL; /*< Process specific data directory */ static char* langdir = NULL; static char* piddir = NULL; static char* execdir = NULL; void set_libdir(char* param); void set_datadir(char* param); +void set_process_datadir(char* param); void set_cachedir(char* param); void set_configdir(char* param); void set_logdir(char* param); @@ -60,6 +62,7 @@ void set_piddir(char* param); void set_execdir(char* param); char* get_libdir(); char* get_datadir(); +char* get_process_datadir(); char* get_cachedir(); char* get_configdir(); char* get_piddir();