MAX-325, Log rotation functionality. When skygw_log_rotate is called, corresponding logfile's rotate flag (lf_rotateflag) is set and log writer thread is woken up. Writer opens a new log file and closes the old one.

This commit is contained in:
VilhoRaatikka 2014-11-12 14:48:17 +02:00
parent 8af97016bb
commit 780733f870
3 changed files with 418 additions and 283 deletions

View File

@ -162,7 +162,8 @@ struct logfile_st {
mlist_t lf_blockbuf_list;
int lf_buf_size;
bool lf_flushflag;
int lf_spinlock; /**< lf_flushflag */
bool lf_rotateflag;
int lf_spinlock; /**< lf_flushflag & lf_rotateflag */
int lf_npending_writes;
#if defined(SS_DEBUG)
skygw_chk_t lf_chk_tail;
@ -232,6 +233,11 @@ static bool logfile_init(
static void logfile_done(logfile_t* logfile);
static void logfile_free_memory(logfile_t* lf);
static void logfile_flush(logfile_t* lf);
static void logfile_rotate(logfile_t* lf);
static bool logfile_create(logfile_t* lf);
static bool logfile_open_file(filewriter_t* fw, logfile_t* lf);
static char* form_full_file_name(strpart_t* parts, int seqno, int seqnoidx);
static bool filewriter_init(
logmanager_t* logmanager,
filewriter_t* fw,
@ -249,14 +255,16 @@ static bool logmanager_register(bool writep);
static void logmanager_unregister(void);
static bool logmanager_init_nomutex(int argc, char* argv[]);
static void logmanager_done_nomutex(void);
static int logmanager_write_log(
logfile_id_t id,
bool flush,
bool use_valist,
bool spread_down,
size_t len,
const char* str,
va_list valist);
bool flush,
bool use_valist,
bool spread_down,
bool rotate,
size_t len,
const char* str,
va_list valist);
static blockbuf_t* blockbuf_init(logfile_id_t id);
static void blockbuf_node_done(void* bb_data);
@ -393,8 +401,10 @@ static bool logmanager_init_nomutex(
*/
lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles;
/** Initialize filewriter data and open the (first) log file(s)
* for each log file type. */
/**
* Initialize filewriter data and open the log file
* for each log file type.
*/
if (!filewriter_init(lm, fw, lm->lm_clientmes, lm->lm_logmes))
{
err = 1;
@ -629,6 +639,8 @@ static logfile_t* logmanager_get_logfile(
*
* @param spread_down - in, use
* if true, log string is spread to all logs having larger id.
*
* @param rotate if set, closes currently open log file and opens a new one
*
* @param str_len - in, use
* length of formatted string
@ -650,6 +662,7 @@ static int logmanager_write_log(
bool flush,
bool use_valist,
bool spread_down,
bool rotate,
size_t str_len,
const char* str,
va_list valist)
@ -673,6 +686,7 @@ static int logmanager_write_log(
true,
false,
false,
false,
strlen(errstr)+1,
errstr,
valist);
@ -689,14 +703,21 @@ static int logmanager_write_log(
CHK_LOGFILE(lf);
/**
* When string pointer is NULL, case is skygw_log_flush and no
* writing is involved. With flush && str != NULL case is
* skygw_log_write_flush.
* When string pointer is NULL, operation is either flush or rotate.
*/
if (str == NULL) {
ss_dassert(flush);
logfile_flush(lf); /**< here we wake up file writer */
} else {
if (str == NULL)
{
if (flush)
{
logfile_flush(lf); /*< wakes up file writer */
}
else if (rotate)
{
logfile_rotate(lf); /*< wakes up file writer */
}
}
else
{
/** Length of string that will be written, limited by bufsize */
int safe_str_len;
@ -704,14 +725,13 @@ static int logmanager_write_log(
/** Findout how much can be safely written with current block size */
if (timestamp_len-1+str_len > lf->lf_buf_size)
{
safe_str_len = lf->lf_buf_size;
}
{
safe_str_len = lf->lf_buf_size;
}
else
{
safe_str_len = timestamp_len-1+str_len;
}
{
safe_str_len = timestamp_len-1+str_len;
}
/**
* Seek write position and register to block buffer.
* Then print formatted string to write position.
@ -719,32 +739,26 @@ static int logmanager_write_log(
#if defined (SS_LOG_DEBUG)
{
char *copy,*tok;
int tokval;
char *copy,*tok;
int tokval;
simple_mutex_lock(&msg_mutex,true);
simple_mutex_lock(&msg_mutex,true);
copy = strdup(str);
tok = strtok(copy,"|");
tok = strtok(NULL,"|");
copy = strdup(str);
tok = strtok(copy,"|");
tok = strtok(NULL,"|");
if(strstr(str,"message|") && tok){
tokval = atoi(tok);
if(prevval > 0){
ss_dassert(tokval == (prevval + 1));
}
prevval = tokval;
}
free(copy);
simple_mutex_unlock(&msg_mutex);
if(strstr(str,"message|") && tok)
{
tokval = atoi(tok);
if(prevval > 0)
{
ss_dassert(tokval == (prevval + 1));
}
prevval = tokval;
}
free(copy);
simple_mutex_unlock(&msg_mutex);
}
#endif
@ -860,7 +874,7 @@ static int logmanager_write_log(
blockbuf_unregister(bb_c);
}
} /* if (spread_down) */
}
} /* if (str == NULL) */
return_err:
return err;
@ -1247,6 +1261,7 @@ static bool logfile_set_enabled(
true,
false,
false,
false,
strlen(errstr)+1,
errstr,
notused);
@ -1272,6 +1287,7 @@ static bool logfile_set_enabled(
true,
false,
false,
false,
strlen(logstr)+1,
logstr,
notused);
@ -1317,9 +1333,6 @@ int skygw_log_write_flush(
/**
* Find out the length of log string (to be formatted str).
*/
va_start(valist, str);
len = vsnprintf(NULL, 0, str, valist);
va_end(valist);
@ -1331,7 +1344,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, true, len, str, valist);
err = logmanager_write_log(id, true, true, true, false, len, str, valist);
va_end(valist);
if (err != 0) {
@ -1370,9 +1383,6 @@ int skygw_log_write(
err = 1;
goto return_unregister;
}
/**
* Find out the length of log string (to be formatted str).
*/
@ -1388,7 +1398,7 @@ int skygw_log_write(
*/
va_start(valist, str);
err = logmanager_write_log(id, false, true, true, len, str, valist);
err = logmanager_write_log(id, false, true, true, false, len, str, valist);
va_end(valist);
if (err != 0) {
@ -1415,7 +1425,7 @@ int skygw_log_flush(
goto return_err;
}
CHK_LOGMANAGER(lm);
err = logmanager_write_log(id, true, false, false, 0, NULL, valist);
err = logmanager_write_log(id, true, false, false, false, 0, NULL, valist);
if (err != 0) {
fprintf(stderr, "skygw_log_flush failed.\n");
@ -1428,12 +1438,14 @@ return_err:
return err;
}
/**
* Replace current logfile with new file with increased sequence number on
* its name.
*/
int skygw_log_rotate(
logfile_id_t id)
{
int err = 0;
goto return_err;
va_list valist; /**< Dummy, must be present but it is not processed */
@ -1443,14 +1455,14 @@ int skygw_log_rotate(
goto return_err;
}
CHK_LOGMANAGER(lm);
err = logmanager_write_log(id, true, false, false, 0, NULL, valist);
err = logmanager_write_log(id, false, false, false, true, 0, NULL, valist);
if (err != 0) {
fprintf(stderr, "skygw_log_flush failed.\n");
fprintf(stderr, "skygw_log_rotate failed.\n");
goto return_unregister;
}
return_unregister:
return_unregister:
logmanager_unregister();
return_err:
return err;
@ -1872,6 +1884,237 @@ static void logfile_flush(
skygw_message_send(lf->lf_logmes);
}
/**
* Set rotate flag for a log file and wake up the writer thread which then
* performs the actual rotation task.
*
* @param lf logfile pointer
*/
static void logfile_rotate(
logfile_t* lf)
{
CHK_LOGFILE(lf);
acquire_lock(&lf->lf_spinlock);
lf->lf_rotateflag = true;
release_lock(&lf->lf_spinlock);
skygw_message_send(lf->lf_logmes);
}
/**
* Forms complete path name for logfile and tests that the file doesn't conflict
* with any existing file and it is writable.
*
* @param lf logfile pointer
*
* @return true if succeed, false if failed
*/
static bool logfile_create(
logfile_t* lf)
{
bool namecreatefail;
bool nameconflicts;
bool store_shmem;
bool writable;
bool succp;
strpart_t spart[3]; /*< string parts of which the file is composed of */
/**
* sparts is an array but next pointers are used to walk through
* the list of string parts.
*/
spart[0].sp_next = &spart[1];
spart[1].sp_next = &spart[2];
spart[2].sp_next = NULL;
spart[1].sp_string = lf->lf_name_prefix;
spart[2].sp_string = lf->lf_name_suffix;
store_shmem = lf->lf_store_shmem;
do {
namecreatefail = false;
nameconflicts = false;
spart[0].sp_string = lf->lf_filepath;
/**
* Create name for log file. Seqno is added between prefix &
* suffix (index == 2)
*/
lf->lf_full_file_name =
form_full_file_name(spart, lf->lf_name_seqno, 2);
if (store_shmem)
{
spart[0].sp_string = lf->lf_linkpath;
/**
* Create name for link file
*/
lf->lf_full_link_name = form_full_file_name(
spart,
lf->lf_name_seqno,
2);
}
/**
* At least one of the files couldn't be created. Increase
* sequence number and retry until succeeds.
*/
if (lf->lf_full_file_name == NULL ||
(store_shmem && lf->lf_full_link_name == NULL))
{
namecreatefail = true;
goto file_create_fail;
}
/**
* If file exists but is different type, create fails and
* new, increased sequence number is added to file name.
*/
if (check_file_and_path(lf->lf_full_file_name, &writable))
{
/** Found similarly named file which isn't writable */
if (!writable || file_is_symlink(lf->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_succp;
}
}
if (store_shmem)
{
if (check_file_and_path(lf->lf_full_file_name, &writable))
{
/** Found similarly named file which isn't writable */
if (!writable ||
file_is_symlink(lf->lf_full_file_name))
{
unlink(lf->lf_full_file_name);
nameconflicts = true;
}
}
else
{
/**
* Opening the file failed for some other reason than
* existing non-writable file. Shut down.
*/
if (!writable)
{
succp = false;
goto return_succp;
}
}
}
file_create_fail:
if (namecreatefail || nameconflicts)
{
lf->lf_name_seqno += 1;
if (lf->lf_full_file_name != NULL)
{
free(lf->lf_full_file_name);
lf->lf_full_file_name = NULL;
}
if (lf->lf_full_link_name != NULL)
{
free(lf->lf_full_link_name);
lf->lf_full_link_name = NULL;
}
}
} while (namecreatefail || nameconflicts);
succp = true;
return_succp:
return succp;
}
/**
* Opens a log file and writes header to the beginning of it. File name, FILE*,
* and file descriptor are stored to skygw_file_t struct which is stored in
* filewriter strcuture passed as parameter.
*
* @param fw filewriter pointer
* @param lf logfile pointer
*
* @return true if succeed; the resulting skygw_file_t is written in filewriter,
* false if failed.
*
*/
static bool logfile_open_file(
filewriter_t* fw,
logfile_t* lf)
{
bool succp;
char* start_msg_str;
int err;
if (lf->lf_store_shmem)
{
/** Create symlink pointing to log file */
fw->fwr_file[lf->lf_id] = skygw_file_init(
lf->lf_full_file_name,
lf->lf_full_link_name);
}
else
{
/** Create normal disk-resident log file */
fw->fwr_file[lf->lf_id] = skygw_file_init(
lf->lf_full_file_name,
NULL);
}
if (fw->fwr_file[lf->lf_id] == NULL)
{
fprintf(stderr,
"Error : opening logfile %s failed.\n",
lf->lf_full_file_name);
succp = false;
goto return_succp;
}
if (lf->lf_enabled)
{
start_msg_str = strdup("---\tLogging is enabled.\n");
}
else
{
start_msg_str = strdup("---\tLogging is disabled.\n");
}
err = skygw_file_write(fw->fwr_file[lf->lf_id],
(void *)start_msg_str,
strlen(start_msg_str),
true);
if (err != 0)
{
fprintf(stderr,
"Error : writing to file %s failed due to %d, %s. "
"Exiting MaxScale.\n",
lf->lf_full_file_name,
err,
strerror(err));
succp = false;
goto return_succp;
}
free(start_msg_str);
succp = true;
return_succp:
return succp;
}
/**
* @node Combine all name parts from left to right.
@ -2153,12 +2396,6 @@ static bool logfile_init(
{
bool succp = false;
fnames_conf_t* fn = &logmanager->lm_fnames_conf;
/** string parts of which the file is composed of */
strpart_t strparts[3];
bool namecreatefail = false;
bool nameconflicts = false;
bool writable;
logfile->lf_state = INIT;
#if defined(SS_DEBUG)
logfile->lf_chk_top = CHK_NUM_LOGFILE;
@ -2172,21 +2409,12 @@ static bool logfile_init(
logfile->lf_name_seqno = 1;
logfile->lf_lmgr = logmanager;
logfile->lf_flushflag = false;
logfile->lf_rotateflag= false;
logfile->lf_spinlock = 0;
logfile->lf_store_shmem = store_shmem;
logfile->lf_write_syslog = write_syslog;
logfile->lf_buf_size = MAX_LOGSTRLEN;
logfile->lf_enabled = logmanager->lm_enabled_logfiles & logfile_id;
/**
* strparts is an array but next pointers are used to walk through
* the list of string parts.
*/
strparts[0].sp_next = &strparts[1];
strparts[1].sp_next = &strparts[2];
strparts[2].sp_next = NULL;
strparts[1].sp_string = logfile->lf_name_prefix;
strparts[2].sp_string = logfile->lf_name_suffix;
/**
* If file is stored in shared memory in /dev/shm, a link
* pointing to shm file is created and located to the file
@ -2204,7 +2432,7 @@ static bool logfile_init(
if (c == NULL)
{
succp = false;
goto file_create_fail;
goto return_with_succp;
}
sprintf(c, "%s%d", shm_pathname_prefix, pid);
logfile->lf_filepath = c;
@ -2213,7 +2441,7 @@ static bool logfile_init(
errno != EEXIST)
{
succp = false;
goto file_create_fail;
goto return_with_succp;
}
logfile->lf_linkpath = strdup(fn->fn_logpath);
logfile->lf_linkpath = add_slash(logfile->lf_linkpath);
@ -2223,114 +2451,11 @@ static bool logfile_init(
logfile->lf_filepath = strdup(fn->fn_logpath);
}
logfile->lf_filepath = add_slash(logfile->lf_filepath);
do {
namecreatefail = false;
nameconflicts = false;
strparts[0].sp_string = logfile->lf_filepath;
/**
* Create name for log file. Seqno is added between prefix &
* suffix (index == 2)
*/
logfile->lf_full_file_name =
form_full_file_name(strparts, logfile->lf_name_seqno, 2);
if (store_shmem)
{
strparts[0].sp_string = logfile->lf_linkpath;
/**
* Create name for link file
*/
logfile->lf_full_link_name =
form_full_file_name(strparts,
logfile->lf_name_seqno,
2);
}
/**
* At least one of the files couldn't be created. Increase
* sequence number and retry until succeeds.
*/
if (logfile->lf_full_file_name == NULL ||
(store_shmem && logfile->lf_full_link_name == NULL))
{
namecreatefail = true;
goto file_create_fail;
}
/**
* If file exists but is different type, create fails and
* new, increased sequence number is added to file name.
*/
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 (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))
{
unlink(logfile->lf_full_file_name);
nameconflicts = true;
}
}
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)
{
logfile->lf_name_seqno += 1;
if (logfile->lf_full_file_name != NULL)
{
free(logfile->lf_full_file_name);
logfile->lf_full_file_name = NULL;
}
if (logfile->lf_full_link_name != NULL)
{
free(logfile->lf_full_link_name);
logfile->lf_full_link_name = NULL;
}
}
} while (namecreatefail || nameconflicts);
if (!(succp = logfile_create(logfile)))
{
goto return_with_succp;
}
/**
* Create a block buffer list for log file. Clients' writes go to buffers
* from where separate log flusher thread writes them to disk.
@ -2365,11 +2490,11 @@ file_create_fail:
CHK_LOGFILE(logfile);
return_with_succp:
if (!succp) {
if (!succp)
{
logfile_done(logfile);
}
ss_dassert(logfile->lf_state == RUN ||
logfile->lf_state == DONE);
ss_dassert(logfile->lf_state == RUN || logfile->lf_state == DONE);
return succp;
}
@ -2428,16 +2553,14 @@ static void logfile_free_memory(
}
/**
* @node Initialize filewriter struct to a given address
* @node Initialize filewriter data and open the log file for each log file type.
*
* Parameters:
* @param fw - <usage>
* <description>
* @param logmanager Log manager struct
* @param fw File writer struct
* @param clientmes Messaging from file writer to log manager
* @param logmes Messaging from loggers to file writer thread
*
* @return
*
*
* @details (write detailed description here)
* @return true if succeed, false if failed
*
*/
static bool filewriter_init(
@ -2447,11 +2570,9 @@ static bool filewriter_init(
skygw_message_t* logmes)
{
bool succp = false;
int err;
logfile_t* lf;
logfile_id_t id;
int i;
char* start_msg_str;
CHK_LOGMANAGER(logmanager);
@ -2469,59 +2590,25 @@ static bool filewriter_init(
if (fw->fwr_logmes == NULL || fw->fwr_clientmes == NULL) {
goto return_succp;
}
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i <<= 1) {
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i <<= 1)
{
id = (logfile_id_t)i;
lf = logmanager_get_logfile(logmanager, id);
if (lf->lf_store_shmem)
{
/** Create symlink pointing to log file */
fw->fwr_file[id] = skygw_file_init(lf->lf_full_file_name,
lf->lf_full_link_name);
}
else
{
/** Create normal disk-resident log file */
fw->fwr_file[id] = skygw_file_init(lf->lf_full_file_name,
NULL);
}
if (fw->fwr_file[id] == NULL)
if (!(succp = logfile_open_file(fw, lf)))
{
fprintf(stderr,
"Error : opening %s failed, %s. Exiting "
"Error : opening log file %s failed. Exiting "
"MaxScale\n",
lf->lf_full_file_name,
strerror(errno));
goto return_succp;
}
if (lf->lf_enabled) {
start_msg_str = strdup("---\tLogging is enabled.\n");
} else {
start_msg_str = strdup("---\tLogging is disabled.\n");
}
err = skygw_file_write(fw->fwr_file[id],
(void *)start_msg_str,
strlen(start_msg_str),
true);
if (err != 0)
{
fprintf(stderr,
"Error : writing to file %s failed due to %d, %s. "
"Exiting MaxScale.\n",
lf->lf_full_file_name,
err,
strerror(err));
succp = false;
lf->lf_full_file_name);
goto return_succp;
}
free(start_msg_str);
}
}
} /*< for */
fw->fwr_state = RUN;
CHK_FILEWRITER(fw);
succp = true;
return_succp:
if (!succp) {
filewriter_done(fw);
@ -2542,9 +2629,10 @@ static void filewriter_done(
case INIT:
fw->fwr_logmes = NULL;
fw->fwr_clientmes = NULL;
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i++) {
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i++)
{
id = (logfile_id_t)i;
skygw_file_done(fw->fwr_file[id]);
skygw_file_close(fw->fwr_file[id], true);
}
fw->fwr_state = DONE;
case DONE:
@ -2612,6 +2700,7 @@ static void* thr_filewriter_fun(
blockbuf_state_t flush_blockbuf; /**< flush single block buffer. */
bool flush_logfile; /**< flush logfile */
bool flushall_logfiles;/**< flush all logfiles */
bool rotate_logfile; /*< close current and open new file */
size_t vn1;
size_t vn2;
@ -2643,13 +2732,45 @@ static void* thr_filewriter_fun(
lf = &lm->lm_logfile[(logfile_id_t)i];
/**
* read and reset logfile's flushflag
* read and reset logfile's flush- and rotateflag
*/
acquire_lock(&lf->lf_spinlock);
flush_logfile = lf->lf_flushflag;
lf->lf_flushflag = false;
flush_logfile = lf->lf_flushflag;
rotate_logfile = lf->lf_rotateflag;
lf->lf_flushflag = false;
lf->lf_rotateflag = false;
release_lock(&lf->lf_spinlock);
/**
* Log rotation :
* Close current, and open a new file for the log.
*/
if (rotate_logfile)
{
bool succp;
lf->lf_name_seqno += 1; /*< new sequence number */
if (!(succp = logfile_create(lf)))
{
lf->lf_name_seqno -= 1; /*< restore */
}
else if ((succp = logfile_open_file(fwr, lf)))
{
skygw_file_close(file, false); /*< close old file */
}
if (!succp)
{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : Log rotation failed. "
"Creating replacement file %s "
"failed. Continuing "
"logging to existing file.",
lf->lf_full_file_name)));
}
continue;
}
/**
* get logfile's block buffer list
*/

View File

@ -1696,7 +1696,8 @@ return_succp:
}
static bool file_write_footer(
skygw_file_t* file)
skygw_file_t* file,
bool shutdown)
{
bool succp = false;
size_t wbytes1;
@ -1710,10 +1711,20 @@ static bool file_write_footer(
const char* header_buf4;
CHK_FILE(file);
header_buf1 = "MaxScale is shut down.\t";
if (shutdown)
{
header_buf1 = "MaxScale is shut down.\t";
}
else
{
header_buf1 = "Closed file due log rotation.\t";
}
tslen = get_timestamp_len();
header_buf3 = (char *)malloc(tslen);
if (header_buf3 == NULL) {
if (header_buf3 == NULL)
{
goto return_succp;
}
tslen = snprint_timestamp(header_buf3, tslen);
@ -1729,7 +1740,8 @@ static bool file_write_footer(
wbytes1=fwrite((void*)header_buf1, len1, 1, file->sf_file);
wbytes4=fwrite((void*)header_buf4, len4, 1, file->sf_file);
if (wbytes1 != 1 || wbytes3 != 1 || wbytes4 != 1) {
if (wbytes1 != 1 || wbytes3 != 1 || wbytes4 != 1)
{
fprintf(stderr,
"* Writing header %s %s to %s failed.\n",
header_buf1,
@ -1743,7 +1755,8 @@ static bool file_write_footer(
succp = true;
return_succp:
if (header_buf3 != NULL) {
if (header_buf3 != NULL)
{
free(header_buf3);
}
return succp;
@ -1886,43 +1899,44 @@ return_file:
return file;
}
void skygw_file_done(
skygw_file_t* file)
void skygw_file_close(
skygw_file_t* file,
bool shutdown)
{
int fd;
int err;
if (file != NULL) {
CHK_FILE(file);
if (!file_write_footer(file)) {
fprintf(stderr,
"* Writing header of log file %s failed.\n",
file->sf_fname);
perror("SkyGW file open\n");
}
fd = fileno(file->sf_file);
fsync(fd);
err = fclose(file->sf_file);
if (err != 0) {
fprintf(stderr,
"* Closing file %s failed : %s.\n",
file->sf_fname,
strerror(errno));
}
else
int fd;
int err;
if (file != NULL)
{
CHK_FILE(file);
if (!file_write_footer(file, shutdown))
{
fprintf(stderr,
"* Writing footer to log file %s failed.\n",
file->sf_fname);
perror("Write fike footer\n");
}
fd = fileno(file->sf_file);
fsync(fd);
if ((err = fclose(file->sf_file)) != 0)
{
fprintf(stderr,
"* Closing file %s failed due to %d, %s.\n",
file->sf_fname,
errno,
strerror(errno));
}
else
{
ss_dfprintf(stderr, "Closed %s\n", file->sf_fname);
free(file->sf_fname);
free(file);
}
}
}
}
/**
* Find the given needle - user-provided literal - and replace it with
* replacement string. Separate user-provided literals from matching table names

View File

@ -145,7 +145,7 @@ EXTERN_C_BLOCK_END
/** Skygw file routines */
skygw_file_t* skygw_file_init(char* fname, char* symlinkname);
void skygw_file_done(skygw_file_t* file);
void skygw_file_close(skygw_file_t* file, bool shutdown);
int skygw_file_write(
skygw_file_t* file,
void* data,