cl_log: Restore old logfile open/seek/write/close behaviour.

This patch actually does not completely revert commit 2435:ada347da564d,
but adds a layer to support both, open/write/close and and 
open-once, write, close/open-for signal handlers

It also changes a marco into a static function. And also uses 
system IO (open/close/write) instead of libc IO (fopen/fclose/fwrite).
Libc IO has a buffer, which is not suitable for log files (in case of 
a stonith, all the buffer and which might large, will be missing in
log files.

Signed-off-by: Bernd Schubert <bschub...@ddn.com>

diff --git a/lib/clplumbing/cl_log.c b/lib/clplumbing/cl_log.c
--- a/lib/clplumbing/cl_log.c
+++ b/lib/clplumbing/cl_log.c
@@ -74,6 +74,7 @@ static IPC_Message* ChildLogIPCMessage(i
 static void    FreeChildLogIPCMessage(IPC_Message* msg);
 static gboolean send_dropped_message(gboolean use_pri_str, IPC_Channel *chan);
 static int cl_set_logging_wqueue_maxlen(int qlen);
+static char * syslog_timestamp(TIME_T t);
 
 static int             use_logging_daemon =  FALSE;
 static int             conn_logd_time = 0;
@@ -92,6 +93,10 @@ int                  debug_level = 0;
 static GDestroyNotify  destroy_logging_channel_callback;
 static void            (*create_logging_channel_callback)(IPC_Channel* chan);
 static gboolean                logging_chan_in_main_loop = FALSE;
+static gboolean                have_signal_handler = FALSE;
+
+static int debug_fd = -1;
+static int log_fd   = -1;
 
 /***********************
  *debug use only, do not use this function in your program
@@ -477,54 +482,79 @@ prio2str(int priority)
                "(undef)" : log_prio[logpri];
 }
 
-/* print log line to a FILE *f */
-#define print_logline(fp,entity,entity_pid,ts,pristr,buf) { \
-                       fprintf(fp, "%s[%d]: %s 
",entity,entity_pid,ha_timestamp(ts)); \
-                       if (pristr) \
-                               fprintf(fp,"%s: %s\n",pristr,buf); \
-                       else \
-                               fprintf(fp,"%s\n",buf); \
-               }
+/* print log line to a string */
+static char *
+logline(char *dest, int max_length, const char * entity, 
+       int entity_pid, TIME_T ts, const char * pristr, const char * msg) 
+{
+       static struct utsname   un;
+       
+       uname(&un);
+       
+       if (!syslogformatfile) {
+               snprintf(dest, max_length, "%s[%d]: %s %s: %s"
+               ,        entity, entity_pid
+               ,        ha_timestamp(ts)
+               ,        (pristr ? pristr : "")
+               ,        msg);
+       } else {
+               /*
+                * Jul 14 21:45:18 beam logd: [1056]: info: setting log file to 
/dev/null
+                */
+               snprintf(dest, max_length, "%s %s %s: [%d]: %s%s%s\n"
+               ,       syslog_timestamp(ts)
+               ,       un.nodename, entity, entity_pid
+               ,       (pristr ? pristr : "")
+               ,       (pristr ? ": " : "")
+               ,       msg);
+       }
+       
+       return dest;
+}
 
-static char * syslog_timestamp(TIME_T t);
+/* print log line to the given file handle */
+static void 
+print_logline(FILE* fh, const char * entity,
+             int entity_pid, TIME_T ts, const char * pristr, const char * buf)
+{
+       char log_str[MAXLINE];
+       
+       logline(log_str, MAXLINE, entity, entity_pid, ts, pristr, buf);
+       fprintf(fh, "%s\n", log_str);
+}
 
 static void
-append_log(FILE * fp, const char * entity, int entity_pid
-,      TIME_T timestamp, const char * pristr, const char * msg)
+append_log(int fd, const char * entity, int entity_pid,
+          TIME_T ts, const char * pristr, const char * msg)
 {
-       static int              got_uname = FALSE;
-       static struct utsname   un;
-
-       if (!syslogformatfile) {
-               print_logline(fp, entity, entity_pid, timestamp, pristr, msg);
-               return;
+       char log_str[MAXLINE];
+       int rc;
+       
+       logline(log_str, MAXLINE, entity, entity_pid, ts, pristr, msg);
+       
+       /* write() is better here, as fprintf() and fwrite() may use 
+        * a rather large libc buffer which we would need to flush */
+       rc = write(fd, log_str, strlen(log_str));
+       if (rc == -1) {
+               /* writing to the log file failed, try stderr */
+               syslog(LOG_ERR, "Failed to write to log file: %s\n",
+                       strerror(errno));
        }
-       if (!got_uname) {
-               uname(&un);
-       }
-       /*
-        * Jul 14 21:45:18 beam logd: [1056]: info: setting log file to 
/dev/null
-        */
-       fprintf(fp, "%s %s %s: [%d]: %s%s%s\n"
-       ,       syslog_timestamp(timestamp)
-       ,       un.nodename, entity, entity_pid
-       ,       (pristr ? pristr : "")
-       ,       (pristr ? ": " : "")
-       ,       msg);
 }
 
 /*
  * Just open the given file name
  */
-static FILE * 
+static int 
 open_log_file(const char * fname)
 {
-       FILE * fp = fopen(fname ,"a");
-       if (!fp) {
+       int mode = S_IRUSR | S_IWUSR | S_IRGRP;
+       int fd = open(fname, O_WRONLY | O_APPEND | O_CREAT, mode);
+       if (!fd) {
                syslog(LOG_ERR, "Failed to open log file %s: %s\n" , 
                       fname, strerror(errno)); 
        }
-       return fp;
+       return fd;
 }
 
 /*
@@ -562,26 +592,20 @@ cl_direct_log(int priority, const char* 
        }
 
        if (debugfile_name != NULL) {
-               static FILE * debug_fp = NULL;
-               if (!debug_fp) {
-                       /* As performance optimization we keep the file-handle
-                        * open all the time */
-                       debug_fp = open_log_file(debugfile_name);
+               if (debug_fd != -1) {
+                       debug_fd = open_log_file(debugfile_name);
                }
-               if (debug_fp)
-                       append_log(debug_fp ,entity, entity_pid, ts, pristr, 
+               if (debug_fd != -1)
+                       append_log(debug_fd ,entity, entity_pid, ts, pristr, 
                                   buf);
        }
 
        if (priority != LOG_DEBUG && logfile_name != NULL) {
-               static FILE * log_fp = NULL;
-               if (!log_fp) {
-                       /* As performance optimization we keep the file-handle
-                        * open all the time */
-                       log_fp = open_log_file(logfile_name);
+               if (log_fd != -1) {
+                       log_fd = open_log_file(logfile_name);
                }
-               if (log_fp)
-                       append_log(log_fp ,entity, entity_pid, ts, pristr, 
+               if (log_fd != -1)
+                       append_log(log_fd ,entity, entity_pid, ts, pristr, 
                                   buf);
        }
 
@@ -589,6 +613,17 @@ cl_direct_log(int priority, const char* 
                return_to_dropped_privs();
        }
        
+       /* As performance optimization we try to keep the file descriptor
+        * open all the time, but as logrotation needs to work, the calling 
+        * program needs a signal handler. Therefore we close fd's, if the 
+        * caller did not tell us it has the signal handler */
+       if (have_signal_handler == FALSE) {
+               close(debug_fd);
+               close(log_fd);
+               debug_fd = -1;
+               log_fd = -1;
+       }
+       
        return;
 }
 

_______________________________________________
Pacemaker mailing list: Pacemaker@oss.clusterlabs.org
http://oss.clusterlabs.org/mailman/listinfo/pacemaker

Project Home: http://www.clusterlabs.org
Getting started: http://www.clusterlabs.org/doc/Cluster_from_Scratch.pdf
Bugs: http://developerbugs.linux-foundation.org/enter_bug.cgi?product=Pacemaker

Reply via email to