log manager now spreads log writings 'down' so that LOGFILE_ERROR logs are duplicated in LOGFILE_MESSAGE, and in LOGFILE_TRACE, and LOGFILE_MESSAGE logs are duplicated in LOGFILE_TRACE.

This commit is contained in:
vraatikka
2013-08-20 10:43:54 +03:00
parent 2ad0b12d79
commit 76de8f3758
3 changed files with 169 additions and 91 deletions

View File

@ -194,7 +194,7 @@ static char* blockbuf_get_writepos(
static void blockbuf_register(blockbuf_t* bb);
static void blockbuf_unregister(blockbuf_t* bb);
static bool log_set_enabled(logfile_id_t id, bool val);
static bool logfile_set_enabled(logfile_id_t id, bool val);
const char* get_suffix_default(void)
@ -517,7 +517,9 @@ static int logmanager_write_log(
char* wp;
int err = 0;
blockbuf_t* bb;
blockbuf_t* bb_c;
int timestamp_len;
int i;
CHK_LOGMANAGER(lm);
@ -554,60 +556,81 @@ static int logmanager_write_log(
ss_dassert(flush);
logfile_flush(lf); /**< here we wake up file writer */
} else {
int i;
timestamp_len = get_timestamp_len();
/**
* Write to target log. If spread_down == TRUE, then write also
* to all logs with greater logfile id.
* LOGFILE_ERROR = 1,
* LOGFILE_MESSAGE = 2,
* LOGFILE_TRACE = 4
*
* So everything written to error log will appear in message and
* trace log. Messages will be written in trace log.
* Seek write position and register to block buffer.
* Then print formatted string to write position.
*/
for (i=id; i<=LOGFILE_LAST; i<<=1) {
/**< Check if particular log is enabled */
if (!(lm->lm_enabled_logfiles & i)) {
continue;
}
/**
* Seek write position and register to block buffer.
* Then print formatted string to write position.
*/
wp = blockbuf_get_writepos(&bb,
(logfile_id_t)i,
timestamp_len-1+str_len,
flush);
/**
* Write timestamp with at most <timestamp_len> characters
* to wp
*/
timestamp_len = snprint_timestamp(wp, timestamp_len);
/**
* Write next string to overwrite terminating null character
* of the timestamp string.
*/
if (use_valist) {
vsnprintf(wp+timestamp_len-1, str_len, str, valist);
} else {
snprintf(wp+timestamp_len-1, str_len, str);
}
/** remove double line feed */
if (wp[timestamp_len-1+str_len-2] == '\n') {
wp[timestamp_len-1+str_len-2]=' ';
}
wp[timestamp_len-1+str_len-1]='\n';
/** lock-free unregistration, includes flush if bb_isfull */
blockbuf_unregister(bb);
if (!spread_down) {
break;
}
wp = blockbuf_get_writepos(&bb,
id,
timestamp_len-1+str_len,
flush);
/**
* Write timestamp with at most <timestamp_len> characters
* to wp
*/
timestamp_len = snprint_timestamp(wp, timestamp_len);
/**
* Write next string to overwrite terminating null character
* of the timestamp string.
*/
if (use_valist) {
vsnprintf(wp+timestamp_len-1, str_len, str, valist);
} else {
snprintf(wp+timestamp_len-1, str_len, str);
}
/** remove double line feed */
if (wp[timestamp_len-1+str_len-2] == '\n') {
wp[timestamp_len-1+str_len-2]=' ';
}
wp[timestamp_len-1+str_len-1]='\n';
if (spread_down) {
/**
* Write to target log. If spread_down == TRUE, then write
* also to all logs with greater logfile id.
* LOGFILE_ERROR = 1,
* LOGFILE_MESSAGE = 2,
* LOGFILE_TRACE = 4
*
* So everything written to error log will appear in
* message and trace log. Messages will be written in
* trace log.
*/
for (i=(id<<1); i<=LOGFILE_LAST; i<<=1) {
/** pointer to write buffer of larger-id log */
char* wp_c;
/**< Check if particular log is enabled */
if (!(lm->lm_enabled_logfiles & i)) {
continue;
}
/**
* Seek write position and register to block buffer.
* Then print formatted string to write position.
*/
wp_c = blockbuf_get_writepos(&bb_c,
(logfile_id_t)i,
timestamp_len-1+str_len,
flush);
/**
* Copy original string from block buffer to other
* logs' block buffers.
*/
snprintf(wp_c, timestamp_len+str_len, wp);
/** remove double line feed */
if (wp_c[timestamp_len-1+str_len-2] == '\n') {
wp_c[timestamp_len-1+str_len-2]=' ';
}
wp_c[timestamp_len-1+str_len-1]='\n';
/** lock-free unregistration, includes flush if
* bb_isfull */
blockbuf_unregister(bb_c);
}
} /* if (spread_down) */
blockbuf_unregister(bb);
}
return_err:
@ -886,8 +909,8 @@ int skygw_log_enable(
}
CHK_LOGMANAGER(lm);
if (log_set_enabled(id, TRUE)) {
lm->lm_enabled_logfiles |= id;
if (logfile_set_enabled(id, TRUE)) {
lm->lm_enabled_logfiles |= id;
}
logmanager_unregister();
@ -908,7 +931,7 @@ int skygw_log_disable(
}
CHK_LOGMANAGER(lm);
if (log_set_enabled(id, FALSE)) {
if (logfile_set_enabled(id, FALSE)) {
lm->lm_enabled_logfiles &= ~id;
}
@ -918,7 +941,7 @@ return_err:
}
static bool log_set_enabled(
static bool logfile_set_enabled(
logfile_id_t id,
bool val)
{
@ -973,7 +996,7 @@ static bool log_set_enabled(
if (err != 0) {
lf->lf_enabled = oldval;
fprintf(stderr,
"log_set_enabled failed. Writing notification to logfile %s "
"logfile_set_enabled failed. Writing notification to logfile %s "
"failed.\n ",
STRLOGID(id));
goto return_succp;
@ -1021,7 +1044,7 @@ int skygw_log_write_flush(
* Write log string to buffer and add to file write list.
*/
va_start(valist, str);
err = logmanager_write_log(id, TRUE, TRUE, FALSE, len, str, valist);
err = logmanager_write_log(id, TRUE, TRUE, TRUE, len, str, valist);
va_end(valist);
if (err != 0) {
@ -1057,8 +1080,8 @@ int skygw_log_write(
* If particular log is disabled only unregister and return.
*/
if (!(lm->lm_enabled_logfiles & id)) {
err = 1;
goto return_unregister;
err = 1;
goto return_unregister;
}
/**
* Find out the length of log string (to be formatted str).
@ -1074,7 +1097,7 @@ int skygw_log_write(
* Write log string to buffer and add to file write list.
*/
va_start(valist, str);
err = logmanager_write_log(id, FALSE, TRUE, FALSE, len, str, valist);
err = logmanager_write_log(id, FALSE, TRUE, TRUE, len, str, valist);
va_end(valist);
if (err != 0) {
@ -1107,11 +1130,7 @@ int skygw_log_flush(
fprintf(stderr, "skygw_log_flush failed.\n");
goto return_unregister;
}
#if 0
ss_dfprintf(stderr,
"skygw_log_flush : flushed %s successfully.\n",
STRLOGID(id));
#endif
return_unregister:
logmanager_unregister();
return_err:
@ -1691,6 +1710,7 @@ static void* thr_filewriter_fun(
/** Process all logfiles which have buffered writes. */
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i <<= 1) {
retry_flush_on_exit:
/**
* Get file pointer of current logfile.
*/
@ -1760,6 +1780,16 @@ static void* thr_filewriter_fun(
} while (vn1 != vn2);
} /* while (node != NULL) */
/**
* Writer's exit flag was set after checking it.
* Loop is restarted to ensure that all logfiles are flushed.
*/
if (!flushall_logfiles && skygw_thread_must_exit(thr)) {
flushall_logfiles = TRUE;
i = LOGFILE_FIRST;
goto retry_flush_on_exit;
}
} /* for */
} /* while (!skygw_thread_must_exit) */

View File

@ -24,7 +24,7 @@ testcomp:
-L$(LOG_MANAGER_PATH) \
-Wl,-rpath,$(DEST)/lib \
-Wl,-rpath,$(LOG_MANAGER_PATH)/ \
-o testlog -DSS_DEBUG \
-o testlog \
-I$(MARIADB_SRC_PATH)/include \
-I$(LOG_MANAGER_PATH) -I$(ROOT_PATH)/utils testlog.c \
-llog_manager $(LDLIBS) \

View File

@ -98,22 +98,35 @@ int main(int argc, char* argv[])
err = skygw_log_flush(LOGFILE_ERROR);
logstr = "My name is %s %d years and %d months.";
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
err = skygw_log_write(LOGFILE_TRACE, logstr, "TraceyTracey", 3, 7);
skygw_log_flush(LOGFILE_TRACE);
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = "My name is Tracey Tracey 47 years and 7 months.";
err = skygw_log_write(LOGFILE_TRACE, logstr);
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = "My name is Stacey %s";
err = skygw_log_write_flush(LOGFILE_TRACE, logstr, " ");
skygw_logmanager_done();
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = "My name is Philip";
err = skygw_log_write(LOGFILE_TRACE, logstr);
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = "Philip.";
err = skygw_log_write(LOGFILE_TRACE, logstr);
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = "Ph%dlip.";
err = skygw_log_write(LOGFILE_TRACE, logstr, 1);
@ -242,12 +255,19 @@ int main(int argc, char* argv[])
/**
* Test enable/disable log.
*/
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = ("\tTEST 3 - test enabling and disabling logs.");
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
r = skygw_logmanager_init(argc, argv);
ss_dassert(r);
skygw_log_disable(LOGFILE_TRACE);
logstr = ("1.\tWrite to ERROR and MESSAGE logs.");
logstr = ("1.\tWrite once to ERROR and twice to MESSAGE log.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
@ -257,7 +277,8 @@ int main(int argc, char* argv[])
skygw_log_enable(LOGFILE_TRACE);
logstr = ("2.\tWrite to ERROR and MESSAGE and TRACE logs.");
logstr = ("2.\tWrite to once to ERROR, twice to MESSAGE and "
"three times to TRACE log.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
@ -267,7 +288,7 @@ int main(int argc, char* argv[])
skygw_log_disable(LOGFILE_ERROR);
logstr = ("3.\tWrite to MESSAGE and TRACE logs.");
logstr = ("3.\tWrite to once to MESSAGE and twice to TRACE log.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
@ -289,7 +310,7 @@ int main(int argc, char* argv[])
skygw_log_enable(LOGFILE_ERROR);
skygw_log_enable(LOGFILE_MESSAGE);
logstr = ("4.\tWrite to ERROR and MESSAGE logs.");
logstr = ("4.\tWrite once to ERROR and twice to MESSAGE log.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
err = skygw_log_write(LOGFILE_TRACE, logstr);
@ -302,29 +323,36 @@ int main(int argc, char* argv[])
#endif /* TEST 3 */
#if defined(TEST4)
r = skygw_logmanager_init(argc, argv);
ss_dassert(r);
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = ("\tTEST 4 - test spreading logs down to other logs.");
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
logstr = ("1.\tWrite to ERROR and thus also to MESSAGE and TRACE logs.");
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
logstr = ("1.\tWrite to MESSAGE and thus to TRACE logs.");
logstr = ("2.\tWrite to MESSAGE and thus to TRACE logs.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
logstr = ("1.\tWrite to TRACE log only.");
logstr = ("3.\tWrite to TRACE log only.");
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_log_disable(LOGFILE_MESSAGE);
logstr = ("1.\tWrite to ERROR and thus also to TRACE log. MESSAGE is disabled");
logstr = ("4.\tWrite to ERROR and thus also to TRACE log. "
"MESSAGE is disabled.");
err = skygw_log_write(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
logstr = ("1.\tThis should not appear anywhere since MESSAGE is disabled.");
logstr = ("5.\tThis should not appear anywhere since MESSAGE "
"is disabled.");
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err != 0);
@ -332,42 +360,51 @@ int main(int argc, char* argv[])
r = skygw_logmanager_init(argc, argv);
ss_dassert(r);
logstr = ("1.\tWrite to ERROR and thus also to MESSAGE and TRACE logs.");
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
logstr = ("6.\tWrite to ERROR and thus also to MESSAGE and TRACE logs.");
err = skygw_log_write_flush(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
logstr = ("1.\tWrite to MESSAGE and thus to TRACE logs.");
logstr = ("7.\tWrite to MESSAGE and thus to TRACE logs.");
err = skygw_log_write_flush(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
logstr = ("1.\tWrite to TRACE log only.");
logstr = ("8.\tWrite to TRACE log only.");
skygw_log_enable(LOGFILE_TRACE);
err = skygw_log_write_flush(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_log_disable(LOGFILE_MESSAGE);
logstr = ("1.\tWrite to ERROR and thus also to TRACE log. MESSAGE is disabled");
logstr = ("9.\tWrite to ERROR and thus also to TRACE log. "
"MESSAGE is disabled");
err = skygw_log_write_flush(LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
logstr = ("1.\tThis should not appear anywhere since MESSAGE is disabled.");
logstr = ("10.\tThis should not appear anywhere since MESSAGE is "
"disabled.");
err = skygw_log_write_flush(LOGFILE_MESSAGE, logstr);
ss_dassert(err != 0);
skygw_log_enable(LOGFILE_MESSAGE);
err = skygw_log_write(LOGFILE_ERROR,
"Write to all logs some formattings : %d %s %d",
"11.\tWrite to all logs some formattings : "
"%d %s %d",
(int)3,
"foo",
(int)3);
err = skygw_log_write(LOGFILE_MESSAGE,
"Write to MESSAGE and TRACE log some formattings "
"12.\tWrite to MESSAGE and TRACE log some "
"formattings "
": %d %s %d",
(int)3,
"foo",
(int)3);
err = skygw_log_write(LOGFILE_TRACE,
"Write to TRACE log some formattings "
"13.\tWrite to TRACE log some formattings "
": %d %s %d",
(int)3,
"foo",
@ -412,8 +449,10 @@ static void* thr_run(
skygw_logmanager_init( 0, NULL);
skygw_log_flush(LOGFILE_ERROR);
logstr = ("For automatic and register variables, it is done each time the function or block is entered.");
skygw_log_enable(LOGFILE_TRACE);
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
ss_dassert(err == 0);
skygw_logmanager_done();
skygw_logmanager_init( 0, NULL);
logstr = ("Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to *(a+i) immediately; the two forms are equivalent. Applying the operatos & to both parts of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the address of the i-th element beyond a.");
@ -430,6 +469,9 @@ static void* thr_run(
skygw_logmanager_init( 0, NULL);
skygw_logmanager_init( 0, NULL);
logstr = ("For automatic and register variables, it is done each time the function or block is entered.");
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_logmanager_init( 0, NULL);
@ -441,8 +483,14 @@ static void* thr_run(
err = skygw_log_write(LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
skygw_logmanager_done();
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
skygw_log_flush(LOGFILE_TRACE);
logstr = ("For automatic and register variables, it is done each time the function or block is entered.");
#if !defined(SS_DEBUG)
skygw_log_enable(LOGFILE_TRACE);
#endif
err = skygw_log_write(LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_logmanager_done();