- still one memory leak and segmentation fault
[strongswan.git] / Source / charon / utils / logger_manager.c
1 /**
2 * @file logger_manager.c
3 *
4 * @brief Logger manager. Manages globaly all logger objects
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 "allocator.h"
27 #include "linked_list.h"
28 #include "../definitions.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 };
45
46 /**
47 * Maximum length of a logger name
48 */
49 #define MAX_LOGGER_NAME 45
50
51 typedef struct private_logger_manager_s private_logger_manager_t;
52 struct private_logger_manager_s {
53 /**
54 * Public data.
55 */
56 logger_manager_t public;
57
58 /**
59 * Managed loggers.
60 */
61 linked_list_t *loggers;
62
63 /**
64 * Log Levels.
65 */
66 linked_list_t *logger_levels;
67
68 /**
69 * Used to manage logger list.
70 */
71 pthread_mutex_t mutex;
72
73 /**
74 * Default logger level for a created logger used if no specific logger_level is set
75 */
76 logger_level_t default_log_level;
77
78 /**
79 * Sets set logger_level of a specific context.
80 * @param this calling object
81 * @param context context to set level
82 * @param logger_level logger_level to set
83 * @param enable enable specific level or disable it
84 * @return SUCCESS
85 */
86 status_t (*set_logger_level) (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable);
87
88 };
89
90 /**
91 * Entry in the logger_levels linked list
92 */
93 typedef struct logger_levels_entry_s logger_levels_entry_t;
94
95 struct logger_levels_entry_s{
96 logger_context_t context;
97 logger_level_t level;
98 };
99
100 /**
101 * Entry in the loggers linked list
102 */
103 typedef struct loggers_entry_s loggers_entry_t;
104
105 struct loggers_entry_s{
106 logger_context_t context;
107 logger_t *logger;
108 };
109
110 /**
111 * Implements logger_manager_t-function create_logger.
112 * @see logger_manager_s.create_logger.
113 */
114 static logger_t *create_logger(private_logger_manager_t *this, logger_context_t context, char * name)
115 {
116
117 char * context_name;
118 bool log_thread_ids = TRUE;
119 FILE * output = NULL;
120 char buffer[MAX_LOGGER_NAME];
121 loggers_entry_t *entry;
122 logger_t *logger;
123 logger_level_t logger_level = this->public.get_logger_level(&(this->public),context);
124
125 context_name = mapping_find(logger_context_t_mappings,context);
126
127 switch(context)
128 {
129 case TESTER:
130 log_thread_ids = FALSE;
131 output = stdout;
132 break;
133 case SCHEDULER:
134 case SENDER:
135 case RECEIVER:
136 case THREAD_POOL:
137 case SOCKET:
138 case DAEMON:
139 log_thread_ids = FALSE;
140 break;
141 default:
142 break;
143 }
144 /* logger manager is thread save */
145 pthread_mutex_lock(&(this->mutex));
146 if (name != NULL)
147 {
148 snprintf(buffer, MAX_LOGGER_NAME, "%s - %s",context_name,name);
149 /* create logger with default log_level */
150 logger = logger_create(buffer,logger_level,log_thread_ids,output);
151 }
152 else
153 {
154 logger = logger_create(context_name,logger_level,log_thread_ids,output);
155 }
156
157
158 if (logger == NULL)
159 {
160 pthread_mutex_unlock(&(this->mutex));
161 return NULL;
162 }
163
164 entry = allocator_alloc_thing(loggers_entry_t);
165
166 if (entry == NULL)
167 {
168 logger->destroy(logger);
169 pthread_mutex_unlock(&(this->mutex));
170 return NULL;
171 }
172
173 entry->context = context;
174 entry->logger = logger;
175
176 if (this->loggers->insert_last(this->loggers,entry) != SUCCESS)
177 {
178 allocator_free(entry);
179 logger->destroy(logger);
180 pthread_mutex_unlock(&(this->mutex));
181 return NULL;
182 }
183
184 pthread_mutex_unlock(&(this->mutex));
185 return logger;
186
187 }
188
189 /**
190 * Implements logger_manager_t-function get_logger_level.
191 * @see logger_manager_s.get_logger_level.
192 */
193 static logger_level_t get_logger_level (private_logger_manager_t *this, logger_context_t context)
194 {
195 linked_list_iterator_t *iterator;
196 /* set logger_level to default logger_level */
197 logger_level_t logger_level = this->default_log_level;
198
199 pthread_mutex_lock(&(this->mutex));
200
201 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
202 {
203 pthread_mutex_unlock(&(this->mutex));
204 return logger_level;
205 }
206
207 /* check for existing logger_level entry */
208 while (iterator->has_next(iterator))
209 {
210
211 logger_levels_entry_t * entry;
212 if (iterator->current(iterator,(void **)&entry) != SUCCESS)
213 {
214 break;
215 }
216 if (entry->context == context)
217 {
218 logger_level = entry->level;
219 break;
220 }
221 }
222
223 iterator->destroy(iterator);
224
225 pthread_mutex_unlock(&(this->mutex));
226 return logger_level;
227 }
228
229 /**
230 * Implements logger_manager_t-function destroy_logger.
231 * @see logger_manager_s.destroy_logger.
232 */
233 static status_t destroy_logger (private_logger_manager_t *this,logger_t *logger)
234 {
235
236 linked_list_iterator_t *iterator;
237 status_t status = NOT_FOUND;
238
239 pthread_mutex_lock(&(this->mutex));
240 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
241 {
242 pthread_mutex_unlock(&(this->mutex));
243 return OUT_OF_RES;
244 }
245
246 while (iterator->has_next(iterator))
247 {
248
249 loggers_entry_t * entry;
250 status = iterator->current(iterator,(void **)&entry);
251 if (status != SUCCESS)
252 {
253 break;
254 }
255 status = NOT_FOUND;
256 if (entry->logger == logger)
257 {
258 this->loggers->remove(this->loggers,iterator);
259 allocator_free(entry);
260 logger->destroy(logger);
261 status = SUCCESS;
262 break;
263 }
264 }
265 iterator->destroy(iterator);
266 pthread_mutex_unlock(&(this->mutex));
267 return status;
268 }
269
270 /**
271 * Implements private_logger_manager_t-function set_logger_level.
272 * @see private_logger_manager_s.set_logger_level.
273 */
274 static status_t set_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable)
275 {
276 linked_list_iterator_t *iterator;
277 status_t status;
278
279 pthread_mutex_lock(&(this->mutex));
280 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
281 {
282 pthread_mutex_unlock(&(this->mutex));
283 return OUT_OF_RES;
284 }
285
286 status = NOT_FOUND;
287 /* find existing logger_level entry */
288 while (iterator->has_next(iterator))
289 {
290 logger_levels_entry_t * entry;
291 status = iterator->current(iterator,(void **)&entry);
292 if (status != SUCCESS)
293 {
294 iterator->destroy(iterator);
295 pthread_mutex_unlock(&(this->mutex));
296 return status;
297 }
298 status = NOT_FOUND;
299 if (entry->context == context)
300 {
301 if (enable)
302 {
303 entry->level |= logger_level;
304 }
305 else
306 {
307 entry->level &= ~logger_level;
308 }
309
310 status = SUCCESS;
311 break;
312 }
313 }
314 iterator->destroy(iterator);
315
316 if (status == NOT_FOUND)
317 {
318 /* logger_levels entry not existing for current context */
319 logger_levels_entry_t *entry = allocator_alloc_thing(logger_levels_entry_t);
320 if (entry == NULL)
321 {
322 pthread_mutex_unlock(&(this->mutex));
323 return OUT_OF_RES;
324 }
325 entry->context = context;
326 entry->level = (enable) ? logger_level : (this->default_log_level & (~logger_level));
327
328 status = this->logger_levels->insert_last(this->logger_levels,entry);
329 if (status != SUCCESS)
330 {
331 allocator_free(entry);
332 pthread_mutex_unlock(&(this->mutex));
333 return status;
334 }
335 }
336
337 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
338 {
339 pthread_mutex_unlock(&(this->mutex));
340 return OUT_OF_RES;
341 }
342
343 while (iterator->has_next(iterator))
344 {
345
346 loggers_entry_t * entry;
347 status = iterator->current(iterator,(void **)&entry);
348 if (status != SUCCESS)
349 {
350 iterator->destroy(iterator);
351 pthread_mutex_unlock(&(this->mutex));
352 return status;
353 }
354 if (entry->context == context)
355 {
356 if (enable)
357 {
358 status = entry->logger->enable_level(entry->logger,logger_level);
359 }
360 else
361 {
362 status = entry->logger->disable_level(entry->logger,logger_level);
363 }
364
365 }
366 }
367
368 iterator->destroy(iterator);
369 pthread_mutex_unlock(&(this->mutex));
370 return SUCCESS;
371 }
372
373 /**
374 * Implements logger_manager_t-function enable_logger_level.
375 * @see logger_manager_s.enable_logger_level.
376 */
377 static status_t enable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
378 {
379 return set_logger_level(this,context,logger_level,TRUE);
380 }
381
382 /**
383 * Implements logger_manager_t-function disable_logger_level.
384 * @see logger_manager_s.disable_logger_level.
385 */
386 static status_t disable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
387 {
388 return set_logger_level(this,context,logger_level,FALSE);
389 }
390
391 /**
392 * Implements logger_manager_t-function destroy.
393 * @see logger_manager_s.destroy.
394 */
395 static status_t destroy(private_logger_manager_t *this)
396 {
397 while (this->loggers->get_count(this->loggers) > 0)
398 {
399 loggers_entry_t *current_entry;
400
401 this->loggers->remove_first(this->loggers,(void **)&current_entry);
402
403 /* destroy logger object */
404 current_entry->logger->destroy(current_entry->logger);
405
406 /* entry can be destroyed */
407 allocator_free(current_entry);
408 }
409
410 while (this->logger_levels->get_count(this->logger_levels) > 0)
411 {
412 logger_levels_entry_t *current_entry;
413
414 this->logger_levels->remove_first(this->logger_levels,(void **)&current_entry);
415
416 /* entry can be destroyed */
417 allocator_free(current_entry);
418 }
419
420 this->loggers->destroy(this->loggers);
421 this->logger_levels->destroy(this->logger_levels);
422 pthread_mutex_destroy(&(this->mutex));
423
424 allocator_free(this);
425 return SUCCESS;
426 }
427
428 /*
429 * Described in header
430 */
431 logger_manager_t *logger_manager_create(logger_level_t default_log_level)
432 {
433 private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
434
435 if (this == NULL)
436 {
437 return NULL;
438 }
439
440 this->public.create_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context, char *))create_logger;
441 this->public.destroy_logger = (status_t(*)(logger_manager_t*,logger_t *logger))destroy_logger;
442 this->public.destroy = (status_t(*)(logger_manager_t*))destroy;
443 this->public.get_logger_level = (logger_level_t (*)(logger_manager_t *, logger_context_t)) get_logger_level;
444 this->public.enable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) enable_logger_level;
445 this->public.disable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) disable_logger_level;
446 this->set_logger_level = (status_t (*)(private_logger_manager_t *, logger_context_t,logger_level_t,bool)) set_logger_level;
447
448 /* private variables */
449 this->loggers = linked_list_create();
450
451 if (this->loggers == NULL)
452 {
453 allocator_free(this);
454 return NULL;
455 }
456 this->logger_levels = linked_list_create();
457 if (this->logger_levels == NULL)
458 {
459 this->loggers->destroy(this->loggers);
460 allocator_free(this);
461 return NULL;
462 }
463 this->default_log_level = default_log_level;
464
465 pthread_mutex_init(&(this->mutex), NULL);
466
467 return (logger_manager_t*)this;
468 }
469