Added functions skygw_log_enable(logfile_id_t) and skygw_log_disable(logfile_id_t) to Log manager API. By calling them log writing to any of predefined log files can be switched on or off.

Added simple test to testlog.c
This commit is contained in:
vraatikka
2013-08-08 23:38:00 +03:00
parent 1ab8420e91
commit 0ad25ba3ab
4 changed files with 247 additions and 20 deletions

View File

@ -87,13 +87,15 @@ typedef struct blockbuf_st {
skygw_chk_t bb_chk_tail; skygw_chk_t bb_chk_tail;
} blockbuf_t; } blockbuf_t;
/** logfile object corresponds to physical file(s) where /**
* logfile object corresponds to physical file(s) where
* certain log is written. * certain log is written.
*/ */
struct logfile_st { struct logfile_st {
skygw_chk_t lf_chk_top; skygw_chk_t lf_chk_top;
flat_obj_state_t lf_state; flat_obj_state_t lf_state;
bool lf_init_started; bool lf_init_started;
bool lf_enabled;
logmanager_t* lf_lmgr; logmanager_t* lf_lmgr;
/** fwr_logmes is for messages from log clients */ /** fwr_logmes is for messages from log clients */
skygw_message_t* lf_logmes; skygw_message_t* lf_logmes;
@ -130,6 +132,7 @@ struct fnames_conf_st {
struct logmanager_st { struct logmanager_st {
skygw_chk_t lm_chk_top; skygw_chk_t lm_chk_top;
bool lm_enabled; bool lm_enabled;
int lm_enabled_logfiles;
simple_mutex_t lm_mutex; simple_mutex_t lm_mutex;
size_t lm_nlinks; size_t lm_nlinks;
/** fwr_logmes is for messages from log clients */ /** fwr_logmes is for messages from log clients */
@ -190,6 +193,8 @@ static char* blockbuf_get_writepos(
static void blockbuf_register(blockbuf_t* bb); static void blockbuf_register(blockbuf_t* bb);
static void blockbuf_unregister(blockbuf_t* bb); static void blockbuf_unregister(blockbuf_t* bb);
static bool log_set_enabled(logfile_id_t id, bool val);
const char* get_suffix_default(void) const char* get_suffix_default(void)
{ {
@ -245,6 +250,8 @@ static bool logmanager_init_nomutex(
lm->lm_chk_tail = CHK_NUM_LOGMANAGER; lm->lm_chk_tail = CHK_NUM_LOGMANAGER;
lm->lm_clientmes = skygw_message_init(); lm->lm_clientmes = skygw_message_init();
lm->lm_logmes = skygw_message_init(); lm->lm_logmes = skygw_message_init();
lm->lm_enabled_logfiles |= LOGFILE_ERROR;
lm->lm_enabled_logfiles |= LOGFILE_MESSAGE;
fn = &lm->lm_fnames_conf; fn = &lm->lm_fnames_conf;
fw = &lm->lm_filewriter; fw = &lm->lm_filewriter;
fn->fn_state = UNINIT; fn->fn_state = UNINIT;
@ -276,6 +283,7 @@ static bool logmanager_init_nomutex(
} }
/** Wait message from filewriter_thr */ /** Wait message from filewriter_thr */
skygw_message_wait(fw->fwr_clientmes); skygw_message_wait(fw->fwr_clientmes);
succp = TRUE; succp = TRUE;
lm->lm_enabled = TRUE; lm->lm_enabled = TRUE;
@ -639,7 +647,6 @@ static char* blockbuf_get_writepos(
mlist_node_t* node; mlist_node_t* node;
blockbuf_t* bb; blockbuf_t* bb;
ss_debug(bool succp;) ss_debug(bool succp;)
ss_debug(int i=0;)
CHK_LOGMANAGER(lm); CHK_LOGMANAGER(lm);
@ -841,6 +848,114 @@ static blockbuf_t* blockbuf_init(
} }
int skygw_log_enable(
logfile_id_t id)
{
bool err = 0;
if (!logmanager_register(TRUE)) {
fprintf(stderr, "ERROR: Can't register to logmanager\n");
err = -1;
goto return_err;
}
CHK_LOGMANAGER(lm);
if (log_set_enabled(id, TRUE)) {
lm->lm_enabled_logfiles |= id;
}
logmanager_unregister();
return_err:
return err;
}
int skygw_log_disable(
logfile_id_t id)
{
bool err = 0;
if (!logmanager_register(TRUE)) {
fprintf(stderr, "ERROR: Can't register to logmanager\n");
err = -1;
goto return_err;
}
CHK_LOGMANAGER(lm);
if (log_set_enabled(id, FALSE)) {
lm->lm_enabled_logfiles &= ~id;
}
logmanager_unregister();
return_err:
return err;
}
static bool log_set_enabled(
logfile_id_t id,
bool val)
{
char* logstr;
va_list notused;
bool oldval;
bool succp = FALSE;
int err = 0;
logfile_t* lf;
CHK_LOGMANAGER(lm);
if (id < LOGFILE_FIRST || id > LOGFILE_LAST) {
char* errstr = "Invalid logfile id argument.";
/**
* invalid id, since we don't have logfile yet.
*/
err = logmanager_write_log(LOGFILE_ERROR,
TRUE,
FALSE,
strlen(errstr)+1,
errstr,
notused);
if (err != 0) {
fprintf(stderr,
"Writing to logfile %s failed.\n",
STRLOGID(LOGFILE_ERROR));
}
ss_dassert(FALSE);
goto return_succp;
}
lf = &lm->lm_logfile[id];
CHK_LOGFILE(lf);
if (val) {
logstr = strdup("---\tLogging is enabled\t--");
} else {
logstr = strdup("---\tLogging is disabled\t--");
}
oldval = lf->lf_enabled;
lf->lf_enabled = val;
err = logmanager_write_log(id,
TRUE,
FALSE,
strlen(logstr)+1,
logstr,
notused);
free(logstr);
if (err != 0) {
lf->lf_enabled = oldval;
fprintf(stderr,
"log_set_enabled failed. Writing notification to logfile %s "
"failed.\n ",
STRLOGID(id));
goto return_succp;
}
succp = TRUE;
return_succp:
return succp;
}
int skygw_log_write_flush( int skygw_log_write_flush(
logfile_id_t id, logfile_id_t id,
char* str, char* str,
@ -862,6 +977,13 @@ int skygw_log_write_flush(
STRLOGID(id), STRLOGID(id),
str); str);
#endif #endif
/**
* If particular log is disabled only unregister and return.
*/
if (!(lm->lm_enabled_logfiles & id)) {
err = 1;
goto return_unregister;
}
/** /**
* Find out the length of log string (to be formatted str). * Find out the length of log string (to be formatted str).
*/ */
@ -915,6 +1037,13 @@ int skygw_log_write(
STRLOGID(id), STRLOGID(id),
str); str);
#endif #endif
/**
* If particular log is disabled only unregister and return.
*/
if (!(lm->lm_enabled_logfiles & id)) {
err = 1;
goto return_unregister;
}
/** /**
* Find out the length of log string (to be formatted str). * Find out the length of log string (to be formatted str).
*/ */
@ -1228,19 +1357,20 @@ static char* fname_conf_get_suffix(
static bool logfiles_init( static bool logfiles_init(
logmanager_t* lmgr) logmanager_t* lm)
{ {
bool succp = TRUE; bool succp = TRUE;
int i = LOGFILE_FIRST; int i = LOGFILE_FIRST;
while(i<=LOGFILE_LAST && succp) { while(i<=LOGFILE_LAST && succp) {
succp = logfile_init(&lmgr->lm_logfile[i], (logfile_id_t)i, lmgr); succp = logfile_init(&lm->lm_logfile[i], (logfile_id_t)i, lm);
if (!succp) { if (!succp) {
fprintf(stderr, "Initializing logfiles failed\n"); fprintf(stderr, "Initializing logfiles failed\n");
break; break;
} }
i++; i <<= 1;
} }
return succp; return succp;
} }
@ -1278,6 +1408,7 @@ static bool logfile_init(
logfile->lf_lmgr = logmanager; logfile->lf_lmgr = logmanager;
logfile->lf_flushflag = FALSE; logfile->lf_flushflag = FALSE;
logfile->lf_spinlock = 0; logfile->lf_spinlock = 0;
logfile->lf_enabled = logmanager->lm_enabled_logfiles & logfile_id;
/** Read existing files to logfile->lf_files_list and create /** Read existing files to logfile->lf_files_list and create
* new file for log named after <directory>/<prefix><counter><suffix> * new file for log named after <directory>/<prefix><counter><suffix>
*/ */
@ -1397,6 +1528,7 @@ static bool filewriter_init(
logfile_t* lf; logfile_t* lf;
logfile_id_t id; logfile_id_t id;
int i; int i;
char* start_msg_str;
CHK_LOGMANAGER(logmanager); CHK_LOGMANAGER(logmanager);
@ -1412,7 +1544,7 @@ static bool filewriter_init(
if (fw->fwr_logmes == NULL || fw->fwr_clientmes == NULL) { if (fw->fwr_logmes == NULL || fw->fwr_clientmes == NULL) {
goto return_succp; goto return_succp;
} }
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i++) { for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i <<= 1) {
id = (logfile_id_t)i; id = (logfile_id_t)i;
lf = logmanager_get_logfile(logmanager, id); lf = logmanager_get_logfile(logmanager, id);
fw->fwr_file[id] = skygw_file_init(lf->lf_full_name); fw->fwr_file[id] = skygw_file_init(lf->lf_full_name);
@ -1420,6 +1552,16 @@ static bool filewriter_init(
if (fw->fwr_file[id] == NULL) { if (fw->fwr_file[id] == NULL) {
goto return_succp; goto return_succp;
} }
if (lf->lf_enabled) {
start_msg_str = strdup("---\tLogging is enabled.\n");
} else {
start_msg_str = strdup("---\tLogging is disabled.\n");
}
skygw_file_write(fw->fwr_file[id],
(void *)start_msg_str,
strlen(start_msg_str),
TRUE);
free(start_msg_str);
} }
fw->fwr_state = RUN; fw->fwr_state = RUN;
CHK_FILEWRITER(fw); CHK_FILEWRITER(fw);
@ -1534,7 +1676,7 @@ static void* thr_filewriter_fun(
flushall_logfiles = skygw_thread_must_exit(thr); flushall_logfiles = skygw_thread_must_exit(thr);
/** Process all logfiles which have buffered writes. */ /** Process all logfiles which have buffered writes. */
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i++) { for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i <<= 1) {
/** /**
* Get file pointer of current logfile. * Get file pointer of current logfile.
*/ */

View File

@ -23,16 +23,15 @@ typedef struct fnames_conf_st fnames_conf_t;
typedef struct logmanager_st logmanager_t; typedef struct logmanager_st logmanager_t;
typedef enum { typedef enum {
LOGFILE_TRACE = 0, LOGFILE_TRACE = 1,
LOGFILE_FIRST = LOGFILE_TRACE, LOGFILE_FIRST = LOGFILE_TRACE,
LOGFILE_MESSAGE, LOGFILE_MESSAGE = 2,
LOGFILE_ERROR, LOGFILE_ERROR = 4,
LOGFILE_LAST = LOGFILE_ERROR LOGFILE_LAST = LOGFILE_ERROR
} logfile_id_t; } logfile_id_t;
typedef enum { FILEWRITER_INIT, FILEWRITER_RUN, FILEWRITER_DONE } typedef enum { FILEWRITER_INIT, FILEWRITER_RUN, FILEWRITER_DONE }
filewriter_state_t; filewriter_state_t;
typedef enum { LOGFILE_INIT, LOGFILE_OPENED, LOGFILE_DONE } logfile_state_t;
/** /**
* UNINIT means zeroed memory buffer allocated for the struct. * UNINIT means zeroed memory buffer allocated for the struct.
@ -56,7 +55,8 @@ void skygw_log_done(void);
int skygw_log_write(logfile_id_t id, char* format, ...); int skygw_log_write(logfile_id_t id, char* format, ...);
int skygw_log_flush(logfile_id_t id); int skygw_log_flush(logfile_id_t id);
int skygw_log_write_flush(logfile_id_t id, char* format, ...); int skygw_log_write_flush(logfile_id_t id, char* format, ...);
int skygw_log_enable(logfile_id_t id);
int skygw_log_disable(logfile_id_t id);
EXTERN_C_BLOCK_END EXTERN_C_BLOCK_END

View File

@ -44,6 +44,9 @@ static void* thr_run_morelog(void* data);
#define TEST1 #define TEST1
#define TEST2 #define TEST2
#endif #endif
#define TEST3
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
int err = 0; int err = 0;
@ -175,7 +178,9 @@ int main(int argc, char* argv[])
free(thr[i]); free(thr[i]);
} }
#endif #endif
#if defined(TEST2) #if defined(TEST2)
fprintf(stderr, "\nStarting test #2 \n"); fprintf(stderr, "\nStarting test #2 \n");
/** 2 */ /** 2 */
@ -229,7 +234,70 @@ int main(int argc, char* argv[])
/** Test ended here */ /** Test ended here */
skygw_message_done(mes); skygw_message_done(mes);
simple_mutex_done(mtx); simple_mutex_done(mtx);
#endif #endif /* TEST 2 */
#if defined(TEST3)
/**
* Test enable/disable log.
*/
r = skygw_logmanager_init(argc, argv);
ss_dassert(r);
logstr = ("1.\tWrite to ERROR and MESSAGE logs.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err != 0); /**< Must fail */
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_log_enable(LOGFILE_TRACE);
logstr = ("2.\tWrite to ERROR and MESSAGE and TRACE logs.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_log_disable(LOGFILE_ERROR);
logstr = ("3.\tWrite to MESSAGE and TRACE logs.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err != 0); /**< Must fail */
skygw_log_disable(LOGFILE_MESSAGE);
skygw_log_disable(LOGFILE_TRACE);
logstr = ("4.\tWrite to none.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err != 0); /**< Must fail */
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err != 0); /**< Must fail */
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err != 0); /**< Must fail */
skygw_log_enable(LOGFILE_ERROR);
skygw_log_enable(LOGFILE_MESSAGE);
logstr = ("4.\tWrite to ERROR and MESSAGE logs.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err != 0); /**< Must fail */
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_logmanager_done();
#endif /* TEST 3 */
fprintf(stderr, ".. done.\n"); fprintf(stderr, ".. done.\n");
return err; return err;
} }

View File

@ -1503,12 +1503,15 @@ static bool file_write_header(
size_t wbytes1; size_t wbytes1;
size_t wbytes2; size_t wbytes2;
size_t wbytes3; size_t wbytes3;
size_t wbytes4;
size_t len1; size_t len1;
size_t len2; size_t len2;
size_t len3; size_t len3;
size_t len4;
const char* header_buf1; const char* header_buf1;
char* header_buf2 = NULL; char* header_buf2 = NULL;
const char* header_buf3; char* header_buf3 = NULL;
const char* header_buf4;
time_t* t; time_t* t;
struct tm* tm; struct tm* tm;
@ -1519,29 +1522,38 @@ static bool file_write_header(
CHK_FILE(file); CHK_FILE(file);
header_buf1 = "\n\nSkySQL MaxScale\t"; header_buf1 = "\n\nSkySQL MaxScale\t";
header_buf2 = strdup(asctime(tm)); header_buf2 = (char *)calloc(1, strlen(file->sf_fname)+2);
header_buf3 = "------------------------------------------\n"; snprintf(header_buf2, strlen(file->sf_fname)+2, "%s ", file->sf_fname);
header_buf3 = strdup(asctime(tm));
header_buf4 = "---------------------------------------------------------"
"---------------------------\n";
if (header_buf2 == NULL) { if (header_buf2 == NULL) {
goto return_succp; goto return_succp;
} }
if (header_buf3 == NULL) {
goto return_succp;
}
len1 = strlen(header_buf1); len1 = strlen(header_buf1);
len2 = strlen(header_buf2); len2 = strlen(header_buf2);
len3 = strlen(header_buf3); len3 = strlen(header_buf3);
len4 = strlen(header_buf4);
#if defined(LAPTOP_TEST) #if defined(LAPTOP_TEST)
usleep(DISKWRITE_LATENCY); usleep(DISKWRITE_LATENCY);
#else #else
wbytes1=fwrite((void*)header_buf1, len1, 1, file->sf_file); wbytes1=fwrite((void*)header_buf1, len1, 1, file->sf_file);
wbytes2=fwrite((void*)header_buf2, len2, 1, file->sf_file); wbytes2=fwrite((void*)header_buf2, len2, 1, file->sf_file);
wbytes3=fwrite((void*)header_buf3, len3, 1, file->sf_file); wbytes3=fwrite((void*)header_buf3, len3, 1, file->sf_file);
wbytes4=fwrite((void*)header_buf4, len4, 1, file->sf_file);
if (wbytes1 != 1 || wbytes2 != 1 || wbytes3 != 1) { if (wbytes1 != 1 || wbytes2 != 1 || wbytes3 != 1 || wbytes4 != 1) {
fprintf(stderr, fprintf(stderr,
"Writing header %s %s %s to %s failed.\n", "Writing header %s %s %s to %s failed.\n",
header_buf1, header_buf1,
header_buf2, header_buf2,
header_buf3, header_buf3,
file->sf_fname); header_buf4);
perror("Logfile header write.\n"); perror("Logfile header write.\n");
goto return_succp; goto return_succp;
} }
@ -1550,7 +1562,12 @@ static bool file_write_header(
succp = TRUE; succp = TRUE;
return_succp: return_succp:
free(header_buf2); if (header_buf2 != NULL) {
free(header_buf2);
}
if (header_buf3 != NULL) {
free(header_buf3);
}
free(t); free(t);
free(tm); free(tm);
return succp; return succp;