QOF  0.7.5
qoflog.c
1 /* **************************************************************************
2  * qoflog.c
3  *
4  * Mon Nov 21 14:41:59 2005
5  * Author: Rob Clark (rclark@cs.hmc.edu)
6  * Copyright (C) 1997-2003 Linas Vepstas <linas@linas.org>
7  * Copyright 2005-2008 Neil Williams
8  * linux@codehelp.co.uk
9  *************************************************************************** */
10 /*
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24  * 02110-1301, USA
25  */
26 
27 #include "config.h"
28 
29 #include <glib.h>
30 #include <unistd.h>
31 #include "qof.h"
32 
33 #define QOF_LOG_MAX_CHARS 50
34 #define QOF_LOG_INDENT_WIDTH 4
35 
36 static FILE *fout = NULL;
37 static gchar *filename = NULL;
38 static gchar *function_buffer = NULL;
39 static const gint MAX_TRACE_FILENAME = 100;
40 static GHashTable *log_table = NULL;
41 static gint qof_log_num_spaces = 0;
42 
43 /* uses the enum_as_string macro.
44 Lookups are done on the string. */
45 AS_STRING_FUNC (QofLogLevel, LOG_LEVEL_LIST)
46 FROM_STRING_FUNC (QofLogLevel, LOG_LEVEL_LIST)
47 
48 void qof_log_add_indent (void)
49 {
50  qof_log_num_spaces += QOF_LOG_INDENT_WIDTH;
51 }
52 
53 gint
54 qof_log_get_indent (void)
55 {
56  return qof_log_num_spaces;
57 }
58 
59 void
61 {
62  qof_log_num_spaces = (qof_log_num_spaces < QOF_LOG_INDENT_WIDTH) ?
63  0 : qof_log_num_spaces - QOF_LOG_INDENT_WIDTH;
64 }
65 
66 static void
67 fh_printer (const gchar * log_domain __attribute__ ((unused)),
68  GLogLevelFlags log_level __attribute__ ((unused)),
69  const gchar * message, gpointer user_data)
70 {
71  FILE *fh = user_data;
72  fprintf (fh, "%*s%s\n", qof_log_num_spaces, "", message);
73  fflush (fh);
74 }
75 
76 void
77 qof_log_init (void)
78 {
79  if (!fout) /* allow qof_log_set_file */
80  {
81  fout = fopen ("/tmp/qof.trace", "w");
82  }
83 
84  if (!fout && (filename = (gchar *) g_malloc (MAX_TRACE_FILENAME)))
85  {
86  snprintf (filename, MAX_TRACE_FILENAME - 1, "/tmp/qof.trace.%d",
87  getpid ());
88  fout = fopen (filename, "w");
89  g_free (filename);
90  }
91 
92  if (!fout)
93  fout = stderr;
94 
95  g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, fh_printer, fout);
96 }
97 
98 void
99 qof_log_set_level (QofLogModule log_module, QofLogLevel level)
100 {
101  gchar *level_string;
102 
103  if (!log_module || level == 0)
104  {
105  return;
106  }
107  level_string = g_strdup (QofLogLevelasString (level));
108  if (!log_table)
109  {
110  log_table = g_hash_table_new (g_str_hash, g_str_equal);
111  }
112  g_hash_table_insert (log_table, (gpointer) log_module, level_string);
113 }
114 
115 static void
116 log_module_foreach (gpointer key,
117  gpointer value __attribute__ ((unused)), gpointer data)
118 {
119  g_hash_table_insert (log_table, key, data);
120 }
121 
122 void
124 {
125  gchar *level_string;
126 
127  if (!log_table || level == 0)
128  {
129  return;
130  }
131  level_string = g_strdup (QofLogLevelasString (level));
132  g_hash_table_foreach (log_table, log_module_foreach, level_string);
133 }
134 
135 void
136 qof_log_set_file (FILE * outfile)
137 {
138  if (!outfile)
139  {
140  fout = stderr;
141  return;
142  }
143  fout = outfile;
144 }
145 
146 void
147 qof_log_init_filename (const gchar * logfilename)
148 {
149  if (!logfilename)
150  {
151  fout = stderr;
152  }
153  else
154  {
155  filename = g_strdup (logfilename);
156  fout = fopen (filename, "w");
157  }
158  qof_log_init ();
159 }
160 
161 void
162 qof_log_shutdown (void)
163 {
164  if (fout && fout != stderr)
165  {
166  fclose (fout);
167  }
168  if (filename)
169  {
170  g_free (filename);
171  }
172  if (function_buffer)
173  {
174  g_free (function_buffer);
175  }
176  g_hash_table_destroy (log_table);
177 }
178 
179 const gchar *
180 qof_log_prettify (const gchar *name)
181 {
182  gchar *p, *buffer;
183  gint length;
184 
185  if (!name)
186  {
187  return "";
188  }
189  buffer = g_strndup (name, QOF_LOG_MAX_CHARS - 1);
190  length = strlen (buffer);
191  p = g_strstr_len (buffer, length, "(");
192  if (p)
193  {
194  *(p + 1) = ')';
195  *(p + 2) = 0x0;
196  }
197  else
198  {
199  strcpy (&buffer[QOF_LOG_MAX_CHARS - 4], "...()");
200  }
201  function_buffer = g_strdup (buffer);
202  g_free (buffer);
203  return function_buffer;
204 }
205 
206 gboolean
207 qof_log_check (QofLogModule log_module, QofLogLevel log_level)
208 {
209  gchar *log_string;
210  /* Any positive log_level less than this will be logged. */
211  QofLogLevel maximum;
212 
213  log_string = NULL;
214  if (log_level > QOF_LOG_TRACE)
215  log_level = QOF_LOG_TRACE;
216  if (!log_table || log_module == NULL)
217  {
218  return FALSE;
219  }
220  log_string = (gchar *) g_hash_table_lookup (log_table, log_module);
221  /* if log_module not found, do not log. */
222  if (!log_string)
223  {
224  return FALSE;
225  }
226  maximum = QofLogLevelfromString (log_string);
227  if (log_level <= maximum)
228  {
229  return TRUE;
230  }
231  return FALSE;
232 }
233 
234 void
236 {
237  qof_log_set_level (QOF_MOD_BACKEND, log_level);
238  qof_log_set_level (QOF_MOD_CLASS, log_level);
239  qof_log_set_level (QOF_MOD_ENGINE, log_level);
240  qof_log_set_level (QOF_MOD_OBJECT, log_level);
241  qof_log_set_level (QOF_MOD_KVP, log_level);
242  qof_log_set_level (QOF_MOD_MERGE, log_level);
243  qof_log_set_level (QOF_MOD_QUERY, log_level);
244  qof_log_set_level (QOF_MOD_SESSION, log_level);
245  qof_log_set_level (QOF_MOD_CHOICE, log_level);
246  qof_log_set_level (QOF_MOD_UTIL, log_level);
247  qof_log_set_level (QOF_MOD_TIME, log_level);
248  qof_log_set_level (QOF_MOD_DATE, log_level);
249  qof_log_set_level (QOF_MOD_UNDO, log_level);
250  qof_log_set_level (QOF_MOD_ERROR, log_level);
251  qof_log_set_level (QOF_MOD_QSF, log_level);
252  qof_log_set_level (QOF_MOD_SQLITE, log_level);
253  qof_log_set_level (QOF_MOD_GDA, log_level);
254 }
255 
256 struct hash_s
257 {
258  QofLogCB cb;
259  gpointer data;
260 };
261 
262 static void
263 hash_cb (gpointer key, gpointer value, gpointer data)
264 {
265  struct hash_s *qiter;
266 
267  qiter = (struct hash_s *) data;
268  if (!qiter)
269  {
270  return;
271  }
272  (qiter->cb) (key, value, qiter->data);
273 }
274 
275 void
276 qof_log_module_foreach (QofLogCB cb, gpointer data)
277 {
278  struct hash_s qiter;
279 
280  if (!cb)
281  {
282  return;
283  }
284  qiter.cb = cb;
285  qiter.data = data;
286  g_hash_table_foreach (log_table, hash_cb, (gpointer) &qiter);
287 }
288 
289 gint
291 {
292  if (!log_table)
293  {
294  return 0;
295  }
296  return g_hash_table_size (log_table);
297 }
298 
299 /* ************************ END OF FILE **************************** */