d030d5cbef3e88319c971a39f3f275bb6926274a
[strongswan.git] / Source / charon / utils / logger_manager.c
1 /**
2 * @file logger_manager.c
3 *
4 * @brief Implementation of logger_manager_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23
24 #include "logger_manager.h"
25
26 #include <definitions.h>
27 #include <utils/allocator.h>
28 #include <utils/linked_list.h>
29
30 mapping_t logger_context_t_mappings[] = {
31 {PARSER, "PARSER"},
32 {GENERATOR, "GENRAT"},
33 {IKE_SA, "IKE_SA"},
34 {IKE_SA_MANAGER, "ISAMGR"},
35 {MESSAGE, "MESSAG"},
36 {THREAD_POOL, "THPOOL"},
37 {WORKER, "WORKER"},
38 {SCHEDULER, "SCHEDU"},
39 {SENDER, "SENDER"},
40 {RECEIVER, "RECEVR"},
41 {SOCKET, "SOCKET"},
42 {TESTER, "TESTER"},
43 {DAEMON, "DAEMON"},
44 {CONFIGURATION_MANAGER, "CONFIG"},
45 };
46
47 /**
48 * Maximum length of a logger name
49 */
50 #define MAX_LOGGER_NAME 45
51
52
53 typedef struct private_logger_manager_t private_logger_manager_t;
54
55 /**
56 * Private data of logger_manager_t object.
57 */
58 struct private_logger_manager_t {
59 /**
60 * Public data.
61 */
62 logger_manager_t public;
63
64 /**
65 * Managed loggers.
66 */
67 linked_list_t *loggers;
68
69 /**
70 * Log Levels.
71 */
72 linked_list_t *logger_levels;
73
74 /**
75 * Used to manage logger list.
76 */
77 pthread_mutex_t mutex;
78
79 /**
80 * Default logger level for a created logger used
81 * if no specific logger_level is set.
82 */
83 logger_level_t default_log_level;
84
85 /**
86 * Sets set logger_level of a specific context.
87 *
88 * @param this calling object
89 * @param context context to set level
90 * @param logger_level logger_level to set
91 * @param enable enable specific level or disable it
92 */
93 void (*set_logger_level) (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable);
94
95 };
96
97
98 typedef struct logger_levels_entry_t logger_levels_entry_t;
99
100 /**
101 * Entry in the logger_levels linked list.
102 *
103 * This entry specifies the current log level for
104 * logger_t objects in specific context.
105 */
106 struct logger_levels_entry_t {
107 logger_context_t context;
108 logger_level_t level;
109 };
110
111 typedef struct loggers_entry_t loggers_entry_t;
112
113 /**
114 * Entry in the loggers linked list.
115 */
116 struct loggers_entry_t {
117 logger_context_t context;
118 logger_t *logger;
119 };
120
121 /**
122 * Implementation of logger_manager_t.create_logger.
123 */
124 static logger_t *create_logger(private_logger_manager_t *this, logger_context_t context, char * name)
125 {
126
127 char * context_name;
128 bool log_thread_ids = TRUE;
129 FILE * output = NULL;
130 char buffer[MAX_LOGGER_NAME];
131 loggers_entry_t *entry;
132 logger_t *logger;
133 logger_level_t logger_level = 0;
134
135 context_name = mapping_find(logger_context_t_mappings,context);
136
137 /* output to stdout, since we are debugging all days */
138 output = stdout;
139
140 switch(context)
141 {
142 case TESTER:
143 log_thread_ids = FALSE;
144 output = stdout;
145 logger_level |= FULL;
146 break;
147 case IKE_SA:
148 logger_level |= FULL;
149 case IKE_SA_MANAGER:
150 case MESSAGE:
151 case WORKER:
152 logger_level |= ALL;
153 case PARSER:
154 case GENERATOR:
155 case THREAD_POOL:
156 case SCHEDULER:
157 case SENDER:
158 case RECEIVER:
159 case SOCKET:
160 case DAEMON:
161 case CONFIGURATION_MANAGER:
162 log_thread_ids = FALSE;
163 logger_level |= ERROR|CONTROL;
164 break;
165 }
166
167
168 /* reduce to global definiton of loglevel */
169 logger_level &= this->public.get_logger_level(&(this->public),context);
170
171 /* logger manager is thread save */
172 pthread_mutex_lock(&(this->mutex));
173 if (name != NULL)
174 {
175 snprintf(buffer, MAX_LOGGER_NAME, "%s - %s",context_name,name);
176 /* create logger with default log_level */
177 logger = logger_create(buffer,logger_level,log_thread_ids,output);
178 }
179 else
180 {
181 logger = logger_create(context_name,logger_level,log_thread_ids,output);
182 }
183
184
185 entry = allocator_alloc_thing(loggers_entry_t);
186
187 entry->context = context;
188 entry->logger = logger;
189
190 this->loggers->insert_last(this->loggers,entry);
191
192 pthread_mutex_unlock(&(this->mutex));
193 return logger;
194
195 }
196
197 /**
198 * Implementation of logger_manager_t.get_logger_level.
199 */
200 static logger_level_t get_logger_level (private_logger_manager_t *this, logger_context_t context)
201 {
202 iterator_t *iterator;
203 /* set logger_level to default logger_level */
204 logger_level_t logger_level = this->default_log_level;
205
206 pthread_mutex_lock(&(this->mutex));
207
208 iterator = this->logger_levels->create_iterator(this->logger_levels,TRUE);
209 /* check for existing logger_level entry */
210 while (iterator->has_next(iterator))
211 {
212 logger_levels_entry_t * entry;
213 iterator->current(iterator,(void **)&entry);
214 if (entry->context == context)
215 {
216 logger_level = entry->level;
217 break;
218 }
219 }
220 iterator->destroy(iterator);
221
222 pthread_mutex_unlock(&(this->mutex));
223 return logger_level;
224 }
225
226 /**
227 * Implementation of logger_manager_t.destroy_logger.
228 */
229 static void destroy_logger(private_logger_manager_t *this,logger_t *logger)
230 {
231 iterator_t *iterator;
232
233 pthread_mutex_lock(&(this->mutex));
234
235 iterator = this->loggers->create_iterator(this->loggers,TRUE);
236 while (iterator->has_next(iterator))
237 {
238 loggers_entry_t * entry;
239 iterator->current(iterator,(void **)&entry);
240 if (entry->logger == logger)
241 {
242 iterator->remove(iterator);
243 allocator_free(entry);
244 logger->destroy(logger);
245 break;
246 }
247 }
248 iterator->destroy(iterator);
249 pthread_mutex_unlock(&(this->mutex));
250 }
251
252 /**
253 * Implementation of private_logger_manager_t.set_logger_level.
254 */
255 static void set_logger_level(private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable)
256 {
257 iterator_t *iterator;
258 bool found = FALSE;
259
260 pthread_mutex_lock(&(this->mutex));
261 iterator = this->logger_levels->create_iterator(this->logger_levels,TRUE);
262
263 /* find existing logger_level entry */
264 while (iterator->has_next(iterator))
265 {
266 logger_levels_entry_t * entry;
267 iterator->current(iterator,(void **)&entry);
268 if (entry->context == context)
269 {
270 if (enable)
271 {
272 entry->level |= logger_level;
273 }
274 else
275 {
276 entry->level &= ~logger_level;
277 }
278 found = TRUE;
279 break;
280 }
281 }
282 iterator->destroy(iterator);
283
284 if (!found)
285 {
286 /* logger_levels entry not existing for current context */
287 logger_levels_entry_t *entry = allocator_alloc_thing(logger_levels_entry_t);
288
289 entry->context = context;
290 entry->level = (enable) ? logger_level : (this->default_log_level & (~logger_level));
291
292 this->logger_levels->insert_last(this->logger_levels,entry);
293 }
294
295 iterator = this->loggers->create_iterator(this->loggers,TRUE);
296 while (iterator->has_next(iterator))
297 {
298 loggers_entry_t * entry;
299 iterator->current(iterator,(void **)&entry);
300
301 if (entry->context == context)
302 {
303 if (enable)
304 {
305 entry->logger->enable_level(entry->logger,logger_level);
306 }
307 else
308 {
309 entry->logger->disable_level(entry->logger,logger_level);
310 }
311
312 }
313 }
314 iterator->destroy(iterator);
315
316 pthread_mutex_unlock(&(this->mutex));
317 }
318
319 /**
320 * Implementation of logger_manager_t.enable_logger_level.
321 */
322 static void enable_logger_level(private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
323 {
324 return set_logger_level(this,context,logger_level,TRUE);
325 }
326
327 /**
328 * Implementation of logger_manager_t.disable_logger_level.
329 */
330 static void disable_logger_level(private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
331 {
332 return set_logger_level(this,context,logger_level,FALSE);
333 }
334
335 /**
336 * Implementation of logger_manager_t.destroy.
337 */
338 static void destroy(private_logger_manager_t *this)
339 {
340
341 while (this->loggers->get_count(this->loggers) > 0)
342 {
343 loggers_entry_t *current_entry;
344
345 this->loggers->remove_first(this->loggers,(void **)&current_entry);
346
347 /* destroy logger object */
348 current_entry->logger->destroy(current_entry->logger);
349
350 /* entry can be destroyed */
351 allocator_free(current_entry);
352 }
353
354 while (this->logger_levels->get_count(this->logger_levels) > 0)
355 {
356 logger_levels_entry_t *current_entry;
357
358 this->logger_levels->remove_first(this->logger_levels,(void **)&current_entry);
359
360 /* entry can be destroyed */
361 allocator_free(current_entry);
362 }
363
364 this->loggers->destroy(this->loggers);
365 this->logger_levels->destroy(this->logger_levels);
366 pthread_mutex_destroy(&(this->mutex));
367
368 allocator_free(this);
369 }
370
371 /*
372 * Described in header.
373 */
374 logger_manager_t *logger_manager_create(logger_level_t default_log_level)
375 {
376 private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
377
378 this->public.create_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context, char *))create_logger;
379 this->public.destroy_logger = (void(*)(logger_manager_t*,logger_t *logger))destroy_logger;
380 this->public.destroy = (void(*)(logger_manager_t*))destroy;
381 this->public.get_logger_level = (logger_level_t (*)(logger_manager_t *, logger_context_t)) get_logger_level;
382 this->public.enable_logger_level = (void (*)(logger_manager_t *, logger_context_t,logger_level_t)) enable_logger_level;
383 this->public.disable_logger_level = (void (*)(logger_manager_t *, logger_context_t,logger_level_t)) disable_logger_level;
384 this->set_logger_level = (void (*)(private_logger_manager_t *, logger_context_t,logger_level_t,bool)) set_logger_level;
385
386 /* private variables */
387 this->loggers = linked_list_create();
388 this->logger_levels = linked_list_create();
389 this->default_log_level = default_log_level;
390
391 pthread_mutex_init(&(this->mutex), NULL);
392
393 return (logger_manager_t*)this;
394 }
395