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