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