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