X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Flog-stream.c;h=5af9f3e6581ad264797e64c566ba0573db40f5d8;hb=634be141f3f014e31d5931a968c0c0f7e07205fb;hp=3a8c1e1094361964eec3a64d08097882610003f0;hpb=de742f43adad78a5bdda6ace083106f7264a2e16;p=libucw.git diff --git a/ucw/log-stream.c b/ucw/log-stream.c index 3a8c1e10..5af9f3e6 100644 --- a/ucw/log-stream.c +++ b/ucw/log-stream.c @@ -10,6 +10,7 @@ #include "ucw/lib.h" #include "ucw/log.h" +#include "ucw/log-internal.h" #include "ucw/simple-lists.h" #include @@ -20,10 +21,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,42 +40,46 @@ 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"; log_add_substream(ls, &log_stream_default); } -/* Close all open streams, un-initialize the module, free all memory, - * and fall back to using only log_stream_default. */ void log_close_all(void) { if (!log_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); + + // Close all streams that remain and free all cached structures for (int i=0; i < log_streams_after; i++) { - if (log_streams.ptr[i]->regnum >= 0) - log_close_stream(log_streams.ptr[i]); - xfree(log_streams.ptr[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); } /* Back to the default state */ lsbuf_done(&log_streams); log_streams_after = 0; - log_streams_free = -1; + log_streams_free = ~0U; log_initialized = 0; } -/* Add a new substream. The parent stream takes a reference on the substream, - * preventing it from being closed as long as it is linked. */ void log_add_substream(struct log_stream *where, struct log_stream *what) { @@ -86,9 +91,6 @@ 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 - * keep. If a substream becomes unreferenced, it is closed. If what is NULL, - * all substreams are removed. Returns the number of deleted entries. */ int log_rm_substream(struct log_stream *where, struct log_stream *what) { @@ -107,9 +109,8 @@ log_rm_substream(struct log_stream *where, struct log_stream *what) return cnt; } -/* 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,30 +119,29 @@ 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 */ bzero(l, sizeof(*l)); - l->levels = LS_ALL_LEVELS; + l->levels = ~0U; + l->types = ~0U; l->regnum = LS_SET_STRNUM(index); clist_init(&l->substreams); return log_ref_stream(l); } -/* Remove a reference on a stream and close it if it was the last reference. - * Closing automatically unlinks all substreams and closes them if they are - * no longer referenced. Returns 1 if the stream has been really closed. */ int log_close_stream(struct log_stream *ls) { @@ -156,8 +156,48 @@ 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; } + +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; +}