005e6948b2d54642fb61a45acaa9b6a7077949a8
[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 * @return
93 * - SUCCESS
94 * - OUT_OF_RES
95 */
96 status_t (*set_logger_level) (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable);
97
98 };
99
100
101 typedef struct logger_levels_entry_t logger_levels_entry_t;
102
103 /**
104 * Entry in the logger_levels linked list.
105 *
106 * This entry specifies the current log level for
107 * logger_t objects in specific context.
108 */
109 struct logger_levels_entry_t {
110 logger_context_t context;
111 logger_level_t level;
112 };
113
114 typedef struct loggers_entry_t loggers_entry_t;
115
116 /**
117 * Entry in the loggers linked list.
118 */
119 struct loggers_entry_t {
120 logger_context_t context;
121 logger_t *logger;
122 };
123
124 /**
125 * Implementation of logger_manager_t.create_logger.
126 */
127 static logger_t *create_logger(private_logger_manager_t *this, logger_context_t context, char * name)
128 {
129
130 char * context_name;
131 bool log_thread_ids = TRUE;
132 FILE * output = NULL;
133 char buffer[MAX_LOGGER_NAME];
134 loggers_entry_t *entry;
135 logger_t *logger;
136 logger_level_t logger_level = 0;
137
138 context_name = mapping_find(logger_context_t_mappings,context);
139
140 /* output to stdout, since we are debugging all days */
141 output = stdout;
142
143 switch(context)
144 {
145 case TESTER:
146 log_thread_ids = FALSE;
147 output = stdout;
148 logger_level |= FULL;
149 break;
150 case IKE_SA:
151 logger_level |= FULL;
152 case IKE_SA_MANAGER:
153 case MESSAGE:
154 logger_level |= ALL;
155 case PARSER:
156 case GENERATOR:
157 case THREAD_POOL:
158 case WORKER:
159 case SCHEDULER:
160 case SENDER:
161 case RECEIVER:
162 case SOCKET:
163 case DAEMON:
164 case CONFIGURATION_MANAGER:
165 log_thread_ids = FALSE;
166 logger_level |= ERROR|CONTROL;
167 break;
168 }
169
170
171 /* reduce to global definiton of loglevel */
172 logger_level &= this->public.get_logger_level(&(this->public),context);
173
174 /* logger manager is thread save */
175 pthread_mutex_lock(&(this->mutex));
176 if (name != NULL)
177 {
178 snprintf(buffer, MAX_LOGGER_NAME, "%s - %s",context_name,name);
179 /* create logger with default log_level */
180 logger = logger_create(buffer,logger_level,log_thread_ids,output);
181 }
182 else
183 {
184 logger = logger_create(context_name,logger_level,log_thread_ids,output);
185 }
186
187
188 if (logger == NULL)
189 {
190 pthread_mutex_unlock(&(this->mutex));
191 return NULL;
192 }
193
194 entry = allocator_alloc_thing(loggers_entry_t);
195
196 if (entry == NULL)
197 {
198 logger->destroy(logger);
199 pthread_mutex_unlock(&(this->mutex));
200 return NULL;
201 }
202
203 entry->context = context;
204 entry->logger = logger;
205
206 if (this->loggers->insert_last(this->loggers,entry) != SUCCESS)
207 {
208 allocator_free(entry);
209 logger->destroy(logger);
210 pthread_mutex_unlock(&(this->mutex));
211 return NULL;
212 }
213
214 pthread_mutex_unlock(&(this->mutex));
215 return logger;
216
217 }
218
219 /**
220 * Implementation of logger_manager_t.get_logger_level.
221 */
222 static logger_level_t get_logger_level (private_logger_manager_t *this, logger_context_t context)
223 {
224 iterator_t *iterator;
225 /* set logger_level to default logger_level */
226 logger_level_t logger_level = this->default_log_level;
227
228 pthread_mutex_lock(&(this->mutex));
229
230 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
231 {
232 pthread_mutex_unlock(&(this->mutex));
233 return logger_level;
234 }
235
236 /* check for existing logger_level entry */
237 while (iterator->has_next(iterator))
238 {
239
240 logger_levels_entry_t * entry;
241 if (iterator->current(iterator,(void **)&entry) != SUCCESS)
242 {
243 break;
244 }
245 if (entry->context == context)
246 {
247 logger_level = entry->level;
248 break;
249 }
250 }
251
252 iterator->destroy(iterator);
253
254 pthread_mutex_unlock(&(this->mutex));
255 return logger_level;
256 }
257
258 /**
259 * Implementation of logger_manager_t.destroy_logger.
260 */
261 static status_t destroy_logger (private_logger_manager_t *this,logger_t *logger)
262 {
263
264 iterator_t *iterator;
265 status_t status = NOT_FOUND;
266
267 pthread_mutex_lock(&(this->mutex));
268 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
269 {
270 pthread_mutex_unlock(&(this->mutex));
271 return OUT_OF_RES;
272 }
273
274 while (iterator->has_next(iterator))
275 {
276
277 loggers_entry_t * entry;
278 status = iterator->current(iterator,(void **)&entry);
279 if (status != SUCCESS)
280 {
281 break;
282 }
283 status = NOT_FOUND;
284 if (entry->logger == logger)
285 {
286 iterator->remove(iterator);
287 allocator_free(entry);
288 logger->destroy(logger);
289 status = SUCCESS;
290 break;
291 }
292 }
293 iterator->destroy(iterator);
294 pthread_mutex_unlock(&(this->mutex));
295 return status;
296 }
297
298 /**
299 * Implementation of private_logger_manager_t.set_logger_level.
300 */
301 static status_t set_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable)
302 {
303 iterator_t *iterator;
304 status_t status;
305
306 pthread_mutex_lock(&(this->mutex));
307 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
308 {
309 pthread_mutex_unlock(&(this->mutex));
310 return OUT_OF_RES;
311 }
312
313 status = NOT_FOUND;
314 /* find existing logger_level entry */
315 while (iterator->has_next(iterator))
316 {
317 logger_levels_entry_t * entry;
318 status = iterator->current(iterator,(void **)&entry);
319 if (status != SUCCESS)
320 {
321 iterator->destroy(iterator);
322 pthread_mutex_unlock(&(this->mutex));
323 return status;
324 }
325 status = NOT_FOUND;
326 if (entry->context == context)
327 {
328 if (enable)
329 {
330 entry->level |= logger_level;
331 }
332 else
333 {
334 entry->level &= ~logger_level;
335 }
336
337 status = SUCCESS;
338 break;
339 }
340 }
341 iterator->destroy(iterator);
342
343 if (status == NOT_FOUND)
344 {
345 /* logger_levels entry not existing for current context */
346 logger_levels_entry_t *entry = allocator_alloc_thing(logger_levels_entry_t);
347 if (entry == NULL)
348 {
349 pthread_mutex_unlock(&(this->mutex));
350 return OUT_OF_RES;
351 }
352 entry->context = context;
353 entry->level = (enable) ? logger_level : (this->default_log_level & (~logger_level));
354
355 status = this->logger_levels->insert_last(this->logger_levels,entry);
356 if (status != SUCCESS)
357 {
358 allocator_free(entry);
359 pthread_mutex_unlock(&(this->mutex));
360 return status;
361 }
362 }
363
364 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
365 {
366 pthread_mutex_unlock(&(this->mutex));
367 return OUT_OF_RES;
368 }
369
370 while (iterator->has_next(iterator))
371 {
372
373 loggers_entry_t * entry;
374 status = iterator->current(iterator,(void **)&entry);
375 if (status != SUCCESS)
376 {
377 iterator->destroy(iterator);
378 pthread_mutex_unlock(&(this->mutex));
379 return status;
380 }
381 if (entry->context == context)
382 {
383 if (enable)
384 {
385 status = entry->logger->enable_level(entry->logger,logger_level);
386 }
387 else
388 {
389 status = entry->logger->disable_level(entry->logger,logger_level);
390 }
391
392 }
393 }
394
395 iterator->destroy(iterator);
396 pthread_mutex_unlock(&(this->mutex));
397 return SUCCESS;
398 }
399
400 /**
401 * Implementation of logger_manager_t.enable_logger_level.
402 */
403 static status_t enable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
404 {
405 return set_logger_level(this,context,logger_level,TRUE);
406 }
407
408 /**
409 * Implementation of logger_manager_t.disable_logger_level.
410 */
411 static status_t disable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
412 {
413 return set_logger_level(this,context,logger_level,FALSE);
414 }
415
416 /**
417 * Implementation of logger_manager_t.destroy.
418 */
419 static status_t destroy(private_logger_manager_t *this)
420 {
421
422 while (this->loggers->get_count(this->loggers) > 0)
423 {
424 loggers_entry_t *current_entry;
425
426 this->loggers->remove_first(this->loggers,(void **)&current_entry);
427
428 /* destroy logger object */
429 current_entry->logger->destroy(current_entry->logger);
430
431 /* entry can be destroyed */
432 allocator_free(current_entry);
433 }
434
435 while (this->logger_levels->get_count(this->logger_levels) > 0)
436 {
437 logger_levels_entry_t *current_entry;
438
439 this->logger_levels->remove_first(this->logger_levels,(void **)&current_entry);
440
441 /* entry can be destroyed */
442 allocator_free(current_entry);
443 }
444
445 this->loggers->destroy(this->loggers);
446 this->logger_levels->destroy(this->logger_levels);
447 pthread_mutex_destroy(&(this->mutex));
448
449 allocator_free(this);
450 return SUCCESS;
451 }
452
453 /*
454 * Described in header.
455 */
456 logger_manager_t *logger_manager_create(logger_level_t default_log_level)
457 {
458 private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
459
460 if (this == NULL)
461 {
462 return NULL;
463 }
464
465 this->public.create_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context, char *))create_logger;
466 this->public.destroy_logger = (status_t(*)(logger_manager_t*,logger_t *logger))destroy_logger;
467 this->public.destroy = (status_t(*)(logger_manager_t*))destroy;
468 this->public.get_logger_level = (logger_level_t (*)(logger_manager_t *, logger_context_t)) get_logger_level;
469 this->public.enable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) enable_logger_level;
470 this->public.disable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) disable_logger_level;
471 this->set_logger_level = (status_t (*)(private_logger_manager_t *, logger_context_t,logger_level_t,bool)) set_logger_level;
472
473 /* private variables */
474 this->loggers = linked_list_create();
475
476 if (this->loggers == NULL)
477 {
478 allocator_free(this);
479 return NULL;
480 }
481 this->logger_levels = linked_list_create();
482 if (this->logger_levels == NULL)
483 {
484 this->loggers->destroy(this->loggers);
485 allocator_free(this);
486 return NULL;
487 }
488 this->default_log_level = default_log_level;
489
490 pthread_mutex_init(&(this->mutex), NULL);
491
492 return (logger_manager_t*)this;
493 }
494