X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=ucw%2Flog-stream.c;h=5af9f3e6581ad264797e64c566ba0573db40f5d8;hb=634be141f3f014e31d5931a968c0c0f7e07205fb;hp=748164c86d804e7ed785a3cbc834d0e89cc30526;hpb=464a5c3067d1fbed8e2f9899e8e3459e7948e07e;p=libucw.git diff --git a/ucw/log-stream.c b/ucw/log-stream.c index 748164c8..5af9f3e6 100644 --- a/ucw/log-stream.c +++ b/ucw/log-stream.c @@ -9,161 +9,195 @@ */ #include "ucw/lib.h" -#include "ucw/clists.h" -#include "ucw/simple-lists.h" #include "ucw/log.h" +#include "ucw/log-internal.h" +#include "ucw/simple-lists.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +/* Initial number of streams to allocate (must be >=2) */ +#define LS_INIT_STREAMS 8 /* Flag indicating initialization of the module */ -static int ls_initialized = 0; +static int log_initialized = 0; -/* The head of the list of freed log_streams indexes in ls_streams.ptr (-1 if none free). - * Freed positions in ls_streams.ptr are connected into a linked list in the following way: - * ls_streams.ptr[ls_streams_free].idata is the index of next freed position (or -1) */ -static int ls_streams_free = -1; +/* 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].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 - * the first ls_new() (for backward compatibility and ease of use). */ -static void ls_init_module(void) + * the first log_new_stream() (for backward compatibility and ease of use). */ +static void +log_init_module(void) { - if (ls_initialized) return; + if (log_initialized) + return; - /* create the grow array */ + /* Create the growing array */ lsbuf_init(&log_streams); lsbuf_set_size(&log_streams, LS_INIT_STREAMS); bzero(log_streams.ptr, sizeof(struct log_stream*) * (log_streams.len)); - ls_streams_free = -1; + log_streams_free = ~0U; - ls_initialized = 1; + log_initialized = 1; /* init the default stream (0) as forwarder to fd2 */ - struct log_stream *ls = ls_new(); + struct log_stream *ls = log_new_stream(sizeof(*ls)); ASSERT(ls == log_streams.ptr[0]); ASSERT(ls->regnum == 0); ls->name = "default"; - ls_add_substream(ls, (struct log_stream *) &ls_default_log); - - /* log this */ - ls_msg(L_DEBUG, "logstream module initialized."); + log_add_substream(ls, &log_stream_default); } -/* close all open streams, un-initialize the module, free all memory, - * use only ls_default_log */ -void ls_close_all(void) +void +log_close_all(void) { - int i; + if (!log_initialized) + return; - if (!ls_initialized) return; + // Remove substreams of all streams + for (int i=0; i < log_streams_after; i++) + if (log_streams.ptr[i]->regnum >= 0) + log_rm_substream(log_streams.ptr[i], NULL); - for (i=0; iregnum>=0) - ls_close(log_streams.ptr[i]); - xfree(log_streams.ptr[i]); - } + // Close all streams that remain and free all cached structures + for (int i=0; i < log_streams_after; i++) + { + struct log_stream *ls = log_streams.ptr[i]; + if (ls->regnum >= 0) + log_close_stream(ls); + ASSERT(ls->regnum < 0 || !ls->use_count); + xfree(ls); + } - /* set to the default state */ + /* Back to the default state */ lsbuf_done(&log_streams); - log_streams_after=0; - ls_streams_free=-1; - ls_initialized = 0; + log_streams_after = 0; + log_streams_free = ~0U; + log_initialized = 0; } -/* add a new substream, malloc()-ate a new simp_node */ -void ls_add_substream(struct log_stream *where, struct log_stream *what) +void +log_add_substream(struct log_stream *where, struct log_stream *what) { ASSERT(where); ASSERT(what); simp_node *n = xmalloc(sizeof(simp_node)); - n->p = what; - clist_add_tail(&(where->substreams), (cnode*)n); + n->p = log_ref_stream(what); + clist_add_tail(&where->substreams, &n->n); } -/* remove all occurences of a substream, free() the simp_node */ -/* return number of deleted entries */ -int ls_rm_substream(struct log_stream *where, struct log_stream *what) +int +log_rm_substream(struct log_stream *where, struct log_stream *what) { void *tmp; - int cnt=0; + int cnt = 0; ASSERT(where); - ASSERT(what); CLIST_FOR_EACH_DELSAFE(simp_node *, i, where->substreams, tmp) - if (i->p == what) - { - clist_remove((cnode*)i); - xfree(i); - cnt++; - } + if (i->p == what || !what) + { + clist_remove(&i->n); + log_close_stream(i->p); + xfree(i); + cnt++; + } return cnt; } -/* Return a pointer to a new stream with no handler and an empty substream list. */ -struct log_stream *ls_new(void) +struct log_stream * +log_new_stream(size_t size) { struct log_stream *l; int index; - /* initialize the array if not initialized already */ - if (unlikely(ls_initialized==0)) - ls_init_module(); - - /* there is no closed stream -- allocate a new one */ - if (ls_streams_free==-1) - { - /* check the size of the pointer array */ - lsbuf_grow(&log_streams, log_streams_after+1); - ls_streams_free = log_streams_after++; - log_streams.ptr[ls_streams_free] = xmalloc(sizeof(struct log_stream)); - log_streams.ptr[ls_streams_free]->idata = -1; - log_streams.ptr[ls_streams_free]->regnum = -1; - } - - ASSERT(ls_streams_free>=0); - - /* initialize the stream */ - index = ls_streams_free; - l = log_streams.ptr[index]; - ls_streams_free = l->idata; - memset(l, 0, sizeof(struct log_stream)); - l->levels = LS_ALL_LEVELS; + /* Initialize the data structures if needed */ + log_init_module(); + + /* Get a free stream, possibly recycling a closed one */ + if (log_streams_free == ~0U) + { + lsbuf_grow(&log_streams, log_streams_after+1); + index = log_streams_after++; + l = log_streams.ptr[index] = xmalloc(size); + } + else + { + index = log_streams_free; + l = xrealloc(log_streams.ptr[index], size); + log_streams.ptr[index] = l; + log_streams_free = l->levels; + } + + /* Initialize the stream */ + bzero(l, sizeof(*l)); + l->levels = ~0U; + l->types = ~0U; l->regnum = LS_SET_STRNUM(index); - l->substreams.head.next = &(l->substreams.head); - l->substreams.head.prev = &(l->substreams.head); - return l; + clist_init(&l->substreams); + return log_ref_stream(l); } -/* Close and remember given log_stream */ -/* does not affect substreams, but frees the .substreams list */ -void ls_close(struct log_stream *ls) +int +log_close_stream(struct log_stream *ls) { - void *tmp; ASSERT(ls); + ASSERT(ls->use_count); + if (--ls->use_count) + return 0; - /* xfree() all the simp_nodes from substreams */ - CLIST_FOR_EACH_DELSAFE(simp_node *, i, ls->substreams, tmp) - { - clist_remove((cnode*)i); - xfree(i); - } + /* Unlink all subtreams */ + log_rm_substream(ls, NULL); - /* close and remember the stream */ - if (ls->close!=NULL) + /* Close the stream and add it to the free-list */ + if (ls->close) ls->close(ls); - ls->idata = ls_streams_free; - ls_streams_free = LS_GET_STRNUM(ls->regnum); + ls->levels = log_streams_free; + log_streams_free = LS_GET_STRNUM(ls->regnum); ls->regnum = -1; + return 1; +} + +void +log_set_format(struct log_stream *ls, uns mask, uns data) +{ + ls->msgfmt = (ls->msgfmt & mask) | data; + CLIST_FOR_EACH(simp_node *, i, ls->substreams) + log_set_format(i->p, mask, data); +} + +/*** Registry of type names ***/ + +int log_register_type(const char *name) +{ + if (!log_type_names) + { + log_type_names = xmalloc_zero(LS_NUM_TYPES * sizeof(char *)); + log_type_names[0] = "default"; + } + uns id; + for (id=0; id < LS_NUM_TYPES && log_type_names[id]; id++) + if (!strcmp(log_type_names[id], name)) + return LS_SET_TYPE(id); + ASSERT(id < LS_NUM_TYPES); + log_type_names[id] = xstrdup(name); + return LS_SET_TYPE(id); +} + +/** Find a message type by name and return its ID encoded by `LS_SET_TYPE`. Returns -1 if no such type found. **/ +int log_find_type(const char *name) +{ + if (!strcmp(name, "default")) + return 0; + if (!log_type_names) + return -1; + + for (uns id=0; id < LS_NUM_TYPES && log_type_names[id]; id++) + if (!strcmp(log_type_names[id], name)) + return LS_SET_TYPE(id); + return -1; }