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