aab35baa3180ab5f48ce76b650108795fe657fe2
[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 TESTER:
126 context_name = "TESTER";
127 output = stdout;
128 break;
129 default:
130 context_name = mapping_find(logger_context_t_mappings,context);
131 break;
132 }
133 /* logger manager is thread save */
134 pthread_mutex_lock(&(this->mutex));
135 if (name != NULL)
136 {
137 snprintf(buffer, MAX_LOGGER_NAME, "%s - %s",context_name,name);
138 /* create logger with default log_level */
139 logger = logger_create(buffer,logger_level,output);
140 }
141 else
142 {
143 logger = logger_create(context_name,logger_level,output);
144 }
145
146
147 if (logger == NULL)
148 {
149 pthread_mutex_unlock(&(this->mutex));
150 return NULL;
151 }
152
153 entry = allocator_alloc_thing(loggers_entry_t);
154
155 if (entry == NULL)
156 {
157 logger->destroy(logger);
158 pthread_mutex_unlock(&(this->mutex));
159 return NULL;
160 }
161
162 entry->context = context;
163 entry->logger = logger;
164
165 if (this->loggers->insert_last(this->loggers,entry) != SUCCESS)
166 {
167 allocator_free(entry);
168 logger->destroy(logger);
169 pthread_mutex_unlock(&(this->mutex));
170 return NULL;
171 }
172
173 pthread_mutex_unlock(&(this->mutex));
174 return logger;
175
176 }
177
178 /**
179 * Implements logger_manager_t-function get_logger_level.
180 * @see logger_manager_s.get_logger_level.
181 */
182 static logger_level_t get_logger_level (private_logger_manager_t *this, logger_context_t context)
183 {
184 linked_list_iterator_t *iterator;
185 /* set logger_level to default logger_level */
186 logger_level_t logger_level = this->default_log_level;
187
188 pthread_mutex_lock(&(this->mutex));
189
190 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
191 {
192 pthread_mutex_unlock(&(this->mutex));
193 return logger_level;
194 }
195
196 /* check for existing logger_level entry */
197 while (iterator->has_next(iterator))
198 {
199
200 logger_levels_entry_t * entry;
201 if (iterator->current(iterator,(void **)&entry) != SUCCESS)
202 {
203 break;
204 }
205 if (entry->context == context)
206 {
207 logger_level = entry->level;
208 break;
209 }
210 }
211
212 iterator->destroy(iterator);
213
214 pthread_mutex_unlock(&(this->mutex));
215 return logger_level;
216 }
217
218 /**
219 * Implements logger_manager_t-function destroy_logger.
220 * @see logger_manager_s.destroy_logger.
221 */
222 static status_t destroy_logger (private_logger_manager_t *this,logger_t *logger)
223 {
224
225 linked_list_iterator_t *iterator;
226 status_t status;
227
228 pthread_mutex_lock(&(this->mutex));
229 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
230 {
231 pthread_mutex_unlock(&(this->mutex));
232 return OUT_OF_RES;
233 }
234
235 while (iterator->has_next(iterator))
236 {
237
238 loggers_entry_t * entry;
239 status = iterator->current(iterator,(void **)&entry);
240 if (status != SUCCESS)
241 {
242 break;
243 }
244 status = NOT_FOUND;
245 if (entry->logger == logger)
246 {
247 this->loggers->remove(this->loggers,iterator);
248 allocator_free(entry);
249 logger->destroy(logger);
250 status = SUCCESS;
251 break;
252 }
253 }
254 iterator->destroy(iterator);
255 pthread_mutex_unlock(&(this->mutex));
256 return status;
257 }
258
259 /**
260 * Implements private_logger_manager_t-function set_logger_level.
261 * @see private_logger_manager_s.set_logger_level.
262 */
263 static status_t set_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level,bool enable)
264 {
265 linked_list_iterator_t *iterator;
266 status_t status;
267
268 pthread_mutex_lock(&(this->mutex));
269 if (this->logger_levels->create_iterator(this->logger_levels,&iterator,TRUE) != SUCCESS)
270 {
271 pthread_mutex_unlock(&(this->mutex));
272 return OUT_OF_RES;
273 }
274
275 status = NOT_FOUND;
276 /* find existing logger_level entry */
277 while (iterator->has_next(iterator))
278 {
279 logger_levels_entry_t * entry;
280 status = iterator->current(iterator,(void **)&entry);
281 if (status != SUCCESS)
282 {
283 iterator->destroy(iterator);
284 pthread_mutex_unlock(&(this->mutex));
285 return status;
286 }
287 status = NOT_FOUND;
288 if (entry->context == context)
289 {
290 if (enable)
291 {
292 entry->level |= logger_level;
293 }
294 else
295 {
296 entry->level &= ~logger_level;
297 }
298
299 status = SUCCESS;
300 break;
301 }
302 }
303 iterator->destroy(iterator);
304
305 if (status == NOT_FOUND)
306 {
307 /* logger_levels entry not existing for current context */
308 logger_levels_entry_t *entry = allocator_alloc_thing(logger_levels_entry_t);
309 if (entry == NULL)
310 {
311 pthread_mutex_unlock(&(this->mutex));
312 return OUT_OF_RES;
313 }
314 entry->context = context;
315 entry->level = (enable) ? logger_level : (this->default_log_level & (~logger_level));
316
317 status = this->logger_levels->insert_last(this->logger_levels,entry);
318 if (status != SUCCESS)
319 {
320 allocator_free(entry);
321 pthread_mutex_unlock(&(this->mutex));
322 return status;
323 }
324 }
325
326 if (this->loggers->create_iterator(this->loggers,&iterator,TRUE) != SUCCESS)
327 {
328 pthread_mutex_unlock(&(this->mutex));
329 return OUT_OF_RES;
330 }
331
332 while (iterator->has_next(iterator))
333 {
334
335 loggers_entry_t * entry;
336 status = iterator->current(iterator,(void **)&entry);
337 if (status != SUCCESS)
338 {
339 iterator->destroy(iterator);
340 pthread_mutex_unlock(&(this->mutex));
341 return status;
342 }
343 if (entry->context == context)
344 {
345 if (enable)
346 {
347 status = entry->logger->enable_level(entry->logger,logger_level);
348 }
349 else
350 {
351 status = entry->logger->disable_level(entry->logger,logger_level);
352 }
353
354 }
355 }
356
357 iterator->destroy(iterator);
358 pthread_mutex_unlock(&(this->mutex));
359 return SUCCESS;
360 }
361
362 /**
363 * Implements logger_manager_t-function enable_logger_level.
364 * @see logger_manager_s.enable_logger_level.
365 */
366 static status_t enable_logger_level (private_logger_manager_t *this, logger_context_t context,logger_level_t logger_level)
367 {
368 return set_logger_level(this,context,logger_level,TRUE);
369 }
370
371 /**
372 * Implements logger_manager_t-function disable_logger_level.
373 * @see logger_manager_s.disable_logger_level.
374 */
375 static status_t 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 * Implements logger_manager_t-function destroy.
382 * @see logger_manager_s.destroy.
383 */
384 static status_t destroy(private_logger_manager_t *this)
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 return SUCCESS;
415 }
416
417 /*
418 * Described in header
419 */
420 logger_manager_t *logger_manager_create(logger_level_t default_log_level)
421 {
422 private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
423
424 if (this == NULL)
425 {
426 return NULL;
427 }
428
429 this->public.create_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context, char *))create_logger;
430 this->public.destroy_logger = (status_t(*)(logger_manager_t*,logger_t *logger))destroy_logger;
431 this->public.destroy = (status_t(*)(logger_manager_t*))destroy;
432 this->public.get_logger_level = (logger_level_t (*)(logger_manager_t *, logger_context_t)) get_logger_level;
433 this->public.enable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) enable_logger_level;
434 this->public.disable_logger_level = (status_t (*)(logger_manager_t *, logger_context_t,logger_level_t)) disable_logger_level;
435 this->set_logger_level = (status_t (*)(private_logger_manager_t *, logger_context_t,logger_level_t,bool)) set_logger_level;
436
437 /* private variables */
438 this->loggers = linked_list_create();
439
440 if (this->loggers == NULL)
441 {
442 allocator_free(this);
443 return NULL;
444 }
445 this->logger_levels = linked_list_create();
446 if (this->logger_levels == NULL)
447 {
448 this->loggers->destroy(this->loggers);
449 allocator_free(this);
450 return NULL;
451 }
452 this->default_log_level = default_log_level;
453
454 pthread_mutex_init(&(this->mutex), NULL);
455
456 return (logger_manager_t*)this;
457 }
458