MXS-589: Separated persistent and temporary data directories

Both the passwords and temporary files of the embedded library were stored
in the same directory. Now the directories are separated and the embedded
library uses the temporary directory. The datadir cleanup also now only
cleans up the temporary data directory.
This commit is contained in:
Markus Makela 2016-02-25 10:43:16 +02:00
parent 7b8200eec0
commit 18526c28f6
4 changed files with 117 additions and 76 deletions

View File

@ -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<char**>(server_options);
char** groups = const_cast<char**>(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<char**>(server_options);
char** groups = const_cast<char**>(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;
}
}

View File

@ -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();

View File

@ -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

View File

@ -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();