]> mj.ucw.cz Git - libucw.git/blob - ucw/log-stream.c
01ada42021118940f55dac7e453d5b5d4044cc78
[libucw.git] / ucw / log-stream.c
1 /*
2  *      UCW Library -- Logging: Management of Log Streams
3  *
4  *      (c) 2008 Tomas Gavenciak <gavento@ucw.cz>
5  *      (c) 2009 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "ucw/lib.h"
12 #include "ucw/log.h"
13 #include "ucw/simple-lists.h"
14
15 #include <string.h>
16
17 /* Initial number of streams to allocate (must be >=2) */
18 #define LS_INIT_STREAMS 8
19
20 /* Flag indicating initialization of the module */
21 static int log_initialized = 0;
22
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;
27
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). */
31 static void
32 log_init_module(void)
33 {
34   if (log_initialized)
35     return;
36
37   /* Create the growing array */
38   lsbuf_init(&log_streams);
39   lsbuf_set_size(&log_streams, LS_INIT_STREAMS);
40
41   bzero(log_streams.ptr, sizeof(struct log_stream*) * (log_streams.len));
42   log_streams_free = -1;
43
44   log_initialized = 1;
45
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);
50   ls->name = "default";
51   log_add_substream(ls, (struct log_stream *) &log_stream_default);
52
53   // FIXME
54   msg(L_DEBUG, "logstream module initialized.");
55 }
56
57 /* Close all open streams, un-initialize the module, free all memory,
58  * and fall back to using only log_stream_default. */
59 void
60 log_close_all(void)
61 {
62   if (!log_initialized)
63     return;
64
65   for (int i=0; i < log_streams_after; i++)
66     {
67       if (log_streams.ptr[i]->regnum >= 0)
68         log_close_stream(log_streams.ptr[i]);
69       xfree(log_streams.ptr[i]);
70     }
71
72   /* Back to the default state */
73   lsbuf_done(&log_streams);
74   log_streams_after = 0;
75   log_streams_free = -1;
76   log_initialized = 0;
77 }
78
79 /* Add a new substream, xmalloc()-ate a new simp_node. */
80 void
81 log_add_substream(struct log_stream *where, struct log_stream *what)
82 {
83   ASSERT(where);
84   ASSERT(what);
85
86   simp_node *n = xmalloc(sizeof(simp_node));
87   n->p = what;
88   clist_add_tail(&where->substreams, &n->n);
89 }
90
91 /* Remove all occurences of a substream, xfree() the simp_node. */
92 /* Return the number of deleted entries. */
93 int
94 log_rm_substream(struct log_stream *where, struct log_stream *what)
95 {
96   void *tmp;
97   int cnt = 0;
98   ASSERT(where);
99   ASSERT(what);
100
101   CLIST_FOR_EACH_DELSAFE(simp_node *, i, where->substreams, tmp)
102     if (i->p == what)
103       {
104         clist_remove(&i->n);
105         xfree(i);
106         cnt++;
107       }
108   return cnt;
109 }
110
111 /* Return a pointer to a new stream with no handler and an empty substream list. */
112 struct log_stream *
113 log_new_stream(void)
114 {
115   struct log_stream *l;
116   int index;
117
118   /* Initialize the data structures if needed */
119   log_init_module();
120
121   /* Get a free stream, possibly recycling a closed one */
122   if (log_streams_free < 0)
123     {
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));
127     }
128   else
129     {
130       index = log_streams_free;
131   l = log_streams.ptr[index];
132       log_streams_free = l->idata;
133     }
134
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);
140   return l;
141 }
142
143 /* Close a stream, unlink (but do not close) all its substreams */
144 void
145 log_close_stream(struct log_stream *ls)
146 {
147   void *tmp;
148   ASSERT(ls);
149
150   /* xfree() all the simp_nodes from substreams */
151   CLIST_FOR_EACH_DELSAFE(simp_node *, i, ls->substreams, tmp)
152     {
153       clist_remove(&i->n);
154       xfree(i);
155     }
156
157   /* Close the stream and add it to the free-list */
158   if (ls->close)
159     ls->close(ls);
160   ls->idata = log_streams_free;
161   log_streams_free = LS_GET_STRNUM(ls->regnum);
162   ls->regnum = -1;
163 }