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