File: | libbaul-private/baul-debug-log.c |
Warning: | line 229, column 17 Value stored to 'p' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- |
2 | |
3 | baul-debug-log.c: Ring buffer for logging debug messages |
4 | |
5 | Copyright (C) 2006 Novell, Inc. |
6 | |
7 | This program is free software; you can redistribute it and/or |
8 | modify it under the terms of the GNU General Public License as |
9 | published by the Free Software Foundation; either version 2 of the |
10 | License, or (at your option) any later version. |
11 | |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public |
18 | License along with this program; if not, write to the |
19 | Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
20 | Boston, MA 02110-1301, USA. |
21 | |
22 | Author: Federico Mena-Quintero <federico@novell.com> |
23 | */ |
24 | #include <config.h> |
25 | #include <errno(*__errno_location ()).h> |
26 | #include <stdio.h> |
27 | #include <string.h> |
28 | #include <time.h> |
29 | #include <sys/time.h> |
30 | #include "baul-debug-log.h" |
31 | #include "baul-file.h" |
32 | |
33 | #define DEFAULT_RING_BUFFER_NUM_LINES1000 1000 |
34 | |
35 | #define KEY_FILE_GROUP"debug log" "debug log" |
36 | #define KEY_FILE_DOMAINS_KEY"enable domains" "enable domains" |
37 | #define KEY_FILE_MAX_LINES_KEY"max lines" "max lines" |
38 | |
39 | #define MAX_URI_COUNT20 20 |
40 | |
41 | static GMutex log_mutex; |
42 | |
43 | static GHashTable *domains_hash; |
44 | static char **ring_buffer; |
45 | static int ring_buffer_next_index; |
46 | static int ring_buffer_num_lines; |
47 | static int ring_buffer_max_lines = DEFAULT_RING_BUFFER_NUM_LINES1000; |
48 | |
49 | static GSList *milestones_head; |
50 | static GSList *milestones_tail; |
51 | |
52 | static void |
53 | lock (void) |
54 | { |
55 | g_mutex_lock (&log_mutex); |
56 | } |
57 | |
58 | static void |
59 | unlock (void) |
60 | { |
61 | g_mutex_unlock (&log_mutex); |
62 | } |
63 | |
64 | void |
65 | baul_debug_log (gboolean is_milestone, const char *domain, const char *format, ...) |
66 | { |
67 | va_list args; |
68 | |
69 | va_start (args, format)__builtin_va_start(args, format); |
70 | baul_debug_logv (is_milestone, domain, NULL((void*)0), format, args); |
71 | va_end (args)__builtin_va_end(args); |
72 | } |
73 | |
74 | static gboolean |
75 | is_domain_enabled (const char *domain) |
76 | { |
77 | /* User actions are always logged */ |
78 | if (strcmp (domain, BAUL_DEBUG_LOG_DOMAIN_USER"USER") == 0) |
79 | return TRUE(!(0)); |
80 | |
81 | if (!domains_hash) |
82 | return FALSE(0); |
83 | |
84 | return (g_hash_table_lookup (domains_hash, domain) != NULL((void*)0)); |
85 | } |
86 | |
87 | static void |
88 | ensure_ring (void) |
89 | { |
90 | if (ring_buffer) |
91 | return; |
92 | |
93 | ring_buffer = g_new0 (char *, ring_buffer_max_lines)((char * *) g_malloc0_n ((ring_buffer_max_lines), sizeof (char *))); |
94 | ring_buffer_next_index = 0; |
95 | ring_buffer_num_lines = 0; |
96 | } |
97 | |
98 | static void |
99 | add_to_ring (char *str) |
100 | { |
101 | ensure_ring (); |
102 | |
103 | g_assert (str != NULL)do { if (str != ((void*)0)) ; else g_assertion_message_expr ( ((gchar*) 0), "baul-debug-log.c", 103, ((const char*) (__func__ )), "str != NULL"); } while (0); |
104 | |
105 | if (ring_buffer_num_lines == ring_buffer_max_lines) |
106 | { |
107 | /* We have an overlap, and the ring_buffer_next_index points to |
108 | * the "first" item. Free it to make room for the new item. |
109 | */ |
110 | |
111 | g_assert (ring_buffer[ring_buffer_next_index] != NULL)do { if (ring_buffer[ring_buffer_next_index] != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c" , 111, ((const char*) (__func__)), "ring_buffer[ring_buffer_next_index] != NULL" ); } while (0); |
112 | g_free (ring_buffer[ring_buffer_next_index]); |
113 | } |
114 | else |
115 | ring_buffer_num_lines++; |
116 | |
117 | g_assert (ring_buffer_num_lines <= ring_buffer_max_lines)do { if (ring_buffer_num_lines <= ring_buffer_max_lines) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c" , 117, ((const char*) (__func__)), "ring_buffer_num_lines <= ring_buffer_max_lines" ); } while (0); |
118 | |
119 | ring_buffer[ring_buffer_next_index] = str; |
120 | |
121 | ring_buffer_next_index++; |
122 | if (ring_buffer_next_index == ring_buffer_max_lines) |
123 | { |
124 | ring_buffer_next_index = 0; |
125 | g_assert (ring_buffer_num_lines == ring_buffer_max_lines)do { if (ring_buffer_num_lines == ring_buffer_max_lines) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 125 , ((const char*) (__func__)), "ring_buffer_num_lines == ring_buffer_max_lines" ); } while (0); |
126 | } |
127 | } |
128 | |
129 | static void |
130 | add_to_milestones (const char *str) |
131 | { |
132 | char *str_copy; |
133 | |
134 | str_copy = g_strdup (str)g_strdup_inline (str); |
135 | |
136 | if (milestones_tail) |
137 | { |
138 | milestones_tail = g_slist_append (milestones_tail, str_copy); |
139 | milestones_tail = milestones_tail->next; |
140 | } |
141 | else |
142 | { |
143 | milestones_head = milestones_tail = g_slist_append (NULL((void*)0), str_copy); |
144 | } |
145 | |
146 | g_assert (milestones_head != NULL && milestones_tail != NULL)do { if (milestones_head != ((void*)0) && milestones_tail != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0) , "baul-debug-log.c", 146, ((const char*) (__func__)), "milestones_head != NULL && milestones_tail != NULL" ); } while (0); |
147 | } |
148 | |
149 | void |
150 | baul_debug_logv (gboolean is_milestone, const char *domain, const GList *uris, const char *format, va_list args) |
151 | { |
152 | char *str; |
153 | char *debug_str; |
154 | struct timeval tv; |
155 | struct tm tm; |
156 | |
157 | lock (); |
158 | |
159 | if (!(is_milestone || is_domain_enabled (domain))) |
160 | goto out; |
161 | |
162 | str = g_strdup_vprintf (format, args); |
163 | gettimeofday (&tv, NULL((void*)0)); |
164 | |
165 | tm = *localtime (&tv.tv_sec); |
166 | |
167 | debug_str = g_strdup_printf ("%p %04d/%02d/%02d %02d:%02d:%02d.%04d (%s): %s", |
168 | g_thread_self (), |
169 | tm.tm_year + 1900, |
170 | tm.tm_mon + 1, |
171 | tm.tm_mday, |
172 | tm.tm_hour, |
173 | tm.tm_min, |
174 | tm.tm_sec, |
175 | (int) (tv.tv_usec / 100), |
176 | domain, |
177 | str); |
178 | g_free (str); |
179 | |
180 | if (uris) |
181 | { |
182 | int debug_str_len; |
183 | int uris_len; |
184 | const GList *l; |
185 | char *new_str; |
186 | char *p; |
187 | int count; |
188 | |
189 | uris_len = 0; |
190 | |
191 | count = 0; |
192 | for (l = uris; l; l = l->next) |
193 | { |
194 | const char *uri; |
195 | |
196 | uri = l->data; |
197 | uris_len += strlen (uri) + 2; /* plus 2 for a tab and the newline */ |
198 | |
199 | if (count++ > MAX_URI_COUNT20) |
200 | { |
201 | uris_len += 4; /* "...\n" */ |
202 | break; |
203 | } |
204 | |
205 | } |
206 | |
207 | debug_str_len = strlen (debug_str); |
208 | new_str = g_new (char, debug_str_len + 1 + uris_len + 1)((char *) g_malloc_n ((debug_str_len + 1 + uris_len + 1), sizeof (char))); /* plus 1 for newline & zero */ |
209 | |
210 | p = g_stpcpy (new_str, debug_str); |
211 | *p++ = '\n'; |
212 | |
213 | count = 0; |
214 | for (l = uris; l; l = l->next) |
215 | { |
216 | const char *uri; |
217 | |
218 | uri = l->data; |
219 | |
220 | *p++ = '\t'; |
221 | |
222 | p = g_stpcpy (p, uri); |
223 | |
224 | if (l->next) |
225 | *p++ = '\n'; |
226 | |
227 | if (count++ > MAX_URI_COUNT20) |
228 | { |
229 | p = g_stpcpy (p, "...\n"); |
Value stored to 'p' is never read | |
230 | break; |
231 | } |
232 | } |
233 | |
234 | g_free (debug_str); |
235 | debug_str = new_str; |
236 | } |
237 | |
238 | add_to_ring (debug_str); |
239 | if (is_milestone) |
240 | add_to_milestones (debug_str); |
241 | |
242 | out: |
243 | unlock (); |
244 | } |
245 | |
246 | void |
247 | baul_debug_log_with_uri_list (gboolean is_milestone, const char *domain, const GList *uris, |
248 | const char *format, ...) |
249 | { |
250 | va_list args; |
251 | |
252 | va_start (args, format)__builtin_va_start(args, format); |
253 | baul_debug_logv (is_milestone, domain, uris, format, args); |
254 | va_end (args)__builtin_va_end(args); |
255 | } |
256 | |
257 | void |
258 | baul_debug_log_with_file_list (gboolean is_milestone, const char *domain, GList *files, |
259 | const char *format, ...) |
260 | { |
261 | va_list args; |
262 | GList *uris; |
263 | GList *l; |
264 | int count; |
265 | |
266 | /* Avoid conversion if debugging disabled */ |
267 | if (!(is_milestone || |
268 | baul_debug_log_is_domain_enabled (domain))) |
269 | { |
270 | return; |
271 | } |
272 | |
273 | uris = NULL((void*)0); |
274 | |
275 | count = 0; |
276 | for (l = files; l; l = l->next) |
277 | { |
278 | BaulFile *file; |
279 | char *uri; |
280 | |
281 | file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((l->data)), (baul_file_get_type()))))); |
282 | uri = baul_file_get_uri (file); |
283 | |
284 | if (baul_file_is_gone (file)) |
285 | { |
286 | char *new_uri; |
287 | |
288 | /* Hack: this will create an invalid URI, but it's for |
289 | * display purposes only. |
290 | */ |
291 | new_uri = g_strconcat (uri ? uri : "", " (gone)", NULL((void*)0)); |
292 | g_free (uri); |
293 | uri = new_uri; |
294 | } |
295 | uris = g_list_prepend (uris, uri); |
296 | |
297 | /* Avoid doing to much work, more than MAX_URI_COUNT uris |
298 | won't be shown anyway */ |
299 | if (count++ > MAX_URI_COUNT20 + 1) |
300 | { |
301 | break; |
302 | } |
303 | } |
304 | |
305 | uris = g_list_reverse (uris); |
306 | |
307 | va_start (args, format)__builtin_va_start(args, format); |
308 | baul_debug_logv (is_milestone, domain, uris, format, args); |
309 | va_end (args)__builtin_va_end(args); |
310 | |
311 | g_list_free_full (uris, g_free); |
312 | } |
313 | |
314 | gboolean |
315 | baul_debug_log_load_configuration (const char *filename, GError **error) |
316 | { |
317 | GKeyFile *key_file; |
318 | char **strings; |
319 | gsize num_strings; |
320 | int num; |
321 | GError *my_error; |
322 | |
323 | g_assert (filename != NULL)do { if (filename != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 323, ((const char*) (__func__ )), "filename != NULL"); } while (0); |
324 | g_assert (error == NULL || *error == NULL)do { if (error == ((void*)0) || *error == ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 324, ((const char*) (__func__ )), "error == NULL || *error == NULL"); } while (0); |
325 | |
326 | key_file = g_key_file_new (); |
327 | |
328 | if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error)) |
329 | { |
330 | g_key_file_free (key_file); |
331 | return FALSE(0); |
332 | } |
333 | |
334 | /* Domains */ |
335 | |
336 | my_error = NULL((void*)0); |
337 | strings = g_key_file_get_string_list (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_DOMAINS_KEY"enable domains", &num_strings, &my_error); |
338 | if (my_error) |
339 | g_error_free (my_error); |
340 | else |
341 | { |
342 | int i; |
343 | |
344 | for (i = 0; i < num_strings; i++) |
345 | strings[i] = g_strstrip (strings[i])g_strchomp (g_strchug (strings[i])); |
346 | |
347 | baul_debug_log_enable_domains ((const char **) strings, num_strings); |
348 | g_strfreev (strings); |
349 | } |
350 | |
351 | /* Number of lines */ |
352 | |
353 | my_error = NULL((void*)0); |
354 | num = g_key_file_get_integer (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_MAX_LINES_KEY"max lines", &my_error); |
355 | if (my_error) |
356 | g_error_free (my_error); |
357 | else |
358 | baul_debug_log_set_max_lines (num); |
359 | |
360 | g_key_file_free (key_file); |
361 | return TRUE(!(0)); |
362 | } |
363 | |
364 | void |
365 | baul_debug_log_enable_domains (const char **domains, int n_domains) |
366 | { |
367 | int i; |
368 | |
369 | g_assert (domains != NULL)do { if (domains != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 369, ((const char*) (__func__ )), "domains != NULL"); } while (0); |
370 | g_assert (n_domains >= 0)do { if (n_domains >= 0) ; else g_assertion_message_expr ( ((gchar*) 0), "baul-debug-log.c", 370, ((const char*) (__func__ )), "n_domains >= 0"); } while (0); |
371 | |
372 | lock (); |
373 | |
374 | if (!domains_hash) |
375 | domains_hash = g_hash_table_new (g_str_hash, g_str_equal); |
376 | |
377 | for (i = 0; i < n_domains; i++) |
378 | { |
379 | g_assert (domains[i] != NULL)do { if (domains[i] != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 379, ((const char*) (__func__ )), "domains[i] != NULL"); } while (0); |
380 | |
381 | if (strcmp (domains[i], BAUL_DEBUG_LOG_DOMAIN_USER"USER") == 0) |
382 | continue; /* user actions are always enabled */ |
383 | |
384 | if (g_hash_table_lookup (domains_hash, domains[i]) == NULL((void*)0)) |
385 | { |
386 | char *domain; |
387 | |
388 | domain = g_strdup (domains[i])g_strdup_inline (domains[i]); |
389 | g_hash_table_insert (domains_hash, domain, domain); |
390 | } |
391 | } |
392 | |
393 | unlock (); |
394 | } |
395 | |
396 | void |
397 | baul_debug_log_disable_domains (const char **domains, int n_domains) |
398 | { |
399 | g_assert (domains != NULL)do { if (domains != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 399, ((const char*) (__func__ )), "domains != NULL"); } while (0); |
400 | g_assert (n_domains >= 0)do { if (n_domains >= 0) ; else g_assertion_message_expr ( ((gchar*) 0), "baul-debug-log.c", 400, ((const char*) (__func__ )), "n_domains >= 0"); } while (0); |
401 | |
402 | lock (); |
403 | |
404 | if (domains_hash) |
405 | { |
406 | int i; |
407 | |
408 | for (i = 0; i < n_domains; i++) |
409 | { |
410 | char *domain; |
411 | |
412 | g_assert (domains[i] != NULL)do { if (domains[i] != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 412, ((const char*) (__func__ )), "domains[i] != NULL"); } while (0); |
413 | |
414 | if (strcmp (domains[i], BAUL_DEBUG_LOG_DOMAIN_USER"USER") == 0) |
415 | continue; /* user actions are always enabled */ |
416 | |
417 | domain = g_hash_table_lookup (domains_hash, domains[i]); |
418 | if (domain) |
419 | { |
420 | g_hash_table_remove (domains_hash, domain); |
421 | g_free (domain); |
422 | } |
423 | } |
424 | } /* else, there is nothing to disable */ |
425 | |
426 | unlock (); |
427 | } |
428 | |
429 | gboolean |
430 | baul_debug_log_is_domain_enabled (const char *domain) |
431 | { |
432 | gboolean retval; |
433 | |
434 | g_assert (domain != NULL)do { if (domain != ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 434, ((const char*) (__func__ )), "domain != NULL"); } while (0); |
435 | |
436 | lock (); |
437 | retval = is_domain_enabled (domain); |
438 | unlock (); |
439 | |
440 | return retval; |
441 | } |
442 | |
443 | struct domains_dump_closure |
444 | { |
445 | char **domains; |
446 | int num_domains; |
447 | }; |
448 | |
449 | static void |
450 | domains_foreach_dump_cb (gpointer key, |
451 | gpointer value G_GNUC_UNUSED__attribute__ ((__unused__)), |
452 | gpointer data) |
453 | { |
454 | struct domains_dump_closure *closure; |
455 | char *domain; |
456 | |
457 | closure = data; |
458 | domain = key; |
459 | |
460 | closure->domains[closure->num_domains] = domain; |
461 | closure->num_domains++; |
462 | } |
463 | |
464 | static GKeyFile * |
465 | make_key_file_from_configuration (void) |
466 | { |
467 | GKeyFile *key_file; |
468 | struct domains_dump_closure closure; |
469 | |
470 | key_file = g_key_file_new (); |
471 | |
472 | /* domains */ |
473 | |
474 | if (domains_hash) |
475 | { |
476 | int num_domains; |
477 | |
478 | num_domains = g_hash_table_size (domains_hash); |
479 | if (num_domains != 0) |
480 | { |
481 | closure.domains = g_new (char *, num_domains)((char * *) g_malloc_n ((num_domains), sizeof (char *))); |
482 | closure.num_domains = 0; |
483 | |
484 | g_hash_table_foreach (domains_hash, domains_foreach_dump_cb, &closure); |
485 | g_assert (num_domains == closure.num_domains)do { if (num_domains == closure.num_domains) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 485, ((const char*) (__func__ )), "num_domains == closure.num_domains"); } while (0); |
486 | |
487 | g_key_file_set_string_list (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_DOMAINS_KEY"enable domains", |
488 | (const gchar * const *) closure.domains, closure.num_domains); |
489 | g_free (closure.domains); |
490 | } |
491 | } |
492 | |
493 | /* max lines */ |
494 | |
495 | g_key_file_set_integer (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_MAX_LINES_KEY"max lines", ring_buffer_max_lines); |
496 | |
497 | return key_file; |
498 | } |
499 | |
500 | static gboolean |
501 | write_string (const char *filename, FILE *file, const char *str, GError **error) |
502 | { |
503 | if (fputs (str, file) == EOF(-1)) |
504 | { |
505 | int saved_errno; |
506 | |
507 | saved_errno = errno(*__errno_location ()); |
508 | g_set_error (error, |
509 | G_FILE_ERRORg_file_error_quark (), |
510 | g_file_error_from_errno (saved_errno), |
511 | "error when writing to log file %s", filename); |
512 | |
513 | return FALSE(0); |
514 | } |
515 | |
516 | return TRUE(!(0)); |
517 | } |
518 | |
519 | static gboolean |
520 | dump_configuration (const char *filename, FILE *file, GError **error) |
521 | { |
522 | GKeyFile *key_file; |
523 | char *data; |
524 | gsize length; |
525 | gboolean success; |
526 | |
527 | if (!write_string (filename, file, |
528 | "\n\n" |
529 | "This configuration for the debug log can be re-created\n" |
530 | "by putting the following in ~/baul-debug-log.conf\n" |
531 | "(use ';' to separate domain names):\n\n", |
532 | error)) |
533 | { |
534 | return FALSE(0); |
535 | } |
536 | |
537 | success = FALSE(0); |
538 | |
539 | key_file = make_key_file_from_configuration (); |
540 | |
541 | data = g_key_file_to_data (key_file, &length, error); |
542 | if (!data) |
543 | goto out; |
544 | |
545 | if (!write_string (filename, file, data, error)) |
546 | { |
547 | goto out; |
548 | } |
549 | |
550 | success = TRUE(!(0)); |
551 | out: |
552 | g_key_file_free (key_file); |
553 | return success; |
554 | } |
555 | |
556 | static gboolean |
557 | dump_milestones (const char *filename, FILE *file, GError **error) |
558 | { |
559 | GSList *l; |
560 | |
561 | if (!write_string (filename, file, "===== BEGIN MILESTONES =====\n", error)) |
562 | return FALSE(0); |
563 | |
564 | for (l = milestones_head; l; l = l->next) |
565 | { |
566 | const char *str; |
567 | |
568 | str = l->data; |
569 | if (!(write_string (filename, file, str, error) |
570 | && write_string (filename, file, "\n", error))) |
571 | return FALSE(0); |
572 | } |
573 | |
574 | if (!write_string (filename, file, "===== END MILESTONES =====\n", error)) |
575 | return FALSE(0); |
576 | |
577 | return TRUE(!(0)); |
578 | } |
579 | |
580 | static gboolean |
581 | dump_ring_buffer (const char *filename, FILE *file, GError **error) |
582 | { |
583 | int start_index; |
584 | int i; |
585 | |
586 | if (!write_string (filename, file, "===== BEGIN RING BUFFER =====\n", error)) |
587 | return FALSE(0); |
588 | |
589 | if (ring_buffer_num_lines == ring_buffer_max_lines) |
590 | start_index = ring_buffer_next_index; |
591 | else |
592 | start_index = 0; |
593 | |
594 | for (i = 0; i < ring_buffer_num_lines; i++) |
595 | { |
596 | int idx; |
597 | |
598 | idx = (start_index + i) % ring_buffer_max_lines; |
599 | |
600 | if (!(write_string (filename, file, ring_buffer[idx], error) |
601 | && write_string (filename, file, "\n", error))) |
602 | { |
603 | return FALSE(0); |
604 | } |
605 | } |
606 | |
607 | if (!write_string (filename, file, "===== END RING BUFFER =====\n", error)) |
608 | return FALSE(0); |
609 | |
610 | return TRUE(!(0)); |
611 | } |
612 | |
613 | gboolean |
614 | baul_debug_log_dump (const char *filename, GError **error) |
615 | { |
616 | FILE *file; |
617 | gboolean success; |
618 | |
619 | g_assert (error == NULL || *error == NULL)do { if (error == ((void*)0) || *error == ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c", 619, ((const char*) (__func__ )), "error == NULL || *error == NULL"); } while (0); |
620 | |
621 | lock (); |
622 | |
623 | success = FALSE(0); |
624 | |
625 | file = fopen (filename, "w"); |
626 | if (!file) |
627 | { |
628 | int saved_errno; |
629 | |
630 | saved_errno = errno(*__errno_location ()); |
631 | g_set_error (error, |
632 | G_FILE_ERRORg_file_error_quark (), |
633 | g_file_error_from_errno (saved_errno), |
634 | "could not open log file %s", filename); |
635 | goto out; |
636 | } |
637 | |
638 | if (!(dump_milestones (filename, file, error) |
639 | && dump_ring_buffer (filename, file, error) |
640 | && dump_configuration (filename, file, error))) |
641 | { |
642 | goto do_close; |
643 | } |
644 | |
645 | success = TRUE(!(0)); |
646 | |
647 | do_close: |
648 | |
649 | if (fclose (file) != 0) |
650 | { |
651 | int saved_errno; |
652 | |
653 | saved_errno = errno(*__errno_location ()); |
654 | |
655 | if (error && *error) |
656 | { |
657 | g_error_free (*error); |
658 | *error = NULL((void*)0); |
659 | } |
660 | |
661 | g_set_error (error, |
662 | G_FILE_ERRORg_file_error_quark (), |
663 | g_file_error_from_errno (saved_errno), |
664 | "error when closing log file %s", filename); |
665 | success = FALSE(0); |
666 | } |
667 | |
668 | out: |
669 | |
670 | unlock (); |
671 | return success; |
672 | } |
673 | |
674 | void |
675 | baul_debug_log_set_max_lines (int num_lines) |
676 | { |
677 | char **new_buffer; |
678 | int lines_to_copy; |
679 | |
680 | g_assert (num_lines > 0)do { if (num_lines > 0) ; else g_assertion_message_expr (( (gchar*) 0), "baul-debug-log.c", 680, ((const char*) (__func__ )), "num_lines > 0"); } while (0); |
681 | |
682 | lock (); |
683 | |
684 | if (num_lines == ring_buffer_max_lines) |
685 | goto out; |
686 | |
687 | new_buffer = g_new0 (char *, num_lines)((char * *) g_malloc0_n ((num_lines), sizeof (char *))); |
688 | |
689 | lines_to_copy = MIN (num_lines, ring_buffer_num_lines)(((num_lines) < (ring_buffer_num_lines)) ? (num_lines) : ( ring_buffer_num_lines)); |
690 | |
691 | if (ring_buffer) |
692 | { |
693 | int start_index; |
694 | int i; |
695 | |
696 | if (ring_buffer_num_lines == ring_buffer_max_lines) |
697 | start_index = (ring_buffer_next_index + ring_buffer_max_lines - lines_to_copy) % ring_buffer_max_lines; |
698 | else |
699 | start_index = ring_buffer_num_lines - lines_to_copy; |
700 | |
701 | g_assert (start_index >= 0 && start_index < ring_buffer_max_lines)do { if (start_index >= 0 && start_index < ring_buffer_max_lines ) ; else g_assertion_message_expr (((gchar*) 0), "baul-debug-log.c" , 701, ((const char*) (__func__)), "start_index >= 0 && start_index < ring_buffer_max_lines" ); } while (0); |
702 | |
703 | for (i = 0; i < lines_to_copy; i++) |
704 | { |
705 | int idx; |
706 | |
707 | idx = (start_index + i) % ring_buffer_max_lines; |
708 | |
709 | new_buffer[i] = ring_buffer[idx]; |
710 | ring_buffer[idx] = NULL((void*)0); |
711 | } |
712 | |
713 | for (i = 0; i < ring_buffer_max_lines; i++) |
714 | g_free (ring_buffer[i]); |
715 | |
716 | g_free (ring_buffer); |
717 | } |
718 | |
719 | ring_buffer = new_buffer; |
720 | ring_buffer_next_index = lines_to_copy; |
721 | ring_buffer_num_lines = lines_to_copy; |
722 | ring_buffer_max_lines = num_lines; |
723 | |
724 | out: |
725 | |
726 | unlock (); |
727 | } |
728 | |
729 | int |
730 | baul_debug_log_get_max_lines (void) |
731 | { |
732 | int retval; |
733 | |
734 | lock (); |
735 | retval = ring_buffer_max_lines; |
736 | unlock (); |
737 | |
738 | return retval; |
739 | } |
740 | |
741 | void |
742 | baul_debug_log_clear (void) |
743 | { |
744 | int i; |
745 | |
746 | lock (); |
747 | |
748 | if (!ring_buffer) |
749 | goto out; |
750 | |
751 | for (i = 0; i < ring_buffer_max_lines; i++) |
752 | { |
753 | g_free (ring_buffer[i]); |
754 | ring_buffer[i] = NULL((void*)0); |
755 | } |
756 | |
757 | ring_buffer_next_index = 0; |
758 | ring_buffer_num_lines = 0; |
759 | |
760 | out: |
761 | unlock (); |
762 | } |