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