]> mj.ucw.cz Git - libucw.git/commitdiff
Logging: Introduce inheritance of log_stream's.
authorMartin Mares <mj@ucw.cz>
Fri, 13 Feb 2009 23:59:36 +0000 (00:59 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 13 Feb 2009 23:59:36 +0000 (00:59 +0100)
The outbreak of various private fields (idata, pdata, udata) in struct log_stream
has gotten somewhat ugly, so I have replaced them by real private data allocated
after the standard portion of the log_stream structure.

log_new_stream() has gained a parameter telling it the size of the structure
to allocate. I have kept the recycler for the time being -- while saving allocations
is not worth the effort, it still nicely keeps the list of free stream ID's.

As idata are gone, the list of free items is now chained by log_stream->levels.

The default log stream no longer stores the fd explicitly, both log-file and
log-syslog keep private data in their own data structure extending log_stream.

ucw/log-file.c
ucw/log-stream.c
ucw/log-syslog.c
ucw/log.c
ucw/log.h

index 52a010876d76540d6aec4dbb0d5ae39a4a7809dd..65e9eb85df41541ccba86c0d0bf3c5d58d80f8bd 100644 (file)
 #include <unistd.h>
 #include <time.h>
 
-/*
- *  Use of the private fields of struct log_stream:
- *
- *     idata   file descriptor
- *     udata   various flags (FF_xxx)
- *     pdata   original name with strftime escapes
- *     name    current name of the log file
- *             (a dynamically allocated buffer)
- */
+struct file_stream {
+  struct log_stream ls;                // ls.name is the current name of the log file
+  int fd;
+  uns flags;                   // FF_xxx
+  char *orig_name;             // Original name with strftime escapes
+};
 
 enum log_file_flag {
   FF_FORMAT_NAME = 1,          // Name contains strftime escapes
@@ -40,41 +37,41 @@ enum log_file_flag {
 static int log_switch_nest;
 
 static void
-do_log_reopen(struct log_stream *ls, const char *name)
+do_log_reopen(struct file_stream *fs, const char *name)
 {
   int fd = ucw_open(name, O_WRONLY | O_CREAT | O_APPEND, 0666);
   if (fd < 0)
     die("Unable to open log file %s: %m", name);
-  if (ls->idata < 0)
-    ls->idata = fd;
+  if (fs->fd < 0)
+    fs->fd = fd;
   else
     {
-      dup2(fd, ls->idata);
+      dup2(fd, fs->fd);
       close(fd);
     }
-  if (ls->name)
+  if (fs->ls.name)
     {
-      xfree(ls->name);
-      ls->name = NULL;         // We have to keep this consistent, die() below can invoke logging
+      xfree(fs->ls.name);
+      fs->ls.name = NULL;      // We have to keep this consistent, die() below can invoke logging
     }
-  ls->name = xstrdup(name);
+  fs->ls.name = xstrdup(name);
 }
 
 static int
-do_log_switch(struct log_stream *ls, struct tm *tm)
+do_log_switch(struct file_stream *fs, struct tm *tm)
 {
-  if (!(ls->udata & FF_FORMAT_NAME))
+  if (!(fs->flags & FF_FORMAT_NAME))
     {
-      if (ls->idata >= 0)
+      if (fs->fd >= 0)
        return 1;
       else
        {
-         do_log_reopen(ls, ls->pdata);
+         do_log_reopen(fs, fs->orig_name);
          return 1;
        }
     }
 
-  int buflen = strlen(ls->pdata) + MAX_EXPAND;
+  int buflen = strlen(fs->orig_name) + MAX_EXPAND;
   char name[buflen];
   int switched = 0;
 
@@ -82,12 +79,12 @@ do_log_switch(struct log_stream *ls, struct tm *tm)
   if (!log_switch_nest)                // Avoid infinite loops if we die when switching logs
     {
       log_switch_nest++;
-      int l = strftime(name, buflen, ls->pdata, tm);
+      int l = strftime(name, buflen, fs->orig_name, tm);
       if (l < 0 || l >= buflen)
        die("Error formatting log file name: %m");
-      if (!ls->name || strcmp(name, ls->name))
+      if (!fs->ls.name || strcmp(name, fs->ls.name))
        {
-         do_log_reopen(ls, name);
+         do_log_reopen(fs, name);
          switched = 1;
        }
       log_switch_nest--;
@@ -107,27 +104,29 @@ log_file(const char *name)
   struct log_stream *def = log_stream_by_flags(0);
   log_rm_substream(def, NULL);
   log_add_substream(def, ls);
-  dup2(ls->idata, 2);                  // Let fd2 be an alias for the log file
+  dup2(((struct file_stream *)ls)->fd, 2);                     // Let fd2 be an alias for the log file
 }
 
 /* destructor for standard files */
 static void
 file_close(struct log_stream *ls)
 {
-  if ((ls->udata & FF_CLOSE_FD) && ls->idata >= 0)
-    close(ls->idata);
-  xfree(ls->name);
-  xfree(ls->pdata);
+  struct file_stream *fs = (struct file_stream *) ls;
+  if ((fs->flags & FF_CLOSE_FD) && fs->fd >= 0)
+    close(fs->fd);
+  xfree(fs->ls.name);
+  xfree(fs->orig_name);
 }
 
 /* handler for standard files */
 static int
 file_handler(struct log_stream *ls, struct log_msg *m)
 {
-  if ((ls->udata & FF_FORMAT_NAME) && m->tm)
-    do_log_switch(ls, m->tm);
+  struct file_stream *fs = (struct file_stream *) ls;
+  if ((fs->flags & FF_FORMAT_NAME) && m->tm)
+    do_log_switch(fs, m->tm);
 
-  int r = write(ls->idata, m->m, m->m_len);
+  int r = write(fs->fd, m->m, m->m_len);
   /* FIXME: check for errors here? */
   return 0;
 }
@@ -137,8 +136,9 @@ file_handler(struct log_stream *ls, struct log_msg *m)
 struct log_stream *
 log_new_fd(int fd)
 {
-  struct log_stream *ls = log_new_stream();
-  ls->idata = fd;
+  struct log_stream *ls = log_new_stream(sizeof(struct file_stream));
+  struct file_stream *fs = (struct file_stream *) ls;
+  fs->fd = fd;
   ls->msgfmt = LSFMT_DEFAULT;
   ls->handler = file_handler;
   ls->close = file_close;
@@ -152,12 +152,13 @@ log_new_fd(int fd)
 struct log_stream *
 log_new_file(const char *path)
 {
-  struct log_stream *ls = log_new_stream();
-  ls->idata = -1;
-  ls->pdata = xstrdup(path);
+  struct log_stream *ls = log_new_stream(sizeof(struct file_stream));
+  struct file_stream *fs = (struct file_stream *) ls;
+  fs->fd = -1;
+  fs->orig_name = xstrdup(path);
   if (strchr(path, '%'))
-    ls->udata = FF_FORMAT_NAME;
-  ls->udata |= FF_CLOSE_FD;
+    fs->flags = FF_FORMAT_NAME;
+  fs->flags |= FF_CLOSE_FD;
   ls->msgfmt = LSFMT_DEFAULT;
   ls->handler = file_handler;
   ls->close = file_close;
@@ -165,7 +166,7 @@ log_new_file(const char *path)
   time_t now = time(NULL);
   struct tm *tm = localtime(&now);
   ASSERT(tm);
-  do_log_switch(ls, tm);               // die()'s on errors
+  do_log_switch(fs, tm);               // die()'s on errors
   return ls;
 }
 
@@ -179,7 +180,7 @@ log_switch(void)
   int switched = 0;
   for (int i=0; i < log_streams_after; i++)
     if (log_streams.ptr[i]->handler == file_handler)
-      switched |= do_log_switch(log_streams.ptr[i], tm);
+      switched |= do_log_switch((struct file_stream *) log_streams.ptr[i], tm);
   return switched;
 }
 
index 3a8c1e1094361964eec3a64d08097882610003f0..a7b10c821878bbe4bc1af465bcd5543ff24393c6 100644 (file)
 /* Flag indicating initialization of the module */
 static int log_initialized = 0;
 
-/* The head of the list of freed log_streams indexes in log_streams.ptr (-1 if none free).
+/* The head of the list of freed log_streams indexes in log_streams.ptr (~0U if none free).
  * Freed positions in log_streams.ptr are connected into a linked list in the following way:
- * log_streams.ptr[log_streams_free].idata is the index of next freed position (or -1) */
-static int log_streams_free = -1;
+ * log_streams.ptr[log_streams_free].levels is the index of next freed position (or ~0U) */
+static uns log_streams_free = ~0U;
 
 /* Initialize the logstream module.
  * It is not neccessary to call this explicitely as it is called by
@@ -39,12 +39,12 @@ log_init_module(void)
   lsbuf_set_size(&log_streams, LS_INIT_STREAMS);
 
   bzero(log_streams.ptr, sizeof(struct log_stream*) * (log_streams.len));
-  log_streams_free = -1;
+  log_streams_free = ~0U;
 
   log_initialized = 1;
 
   /* init the default stream (0) as forwarder to fd2 */
-  struct log_stream *ls = log_new_stream();
+  struct log_stream *ls = log_new_stream(sizeof(*ls));
   ASSERT(ls == log_streams.ptr[0]);
   ASSERT(ls->regnum == 0);
   ls->name = "default";
@@ -69,7 +69,7 @@ log_close_all(void)
   /* Back to the default state */
   lsbuf_done(&log_streams);
   log_streams_after = 0;
-  log_streams_free = -1;
+  log_streams_free = ~0U;
   log_initialized = 0;
 }
 
@@ -86,7 +86,7 @@ log_add_substream(struct log_stream *where, struct log_stream *what)
   clist_add_tail(&where->substreams, &n->n);
 }
 
-/* Remove all occurences of a substream together with the references they
+/* Remove all occurrences of a substream together with the references they
  * keep. If a substream becomes unreferenced, it is closed. If what is NULL,
  * all substreams are removed. Returns the number of deleted entries. */
 int
@@ -109,7 +109,7 @@ log_rm_substream(struct log_stream *where, struct log_stream *what)
 
 /* Return a pointer to a new stream with no handler and an empty substream list. */
 struct log_stream *
-log_new_stream(void)
+log_new_stream(size_t size)
 {
   struct log_stream *l;
   int index;
@@ -118,17 +118,18 @@ log_new_stream(void)
   log_init_module();
 
   /* Get a free stream, possibly recycling a closed one */
-  if (log_streams_free < 0)
+  if (log_streams_free == ~0U)
     {
       lsbuf_grow(&log_streams, log_streams_after+1);
       index = log_streams_after++;
-      l = log_streams.ptr[index] = xmalloc(sizeof(struct log_stream));
+      l = log_streams.ptr[index] = xmalloc(size);
     }
   else
     {
       index = log_streams_free;
-      l = log_streams.ptr[index];
-      log_streams_free = l->idata;
+      l = xrealloc(log_streams.ptr[index], size);
+      log_streams.ptr[index] = l;
+      log_streams_free = l->levels;
     }
 
   /* Initialize the stream */
@@ -156,7 +157,7 @@ log_close_stream(struct log_stream *ls)
   /* Close the stream and add it to the free-list */
   if (ls->close)
     ls->close(ls);
-  ls->idata = log_streams_free;
+  ls->levels = log_streams_free;
   log_streams_free = LS_GET_STRNUM(ls->regnum);
   ls->regnum = -1;
   return 1;
index dc1df456504687e35e5221e00d22a00a240e4927..50bb6efcc7a18be5a729418f45847c4d5a38c175 100644 (file)
 
 #include <syslog.h>
 
+struct syslog_stream {
+  struct log_stream ls;
+  int facility;
+};
+
 /* Destructor */
 static void
 syslog_close(struct log_stream *ls)
@@ -42,16 +47,17 @@ syslog_level(int level)
 static int
 syslog_handler(struct log_stream *ls, struct log_msg *m)
 {
+  struct syslog_stream *ss = (struct syslog_stream *) ls;
   int prio;
   ASSERT(ls);
   ASSERT(m);
 
   // FIXME: Logging of PID
-  prio = syslog_level(LS_GET_LEVEL(m->flags)) | (ls->idata);
+  prio = syslog_level(LS_GET_LEVEL(m->flags)) | ss->facility;
   if (ls->name)
-    syslog(prio | (ls->idata), "%s: %s", ls->name, m->m);
+    syslog(prio, "%s: %s", ls->name, m->m);
   else
-    syslog(prio | (ls->idata), "%s", m->m);
+    syslog(prio, "%s", m->m);
   return 0;
 }
 
@@ -61,12 +67,13 @@ syslog_handler(struct log_stream *ls, struct log_msg *m)
 struct log_stream *
 log_new_syslog(int facility, const char *name)
 {
-  struct log_stream *ls = log_new_stream();
+  struct log_stream *ls = log_new_stream(sizeof(struct syslog_stream));
+  struct syslog_stream *ss = (struct syslog_stream *) ls;
   if (name)
     ls->name = xstrdup(name);
-  ls->idata = facility;
   ls->msgfmt = LSFMT_NONE;
   ls->handler = syslog_handler;
   ls->close = syslog_close;
+  ss->facility = facility;
   return ls;
 }
index 19609809f9b36b632dc92bdd513d65b61a2cd961..76821d981cdb73495a1a90fd59d59eeb4dd5131a 100644 (file)
--- a/ucw/log.c
+++ b/ucw/log.c
@@ -27,16 +27,15 @@ void (*log_die_hook)(void);
 
 /*** The default log stream, which logs to stderr ***/
 
-static int default_log_handler(struct log_stream *ls, struct log_msg *m)
+static int default_log_handler(struct log_stream *ls UNUSED, struct log_msg *m)
 {
   // This is a completely bare version of the log-file module. Errors are ignored.
-  write(ls->idata, m->m, m->m_len);
+  write(2, m->m, m->m_len);
   return 0;
 }
 
 struct log_stream log_stream_default = {
   .name = "stderr",
-  .idata = 2,
   .use_count = 1000000,
   .handler = default_log_handler,
   .levels = LS_ALL_LEVELS,
index 09be0b173d90f473c21c2c0ccdda9164b3d54805..d87c389638a4ebdfc9bb3fae91089fae1f7a11c8 100644 (file)
--- a/ucw/log.h
+++ b/ucw/log.h
@@ -38,9 +38,7 @@ struct log_stream
   struct clist substreams;             // Pass the message to these streams (simple_list of pointers)
   int (*handler)(struct log_stream *ls, struct log_msg *m);    // Called to commit the message
   void (*close)(struct log_stream* ls);        // Called upon log_close_stream()
-  int idata;                           // Private data of the handler
-  void *pdata;
-  uns udata;
+  // Private data of the handler follow
 };
 
 /* the default logger */
@@ -123,8 +121,10 @@ enum ls_flagmasks {
 // The module is initialized when a first stream is created.
 // Before that only the default stream exists.
 
-/* Return pointer a new (xmalloc()-ated) stream with no handler and an empty substream list. */
-struct log_stream *log_new_stream(void);
+/* Return pointer a new (xmalloc()-ated) stream with no handler and an empty substream list.
+ * Since struct log_stream is followed by private data, @size bytes of memory are allocated
+ * for the whole structure. */
+struct log_stream *log_new_stream(size_t size);
 
 /* Close and xfree() given log_stream */
 /* Does not affect substreams */