2d1587caced4c10966dcd10fbfd8c2ced89ee526
[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;
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
267 pthread_mutex_unlock(&(this->mutex));
268 return status;
269 }
270
271 /**
272 * Implements private_logger_manager_t-function set_logger_level.
273 * @see private_logger_manager_s.set_logger_level.
274 */
275 static status_t set_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable)
276 {
277 linked_list_iterator_t *iterator;
278 status_t status;
279
280 pthread_mutex_lock(&(this->mutex));
281 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
282 {
283 pthread_mutex_unlock(&(this->mutex));
284 return OUT_OF_RES;
285 }
286
287 status = NOT_FOUND;
288 /* find existing logger_level entry */
289 while (iterator->has_next(iterator))
290 {
291 logger_levels_entry_t * entry;
292 status = iterator->current(iterator,(void **)&entry);
293 if (status != SUCCESS)
294 {
295 iterator->destroy(iterator);
296 pthread_mutex_unlock(&(this->mutex));
297 return status;
298 }
299 status = NOT_FOUND;
300 if (entry->context == context)
301 {
302 if (enable)
303 {
304 entry->level |= logger_level;
305 }
306 else
307 {
308 entry->level &= ~logger_level;
309 }
310
311 status = SUCCESS;
312 break;
313 }
314 }
315 iterator->destroy(iterator);
316
317 if (status == NOT_FOUND)
318 {
319 /* logger_levels entry not existing for current context */
320 logger_levels_entry_t *entry = allocator_alloc_thing(logger_levels_entry_t);
321 if (entry == NULL)
322 {
323 pthread_mutex_unlock(&(this->mutex));
324 return OUT_OF_RES;
325 }
326 entry->context = context;
327 entry->level = (enable) ? logger_level : (this->default_log_level & (~logger_level));
328
329 status = this->logger_levels->insert_last(this->logger_levels,entry);
330 if (status != SUCCESS)
331 {
332 allocator_free(entry);
333 pthread_mutex_unlock(&(this->mutex));
334 return status;
335 }
336 }
337
338 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
339 {
340 pthread_mutex_unlock(&(this->mutex));
341 return OUT_OF_RES;
342 }
343
344 while (iterator->has_next(iterator))
345 {
346
347 loggers_entry_t * entry;
348 status = iterator->current(iterator,(void **)&entry);
349 if (status != SUCCESS)
350 {
351 iterator->destroy(iterator);
352 pthread_mutex_unlock(&(this->mutex));
353 return status;
354 }
355 if (entry->context == context)
356 {
357 if (enable)
358 {
359 status = entry->logger->enable_level(entry->logger,logger_level);
360 }
361 else
362 {
363 status = entry->logger->disable_level(entry->logger,logger_level);
364 }
365
366 }
367 }
368
369 iterator->destroy(iterator);
370 pthread_mutex_unlock(&(this->mutex));
371 return SUCCESS;
372 }
373
374 /**
375 * Implements logger_manager_t-function enable_logger_level.
376 * @see logger_manager_s.enable_logger_level.
377 */
378 static status_t enable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
379 {
380 return set_logger_level(this,context,logger_level,TRUE);
381 }
382
383 /**
384 * Implements logger_manager_t-function disable_logger_level.
385 * @see logger_manager_s.disable_logger_level.
386 */
387 static status_t disable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
388 {
389 return set_logger_level(this,context,logger_level,FALSE);
390 }
391
392 /**
393 * Implements logger_manager_t-function destroy.
394 * @see logger_manager_s.destroy.
395 */
396 static status_t destroy(private_logger_manager_t *this)
397 {
398 while (this->loggers->get_count(this->loggers) > 0)
399 {
400 loggers_entry_t *current_entry;
401
402 this->loggers->remove_first(this->loggers,(void **)&current_entry);
403
404 /* destroy logger object */
405 current_entry->logger->destroy(current_entry->logger);
406
407 /* entry can be destroyed */
408 allocator_free(current_entry);
409 }
410
411 while (this->logger_levels->get_count(this->logger_levels) > 0)
412 {
413 logger_levels_entry_t *current_entry;
414
415 this->logger_levels->remove_first(this->logger_levels,(void **)&current_entry);
416
417 /* entry can be destroyed */
418 allocator_free(current_entry);
419 }
420
421 this->loggers->destroy(this->loggers);
422 this->logger_levels->destroy(this->logger_levels);
423 pthread_mutex_destroy(&(this->mutex));
424
425 allocator_free(this);
426 return SUCCESS;
427 }
428
429 /*
430 * Described in header
431 */
432 logger_manager_t *logger_manager_create(logger_level_t default_log_level)
433 {
434 private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
435
436 if (this == NULL)
437 {
438 return NULL;
439 }
440
441 this->public.create_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context, char *))create_logger;
442 this->public.destroy_logger = (status_t(*)(logger_manager_t*,logger_t *logger))destroy_logger;
443 this->public.destroy = (status_t(*)(logger_manager_t*))destroy;
444 this->public.get_logger_level = (logger_level_t (*)(logger_manager_t *, logger_context_t)) get_logger_level;
445 this->public.enable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) enable_logger_level;
446 this->public.disable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) disable_logger_level;
447 this->set_logger_level = (status_t (*)(private_logger_manager_t *, logger_context_t,logger_level_t,bool)) set_logger_level;
448
449 /* private variables */
450 this->loggers = linked_list_create();
451
452 if (this->loggers == NULL)
453 {
454 allocator_free(this);
455 return NULL;
456 }
457 this->logger_levels = linked_list_create();
458 if (this->logger_levels == NULL)
459 {
460 this->loggers->destroy(this->loggers);
461 allocator_free(this);
462 return NULL;
463 }
464 this->default_log_level = default_log_level;
465
466 pthread_mutex_init(&(this->mutex), NULL);
467
468 return (logger_manager_t*)this;
469 }
470