it merges an updated upstream into a topic branch.
This commit is contained in:
Markus Makela
2014-10-14 13:45:00 +03:00
4 changed files with 317 additions and 172 deletions

View File

@ -270,12 +270,14 @@ static void blockbuf_register(blockbuf_t* bb);
static void blockbuf_unregister(blockbuf_t* bb);
static bool logfile_set_enabled(logfile_id_t id, bool val);
static char* add_slash(char* str);
static bool file_exists_and_is_writable(char* filename, bool* writable);
static bool check_file_and_path(
char* filename,
bool* nameconflict,
bool* writable);
static bool file_is_symlink(char* filename);
const char* get_suffix_default(void)
{
return ".log";
@ -356,11 +358,6 @@ static bool logmanager_init_nomutex(
fw = &lm->lm_filewriter;
fn->fn_state = UNINIT;
fw->fwr_state = UNINIT;
/**
* Set global variable
*/
lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles;
/** Initialize configuration including log file naming info */
if (!fnames_conf_init(fn, argc, argv)) {
@ -368,14 +365,23 @@ static bool logmanager_init_nomutex(
}
/** Initialize logfiles */
if(!logfiles_init(lm)) {
goto return_succp;
if(!logfiles_init(lm))
{
err = 1;
goto return_succp;
}
/** Initialize filewriter data and open the (first) log file(s)
/**
* Set global variable
*/
lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles;
/** Initialize filewriter data and open the (first) log file(s)
* for each log file type. */
if (!filewriter_init(lm, fw, lm->lm_clientmes, lm->lm_logmes)) {
goto return_succp;
if (!filewriter_init(lm, fw, lm->lm_clientmes, lm->lm_logmes))
{
err = 1;
goto return_succp;
}
/** Initialize and start filewriter thread */
@ -383,8 +389,9 @@ static bool logmanager_init_nomutex(
thr_filewriter_fun,
(void *)fw);
if ((err = skygw_thread_start(fw->fwr_thread)) != 0) {
goto return_succp;
if ((err = skygw_thread_start(fw->fwr_thread)) != 0)
{
goto return_succp;
}
/** Wait message from filewriter_thr */
skygw_message_wait(fw->fwr_clientmes);
@ -393,10 +400,11 @@ static bool logmanager_init_nomutex(
lm->lm_enabled = true;
return_succp:
if (err != 0) {
if (err != 0)
{
/** This releases memory of all created objects */
logmanager_done_nomutex();
fprintf(stderr, "* Initializing logmanager failed.\n");
fprintf(stderr, "*\n* Error : Initializing log manager failed.\n*\n");
}
return succp;
}
@ -1769,7 +1777,7 @@ static bool logfiles_init(
write_syslog);
if (!succp) {
fprintf(stderr, "Initializing logfiles failed\n");
fprintf(stderr, "*\n* Error : Initializing log files failed.\n");
break;
}
lid <<= 1;
@ -1917,10 +1925,11 @@ static char* add_slash(
return str;
}
/**
* @node Check if the file exists in the local file system and if it does,
* whether it is writable.
*
/**
* @node Check if the path and file exist in the local file system and if they do,
* check if they are accessible and writable.
*
* Parameters:
* @param filename - <usage>
* <description>
@ -1928,55 +1937,91 @@ static char* add_slash(
* @param writable - <usage>
* <description>
*
* @return
* @return true & writable if file exists and it is writable,
* true & not writable if file exists but it can't be written,
* false & writable if file doesn't exist but directory could be written, and
* false & not writable if directory can't be written.
*
*
* @details Note, that an space character is written to the end of file.
* @details Note, that a space character is written to the end of file.
* TODO: recall what was the reason for not succeeding with simply
* calling access, and fstat. vraa 26.11.13
*
*/
static bool file_exists_and_is_writable(
char* filename,
bool* writable)
static bool check_file_and_path(
char* filename,
bool* writable)
{
int fd;
bool exists = true;
if (filename == NULL)
{
exists = false;
}
else
{
fd = open(filename, O_CREAT|O_EXCL, S_IRWXU);
/** file exist */
if (fd == -1)
{
/** Open file and write a byte for test */
fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG);
if (fd != -1)
{
char c = ' ';
if (write(fd, &c, 1) == 1)
{
*writable = true;
}
close(fd);
}
}
else
{
close(fd);
unlink(filename);
exists = false;
}
}
return exists;
int fd;
bool exists;
if (filename == NULL)
{
exists = false;
*writable = false;
}
else
{
fd = open(filename, O_CREAT|O_EXCL, S_IRWXU);
if (fd == -1)
{
/** File exists, check permission to read/write */
if (errno == EEXIST)
{
/** Open file and write a byte for test */
fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG);
if (fd == -1)
{
fprintf(stderr,
"*\n* Error : Can't access %s due "
"to %s.\n",
filename,
strerror(errno));
*writable = false;
}
else
{
char c = ' ';
if (write(fd, &c, 1) == 1)
{
*writable = true;
}
else
{
fprintf(stderr,
"*\n* Error : Can't write to "
"%s due to %s.\n",
filename,
strerror(errno));
*writable = false;
}
close(fd);
}
exists = true;
}
else
{
fprintf(stderr,
"*\n* Error : Can't access %s due to %s.\n",
filename,
strerror(errno));
exists = false;
*writable = false;
}
}
else
{
close(fd);
unlink(filename);
exists = false;
*writable = true;
}
}
return exists;
}
static bool file_is_symlink(
char* filename)
{
@ -2112,7 +2157,8 @@ static bool logfile_init(
logfile->lf_full_file_name =
form_full_file_name(strparts, logfile->lf_name_seqno, 2);
if (store_shmem) {
if (store_shmem)
{
strparts[0].sp_string = logfile->lf_linkpath;
/**
* Create name for link file
@ -2121,17 +2167,7 @@ static bool logfile_init(
form_full_file_name(strparts,
logfile->lf_name_seqno,
2);
fprintf(stderr, "%s\t: %s->%s\n",
STRLOGNAME(logfile_id),
logfile->lf_full_link_name,
logfile->lf_full_file_name);
}
else
{
fprintf(stderr, "%s\t: %s\n",
STRLOGNAME(logfile_id),
logfile->lf_full_file_name);
}
/**
* At least one of the files couldn't be created. Increase
* sequence number and retry until succeeds.
@ -2147,32 +2183,57 @@ static bool logfile_init(
* If file exists but is different type, create fails and
* new, increased sequence number is added to file name.
*/
if (file_exists_and_is_writable(logfile->lf_full_file_name,
&writable))
{
if (!writable ||
file_is_symlink(logfile->lf_full_file_name))
{
nameconflicts = true;
goto file_create_fail;
}
}
if (store_shmem)
{
writable = false;
if (check_file_and_path(
logfile->lf_full_file_name,
&writable))
{
/** Found similarly named file which isn't writable */
if (!writable ||
file_is_symlink(logfile->lf_full_file_name))
{
nameconflicts = true;
goto file_create_fail;
}
}
else
{
/**
* Opening the file failed for some other reason than
* existing non-writable file. Shut down.
*/
if (!writable)
{
succp = false;
goto return_with_succp;
}
}
if (file_exists_and_is_writable(
logfile->lf_full_link_name,
&writable))
{
if (!writable ||
!file_is_symlink(logfile->lf_full_link_name))
{
nameconflicts = true;
goto file_create_fail;
}
}
if (store_shmem)
{
if (check_file_and_path(
logfile->lf_full_file_name,
&writable))
{
/** Found similarly named file which isn't writable */
if (!writable ||
file_is_symlink(logfile->lf_full_file_name))
{
nameconflicts = true;
goto file_create_fail;
}
}
else
{
/**
* Opening the file failed for some other reason than
* existing non-writable file. Shut down.
*/
if (!writable)
{
succp = false;
goto return_with_succp;
}
}
}
file_create_fail:
if (namecreatefail || nameconflicts)
@ -2189,7 +2250,6 @@ file_create_fail:
free(logfile->lf_full_link_name);
logfile->lf_full_link_name = NULL;
}
goto return_with_succp;
}
} while (namecreatefail || nameconflicts);
/**
@ -2203,11 +2263,24 @@ file_create_fail:
MAXNBLOCKBUFS) == NULL)
{
ss_dfprintf(stderr,
"Initializing logfile blockbuf list "
"failed\n");
"*\n* Error : Initializing buffers for log files "
"failed.");
logfile_free_memory(logfile);
goto return_with_succp;
}
if (store_shmem)
{
fprintf(stderr, "%s\t: %s->%s\n",
STRLOGNAME(logfile_id),
logfile->lf_full_link_name,
logfile->lf_full_file_name);
}
else
{
fprintf(stderr, "%s\t: %s\n",
STRLOGNAME(logfile_id),
logfile->lf_full_file_name);
}
succp = true;
logfile->lf_state = RUN;
CHK_LOGFILE(logfile);
@ -2245,12 +2318,18 @@ static void logfile_done(
{
switch(lf->lf_state) {
case RUN:
CHK_LOGFILE(lf);
ss_dassert(lf->lf_npending_writes == 0);
CHK_LOGFILE(lf);
ss_dassert(lf->lf_npending_writes == 0);
/** fallthrough */
case INIT:
mlist_done(&lf->lf_blockbuf_list);
logfile_free_memory(lf);
lf->lf_state = DONE;
/** Test if list is initialized before freeing it */
if (lf->lf_blockbuf_list.mlist_versno != 0)
{
mlist_done(&lf->lf_blockbuf_list);
}
logfile_free_memory(lf);
lf->lf_state = DONE;
/** fallthrough */
case DONE:
case UNINIT:
default:

View File

@ -73,7 +73,9 @@
#include <execinfo.h>
/** for procname */
#define _GNU_SOURCE
#if !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif
extern char *program_invocation_name;
extern char *program_invocation_short_name;
@ -174,6 +176,9 @@ static bool resolve_maxscale_conf_fname(
char* cnf_file_arg);
static bool resolve_maxscale_homedir(
char** p_home_dir);
static char* check_dir_access(char* dirname);
/**
* Handler for SIGHUP signal. Reload the configuration for the
* gateway.
@ -593,65 +598,45 @@ static bool resolve_maxscale_homedir(
if (*p_home_dir != NULL)
{
log_context = strdup("Current working directory");
goto check_home_dir;
}
check_home_dir:
if (*p_home_dir != NULL)
{
if (!file_is_readable(*p_home_dir))
{
char* tailstr = "MaxScale doesn't have read permission "
"to MAXSCALE_HOME.";
char* logstr = (char*)malloc(strlen(log_context)+
1+
strlen(tailstr)+
1);
snprintf(logstr,
strlen(log_context)+
1+
strlen(tailstr)+1,
"%s:%s",
log_context,
tailstr);
print_log_n_stderr(true, true, logstr, logstr, 0);
free(logstr);
goto return_succp;
}
if (!file_is_writable(*p_home_dir))
{
char* tailstr = "MaxScale doesn't have write permission "
"to MAXSCALE_HOME. Exiting.";
char* logstr = (char*)malloc(strlen(log_context)+
1+
strlen(tailstr)+
1);
snprintf(logstr,
strlen(log_context)+
1+
strlen(tailstr)+1,
"%s:%s",
log_context,
tailstr);
print_log_n_stderr(true, true, logstr, logstr, 0);
free(logstr);
goto return_succp;
}
if (!daemon_mode)
{
fprintf(stderr,
"Using %s as MAXSCALE_HOME = %s\n",
log_context,
tmp);
}
succp = true;
goto return_succp;
}
return_succp:
free (tmp);
if (*p_home_dir != NULL)
{
char* errstr;
errstr = check_dir_access(*p_home_dir);
if (errstr != NULL)
{
char* logstr = (char*)malloc(strlen(log_context)+
1+
strlen(errstr)+
1);
snprintf(logstr,
strlen(log_context)+
1+
strlen(errstr)+1,
"%s: %s",
log_context,
errstr);
print_log_n_stderr(true, true, logstr, logstr, 0);
free(errstr);
free(logstr);
}
else if (!daemon_mode)
{
fprintf(stderr,
"Using %s as MAXSCALE_HOME = %s\n",
log_context,
tmp);
}
}
free (tmp);
if (log_context != NULL)
{
@ -668,6 +653,42 @@ return_succp:
return succp;
}
/**
* Check read and write accessibility to a directory.
* @param dirname directory to be checked
*
* @return NULL if directory can be read and written, an error message if either
* read or write is not permitted.
*/
static char* check_dir_access(
char* dirname)
{
char* errstr = NULL;
if (dirname == NULL)
{
errstr = strdup("Directory argument is NULL");
goto retblock;
}
if (!file_is_readable(dirname))
{
errstr = strdup("MaxScale doesn't have read permission "
"to MAXSCALE_HOME.");
goto retblock;
}
if (!file_is_writable(dirname))
{
errstr = strdup("MaxScale doesn't have write permission "
"to MAXSCALE_HOME. Exiting.");
goto retblock;
}
retblock:
return errstr;
}
/**
* @node Provides error printing for non-formatted error strings.
@ -1378,6 +1399,44 @@ int main(int argc, char **argv)
sprintf(mysql_home, "%s/mysql", home_dir);
setenv("MYSQL_HOME", mysql_home, 1);
}
else
{
char* log_context = strdup("Home directory command-line argument");
char* errstr;
errstr = check_dir_access(home_dir);
if (errstr != NULL)
{
char* logstr = (char*)malloc(strlen(log_context)+
1+
strlen(errstr)+
1);
snprintf(logstr,
strlen(log_context)+
1+
strlen(errstr)+1,
"%s: %s",
log_context,
errstr);
print_log_n_stderr(true, true, logstr, logstr, 0);
free(errstr);
free(logstr);
rc = MAXSCALE_HOMELESS;
goto return_main;
}
else if (!daemon_mode)
{
fprintf(stderr,
"Using %s as MAXSCALE_HOME = %s\n",
log_context,
home_dir);
}
free(log_context);
}
/*<
* Init Log Manager for MaxScale.
@ -1387,8 +1446,9 @@ int main(int argc, char **argv)
* argv[0]
*/
{
char buf[1024];
char *argv[8];
char buf[1024];
char *argv[8];
bool succp;
sprintf(buf, "%s/log", home_dir);
mkdir(buf, 0777);
@ -1401,7 +1461,7 @@ int main(int argc, char **argv)
argv[4] = "LOGFILE_MESSAGE,LOGFILE_ERROR"
"LOGFILE_DEBUG,LOGFILE_TRACE";
argv[5] = NULL;
skygw_logmanager_init(5, argv);
succp = skygw_logmanager_init(5, argv);
}
else
{
@ -1410,7 +1470,13 @@ int main(int argc, char **argv)
argv[5] = "-l"; /*< write to syslog */
argv[6] = "LOGFILE_MESSAGE,LOGFILE_ERROR"; /*< ..these logs to syslog */
argv[7] = NULL;
skygw_logmanager_init(7, argv);
succp = skygw_logmanager_init(7, argv);
}
if (!succp)
{
rc = MAXSCALE_BADCONFIG;
goto return_main;
}
}

View File

@ -320,6 +320,7 @@ mlist_t* mlist_init(
list->mlist_nodecount_max = maxnodes;
/** Set data deletion callback fun */
list->mlist_datadel = datadel;
if (name != NULL) {
list->mlist_name = name;
}
@ -345,6 +346,7 @@ mlist_t* mlist_init(
CHK_MLIST_CURSOR(c);
*cursor = c;
}
list->mlist_versno = 2; /*< vresno != 0 means that list is initialized */
CHK_MLIST(list);
return_list:

View File

@ -52,9 +52,7 @@ typedef struct mlist_st {
bool mlist_deleted;
size_t mlist_nodecount;
size_t mlist_nodecount_max; /**< size limit. 0 == no limit */
#if 1
size_t mlist_versno;
#endif
bool mlist_flat;
mlist_node_t* mlist_first;
mlist_node_t* mlist_last;