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.
13 #include "ucw/simple-lists.h"
17 /* Initial number of streams to allocate (must be >=2) */
18 #define LS_INIT_STREAMS 8
20 /* Flag indicating initialization of the module */
21 static int log_initialized = 0;
23 /* The head of the list of freed log_streams indexes in log_streams.ptr (-1 if none free).
24 * Freed positions in log_streams.ptr are connected into a linked list in the following way:
25 * log_streams.ptr[log_streams_free].idata is the index of next freed position (or -1) */
26 static int log_streams_free = -1;
28 /* Initialize the logstream module.
29 * It is not neccessary to call this explicitely as it is called by
30 * the first log_new_stream() (for backward compatibility and ease of use). */
37 /* Create the growing array */
38 lsbuf_init(&log_streams);
39 lsbuf_set_size(&log_streams, LS_INIT_STREAMS);
41 bzero(log_streams.ptr, sizeof(struct log_stream*) * (log_streams.len));
42 log_streams_free = -1;
46 /* init the default stream (0) as forwarder to fd2 */
47 struct log_stream *ls = log_new_stream();
48 ASSERT(ls == log_streams.ptr[0]);
49 ASSERT(ls->regnum == 0);
51 log_add_substream(ls, (struct log_stream *) &log_stream_default);
54 msg(L_DEBUG, "logstream module initialized.");
57 /* Close all open streams, un-initialize the module, free all memory,
58 * and fall back to using only log_stream_default. */
65 for (int i=0; i < log_streams_after; i++)
67 if (log_streams.ptr[i]->regnum >= 0)
68 log_close_stream(log_streams.ptr[i]);
69 xfree(log_streams.ptr[i]);
72 /* Back to the default state */
73 lsbuf_done(&log_streams);
74 log_streams_after = 0;
75 log_streams_free = -1;
79 /* Add a new substream, xmalloc()-ate a new simp_node. */
81 log_add_substream(struct log_stream *where, struct log_stream *what)
86 simp_node *n = xmalloc(sizeof(simp_node));
88 clist_add_tail(&where->substreams, &n->n);
91 /* Remove all occurences of a substream, xfree() the simp_node. */
92 /* Return the number of deleted entries. */
94 log_rm_substream(struct log_stream *where, struct log_stream *what)
101 CLIST_FOR_EACH_DELSAFE(simp_node *, i, where->substreams, tmp)
111 /* Return a pointer to a new stream with no handler and an empty substream list. */
115 struct log_stream *l;
118 /* Initialize the data structures if needed */
121 /* Get a free stream, possibly recycling a closed one */
122 if (log_streams_free < 0)
124 lsbuf_grow(&log_streams, log_streams_after+1);
125 index = log_streams_after++;
126 l = log_streams.ptr[log_streams_free] = xmalloc(sizeof(struct log_stream));
130 index = log_streams_free;
131 l = log_streams.ptr[index];
132 log_streams_free = l->idata;
135 /* Initialize the stream */
136 bzero(l, sizeof(*l));
137 l->levels = LS_ALL_LEVELS;
138 l->regnum = LS_SET_STRNUM(index);
139 clist_init(&l->substreams);
143 /* Close a stream, unlink (but do not close) all its substreams */
145 log_close_stream(struct log_stream *ls)
150 /* xfree() all the simp_nodes from substreams */
151 CLIST_FOR_EACH_DELSAFE(simp_node *, i, ls->substreams, tmp)
157 /* Close the stream and add it to the free-list */
160 ls->idata = log_streams_free;
161 log_streams_free = LS_GET_STRNUM(ls->regnum);