2 * UCW Library -- Logging: Management of Log Streams
4 * (c) 2008 Tomas Gavenciak <gavento@ucw.cz>
5 * (c) 2009 Martin Mares <mj@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
12 #include "ucw/clists.h"
13 #include "ucw/simple-lists.h"
27 /* Flag indicating initialization of the module */
28 static int ls_initialized = 0;
30 /* The head of the list of freed log_streams indexes in ls_streams.ptr (-1 if none free).
31 * Freed positions in ls_streams.ptr are connected into a linked list in the following way:
32 * ls_streams.ptr[ls_streams_free].idata is the index of next freed position (or -1) */
33 static int ls_streams_free = -1;
35 /* Initialize the logstream module.
36 * It is not neccessary to call this explicitely as it is called by
37 * the first ls_new() (for backward compatibility and ease of use). */
38 static void ls_init_module(void)
40 if (ls_initialized) return;
42 /* create the grow array */
43 lsbuf_init(&log_streams);
44 lsbuf_set_size(&log_streams, LS_INIT_STREAMS);
46 bzero(log_streams.ptr, sizeof(struct log_stream*) * (log_streams.len));
51 /* init the default stream (0) as forwarder to fd2 */
52 struct log_stream *ls = ls_new();
53 ASSERT(ls == log_streams.ptr[0]);
54 ASSERT(ls->regnum == 0);
56 ls_add_substream(ls, (struct log_stream *) &ls_default_log);
59 ls_msg(L_DEBUG, "logstream module initialized.");
62 /* close all open streams, un-initialize the module, free all memory,
63 * use only ls_default_log */
64 void ls_close_all(void)
68 if (!ls_initialized) return;
70 for (i=0; i<log_streams_after; i++)
72 if (log_streams.ptr[i]->regnum>=0)
73 ls_close(log_streams.ptr[i]);
74 xfree(log_streams.ptr[i]);
77 /* set to the default state */
78 lsbuf_done(&log_streams);
84 /* add a new substream, malloc()-ate a new simp_node */
85 void ls_add_substream(struct log_stream *where, struct log_stream *what)
90 simp_node *n = xmalloc(sizeof(simp_node));
92 clist_add_tail(&(where->substreams), (cnode*)n);
95 /* remove all occurences of a substream, free() the simp_node */
96 /* return number of deleted entries */
97 int ls_rm_substream(struct log_stream *where, struct log_stream *what)
104 CLIST_FOR_EACH_DELSAFE(simp_node *, i, where->substreams, tmp)
107 clist_remove((cnode*)i);
114 /* Return a pointer to a new stream with no handler and an empty substream list. */
115 struct log_stream *ls_new(void)
117 struct log_stream *l;
120 /* initialize the array if not initialized already */
121 if (unlikely(ls_initialized==0))
124 /* there is no closed stream -- allocate a new one */
125 if (ls_streams_free==-1)
127 /* check the size of the pointer array */
128 lsbuf_grow(&log_streams, log_streams_after+1);
129 ls_streams_free = log_streams_after++;
130 log_streams.ptr[ls_streams_free] = xmalloc(sizeof(struct log_stream));
131 log_streams.ptr[ls_streams_free]->idata = -1;
132 log_streams.ptr[ls_streams_free]->regnum = -1;
135 ASSERT(ls_streams_free>=0);
137 /* initialize the stream */
138 index = ls_streams_free;
139 l = log_streams.ptr[index];
140 ls_streams_free = l->idata;
141 memset(l, 0, sizeof(struct log_stream));
142 l->levels = LS_ALL_LEVELS;
143 l->regnum = LS_SET_STRNUM(index);
144 l->substreams.head.next = &(l->substreams.head);
145 l->substreams.head.prev = &(l->substreams.head);
149 /* Close and remember given log_stream */
150 /* does not affect substreams, but frees the .substreams list */
151 void ls_close(struct log_stream *ls)
156 /* xfree() all the simp_nodes from substreams */
157 CLIST_FOR_EACH_DELSAFE(simp_node *, i, ls->substreams, tmp)
159 clist_remove((cnode*)i);
163 /* close and remember the stream */
166 ls->idata = ls_streams_free;
167 ls_streams_free = LS_GET_STRNUM(ls->regnum);