From 96d356a371d711395e0a39b62f8ac785739366dd Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 14 Feb 2009 00:59:36 +0100 Subject: [PATCH] Logging: Introduce inheritance of log_stream's. 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 | 85 ++++++++++++++++++++++++------------------------ ucw/log-stream.c | 27 +++++++-------- ucw/log-syslog.c | 17 +++++++--- ucw/log.c | 5 ++- ucw/log.h | 10 +++--- 5 files changed, 76 insertions(+), 68 deletions(-) diff --git a/ucw/log-file.c b/ucw/log-file.c index 52a01087..65e9eb85 100644 --- a/ucw/log-file.c +++ b/ucw/log-file.c @@ -20,15 +20,12 @@ #include #include -/* - * 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; } diff --git a/ucw/log-stream.c b/ucw/log-stream.c index 3a8c1e10..a7b10c82 100644 --- a/ucw/log-stream.c +++ b/ucw/log-stream.c @@ -20,10 +20,10 @@ /* 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; diff --git a/ucw/log-syslog.c b/ucw/log-syslog.c index dc1df456..50bb6efc 100644 --- a/ucw/log-syslog.c +++ b/ucw/log-syslog.c @@ -13,6 +13,11 @@ #include +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; } diff --git a/ucw/log.c b/ucw/log.c index 19609809..76821d98 100644 --- 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, diff --git a/ucw/log.h b/ucw/log.h index 09be0b17..d87c3896 100644 --- 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 */ -- 2.39.2