00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "config.h"
00028
00029 #include <glib.h>
00030 #ifdef HAVE_UNISTD_H
00031 # include <unistd.h>
00032 #else
00033
00034 #endif
00035 #include <stdarg.h>
00036 #include <string.h>
00037 #include <sys/time.h>
00038 #include "qof.h"
00039 #include "gnc-trace.h"
00040
00041 static FILE *fout = NULL;
00042 static gchar* filename = NULL;
00043
00044 static const int MAX_TRACE_FILENAME = 100;
00045 static GHashTable *log_table = NULL;
00046
00047
00048
00049 AS_STRING_FUNC(gncLogLevel, LOG_LEVEL_LIST)
00050
00051 FROM_STRING_FUNC(gncLogLevel, LOG_LEVEL_LIST)
00052
00053
00054
00055
00056
00057 gint __attribute__ ((unused)) gnc_trace_num_spaces = 0;
00058
00059 static void
00060 fh_printer (const gchar *log_domain,
00061 GLogLevelFlags log_level,
00062 const gchar *message,
00063 gpointer user_data)
00064 {
00065 extern gint gnc_trace_num_spaces;
00066 FILE *fh = user_data;
00067 fprintf (fh, "%*s%s\n", gnc_trace_num_spaces, "", message);
00068 fflush(fh);
00069 }
00070
00071 void
00072 gnc_log_init (void)
00073 {
00074 if(!fout)
00075 {
00076 fout = fopen ("/tmp/qof.trace", "w");
00077 }
00078
00079 if(!fout && (filename = (char *)g_malloc(MAX_TRACE_FILENAME))) {
00080 snprintf(filename, MAX_TRACE_FILENAME-1, "/tmp/qof.trace.%d",
00081 getpid());
00082 fout = fopen (filename, "w");
00083 g_free(filename);
00084 }
00085
00086 if(!fout)
00087 fout = stderr;
00088
00089 g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, fh_printer, fout);
00090 }
00091
00092
00093 void
00094 gnc_set_log_level(QofLogModule log_module, gncLogLevel level)
00095 {
00096 gchar* level_string;
00097
00098 if(!log_module || level == 0) { return; }
00099 level_string = g_strdup(gncLogLevelasString(level));
00100 if(!log_table)
00101 {
00102 log_table = g_hash_table_new(g_str_hash, g_str_equal);
00103 }
00104 g_hash_table_insert(log_table, (gpointer)log_module, level_string);
00105 }
00106
00107 static void
00108 log_module_foreach(gpointer key, gpointer value, gpointer data)
00109 {
00110 g_hash_table_insert(log_table, key, data);
00111 }
00112
00113
00114 void
00115 gnc_set_log_level_global(gncLogLevel level)
00116 {
00117 gchar* level_string;
00118
00119 if(!log_table || level == 0) { return; }
00120 level_string = g_strdup(gncLogLevelasString(level));
00121 g_hash_table_foreach(log_table, log_module_foreach, level_string);
00122 }
00123
00124 void
00125 gnc_set_logfile (FILE *outfile)
00126 {
00127 if(!outfile) { fout = stderr; return; }
00128 fout = outfile;
00129 }
00130
00131 void
00132 qof_log_init_filename (const gchar* logfilename)
00133 {
00134 if(!logfilename)
00135 {
00136 fout = stderr;
00137 }
00138 else
00139 {
00140 filename = g_strdup(logfilename);
00141 fout = fopen(filename, "w");
00142 }
00143 gnc_log_init();
00144 }
00145
00146 void
00147 qof_log_shutdown (void)
00148 {
00149 if(fout && fout != stderr) { fclose(fout); }
00150 if(filename) { g_free(filename); }
00151 g_hash_table_destroy(log_table);
00152 }
00153
00154 #define MAX_CHARS 50
00155
00156
00157
00158
00159
00160 const char *
00161 gnc_log_prettify (const char *name)
00162 {
00163 static char bf[128];
00164 char *p;
00165
00166 if (!name)
00167 return "";
00168
00169 strncpy (bf, name, MAX_CHARS-1); bf[MAX_CHARS-2] = 0;
00170 p = strchr (bf, '(');
00171
00172 if (p)
00173 {
00174 *(p+1) = ')';
00175 *(p+2) = 0x0;
00176 }
00177 else
00178 strcpy (&bf[MAX_CHARS-4], "...()");
00179
00180 return bf;
00181 }
00182
00183
00184
00185
00186 #define NUM_CLOCKS 10
00187
00188 static
00189 struct timeval gnc_clock[NUM_CLOCKS] = {
00190 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
00191 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
00192 };
00193
00194 static
00195 struct timeval gnc_clock_total[NUM_CLOCKS] = {
00196 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
00197 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
00198 };
00199
00200 void
00201 gnc_start_clock (int clockno, QofLogModule log_module, gncLogLevel log_level,
00202 const char *function_name, const char *format, ...)
00203 {
00204 struct timezone tz;
00205 va_list ap;
00206
00207 if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
00208 gettimeofday (&gnc_clock[clockno], &tz);
00209
00210 if (!fout) gnc_log_init();
00211
00212 fprintf (fout, "Clock %d Start: %s: ",
00213 clockno, gnc_log_prettify (function_name));
00214
00215 va_start (ap, format);
00216
00217 vfprintf (fout, format, ap);
00218
00219 va_end (ap);
00220
00221 fprintf (fout, "\n");
00222 fflush (fout);
00223 }
00224
00225 void
00226 gnc_report_clock (int clockno, QofLogModule log_module, gncLogLevel log_level,
00227 const char *function_name, const char *format, ...)
00228 {
00229 struct timezone tz;
00230 struct timeval now;
00231 va_list ap;
00232
00233 if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
00234 gettimeofday (&now, &tz);
00235
00236
00237 if (now.tv_usec < gnc_clock[clockno].tv_usec)
00238 {
00239 now.tv_sec --;
00240 now.tv_usec += 1000000;
00241 }
00242 now.tv_sec -= gnc_clock[clockno].tv_sec;
00243 now.tv_usec -= gnc_clock[clockno].tv_usec;
00244
00245 gnc_clock_total[clockno].tv_sec += now.tv_sec;
00246 gnc_clock_total[clockno].tv_usec += now.tv_usec;
00247
00248 if (!fout) gnc_log_init();
00249
00250 fprintf (fout, "Clock %d Elapsed: %ld.%06lds %s: ",
00251 clockno, (long int) now.tv_sec, (long int) now.tv_usec,
00252 gnc_log_prettify (function_name));
00253
00254 va_start (ap, format);
00255
00256 vfprintf (fout, format, ap);
00257
00258 va_end (ap);
00259
00260 fprintf (fout, "\n");
00261 fflush (fout);
00262 }
00263
00264 void
00265 gnc_report_clock_total (int clockno,
00266 QofLogModule log_module, gncLogLevel log_level,
00267 const char *function_name, const char *format, ...)
00268 {
00269 va_list ap;
00270
00271 if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
00272
00273
00274 while (gnc_clock_total[clockno].tv_usec >= 1000000)
00275 {
00276 gnc_clock_total[clockno].tv_sec ++;
00277 gnc_clock_total[clockno].tv_usec -= 1000000;
00278 }
00279
00280 if (!fout) gnc_log_init();
00281
00282 fprintf (fout, "Clock %d Total Elapsed: %ld.%06lds %s: ",
00283 clockno,
00284 (long int) gnc_clock_total[clockno].tv_sec,
00285 (long int) gnc_clock_total[clockno].tv_usec,
00286 gnc_log_prettify (function_name));
00287
00288 va_start (ap, format);
00289
00290 vfprintf (fout, format, ap);
00291
00292 va_end (ap);
00293
00294 fprintf (fout, "\n");
00295 fflush (fout);
00296 }
00297
00298 gboolean
00299 gnc_should_log(QofLogModule log_module, gncLogLevel log_level)
00300 {
00301 gchar* log_string;
00302 gncLogLevel maximum;
00303
00304 log_string = NULL;
00305 if(!log_table || log_module == NULL || log_level == 0) { return FALSE; }
00306 log_string = (gchar*)g_hash_table_lookup(log_table, log_module);
00307
00308 if(!log_string) { return FALSE; }
00309 maximum = gncLogLevelfromString(log_string);
00310 if(log_level <= maximum) { return TRUE; }
00311 return FALSE;
00312 }
00313
00314 void qof_log_set_default(gncLogLevel log_level)
00315 {
00316 gnc_set_log_level(QOF_MOD_BACKEND, log_level);
00317 gnc_set_log_level(QOF_MOD_CLASS, log_level);
00318 gnc_set_log_level(QOF_MOD_ENGINE, log_level);
00319 gnc_set_log_level(QOF_MOD_OBJECT, log_level);
00320 gnc_set_log_level(QOF_MOD_KVP, log_level);
00321 gnc_set_log_level(QOF_MOD_MERGE, log_level);
00322 gnc_set_log_level(QOF_MOD_QUERY, log_level);
00323 gnc_set_log_level(QOF_MOD_SESSION, log_level);
00324 }
00325
00326 struct hash_s
00327 {
00328 QofLogCB cb;
00329 gpointer data;
00330 };
00331
00332 static void hash_cb (gpointer key, gpointer value, gpointer data)
00333 {
00334 struct hash_s *iter;
00335
00336 iter = (struct hash_s*)data;
00337 if(!iter) { return; }
00338 (iter->cb)(key, value, iter->data);
00339 }
00340
00341 void qof_log_module_foreach(QofLogCB cb, gpointer data)
00342 {
00343 struct hash_s iter;
00344
00345 if(!cb) { return; }
00346 iter.cb = cb;
00347 iter.data = data;
00348 g_hash_table_foreach(log_table, hash_cb, (gpointer)&iter);
00349 }
00350
00351 gint qof_log_module_count(void)
00352 {
00353 if(!log_table) { return 0; }
00354 return g_hash_table_size(log_table);
00355 }
00356
00357
00358