summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-10-04 11:09:39 +0000
committerChristian Grothoff <christian@grothoff.org>2011-10-04 11:09:39 +0000
commite305c764722394c18d55e084c7be4b64ff799fa4 (patch)
tree24f9dd8cc6f5393a9084d8149e53af5e850b25e7 /src
parentba59bf06eefaefa447fbca9059adefe9ac0ef167 (diff)
downloadgnunet-e305c764722394c18d55e084c7be4b64ff799fa4.tar.gz
gnunet-e305c764722394c18d55e084c7be4b64ff799fa4.zip
LRN's big logging rewrite (#1805):
* GNUNET_BOTTOM_LOGLEVEL and GNUNET_TOP_LOGLEVEL set global levels Use bottom level to force logging to be more verbose than configured Use top level to force logging to be less verbose than configured Obviously, bottom <= top * GNUNET_LOG sets per-component levels GNUNET_LOG looks like this: name[/bottom[/top]]/... name starts with a non-digit character, must not include '/' bottom and top must consist only of digits, or be empty a description is only used if it matches the component exactly as a special exception (for now) the name '*' matches any component per-component loglevels override global loglevels global levels override whatever is given via arguments or in config Examples: test_client/8/8/ run test_client with DEBUG level (usually leads to a timeout, by the way) */2/2/core/8/8/transport/4/4 run everything with WARNING, core - with DEBUG, transport - with INFO *//1/peerinfo/4/ run everything with top loglevel ERROR, global/configured bottom loglevel, and peerinfo - with bottom loglevel INFO and global/configured top loglevel statistics/ does nothing * Added GNUNET_ERROR_TYPE_UNSPECIFIED enum value, to hold -1. Its corresponding string is NULL. * Changed the logger calls as Grothoff suggested - to use static int to hold the result of runtime evaluation of logability. Logging can be unconditionally disabled in advance by defining GNUNET_LOG_CALL_STATUS to 0, and enabled in advance by defining it to 1. * Added GNUNET_CULL_LOGGING, which, if defined, completely culls out all logging calls at compile time. * Log definition parsing is only done once, results are cached. * Changed definition format, now it looks like this: [component|*|];[file|*|];[function|*|];[from_line[-to_line]];level/[component...] All field separators are mandatory (but some fields could be empty or be '*'). Line definition must be either empty or "number" or "number-number" Level definition must not be empty, and is a string representation of the level (i.e. DEBUG, WARNING, INFO, etc). Definition entry must end with a slash, whether or not there's another entry after it. File name is matched to the end of __FILE__, which allows file name to match not only the base name, but also directories leading to it. * Removed default WARNING loglevel from program and service utility code. Now they default to NULL (UNSPECIFIED) level, which can be overriden by GNUNET_LOG definition, if no level is specified via config or commandline. Log levels from config or commandline are overriden by GNUNET_FORCE_LOG. If GNUNET_*LOG are undefined, and no levels came from config or commandline, logger internally defaults to WARNING level. Add --enable-logging configure option
Diffstat (limited to 'src')
-rw-r--r--src/core/gnunet-service-core.c2
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c6
-rw-r--r--src/dht/test_dht_multipeer.c49
-rw-r--r--src/hello/hello.c2
-rw-r--r--src/include/gnunet_common.h62
-rw-r--r--src/util/common_logging.c387
-rw-r--r--src/util/program.c4
-rw-r--r--src/util/service.c4
8 files changed, 464 insertions, 52 deletions
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 944159b65..989c79f51 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -2079,7 +2079,7 @@ process_encrypted_neighbour_queue (struct Neighbour *n)
2079 GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value); 2079 GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
2080#endif 2080#endif
2081 n->th = 2081 n->th =
2082 GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size, 2082 GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size,
2083 m->priority, 2083 m->priority,
2084 GNUNET_TIME_absolute_get_remaining 2084 GNUNET_TIME_absolute_get_remaining
2085 (m->deadline), 2085 (m->deadline),
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index 69d14ab78..6697d49ea 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -1274,7 +1274,7 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1274 return; 1274 return;
1275 } 1275 }
1276 GNUNET_STATISTICS_update (GDS_stats, 1276 GNUNET_STATISTICS_update (GDS_stats,
1277 gettext_noop ("# Peers selected as targets for PUT requests"), target_count, 1277 gettext_noop ("# PUT messages queued for transmission"), target_count,
1278 GNUNET_NO); 1278 GNUNET_NO);
1279 for (i=0;i<target_count;i++) 1279 for (i=0;i<target_count;i++)
1280 { 1280 {
@@ -1384,7 +1384,7 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1384 return; 1384 return;
1385 } 1385 }
1386 GNUNET_STATISTICS_update (GDS_stats, 1386 GNUNET_STATISTICS_update (GDS_stats,
1387 gettext_noop ("# Peers selected as targets for GET requests"), target_count, 1387 gettext_noop ("# GET messages queued for transmission"), target_count,
1388 GNUNET_NO); 1388 GNUNET_NO);
1389 /* forward request */ 1389 /* forward request */
1390 for (i=0;i<target_count;i++) 1390 for (i=0;i<target_count;i++)
@@ -1483,7 +1483,7 @@ GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
1483 return; 1483 return;
1484 } 1484 }
1485 GNUNET_STATISTICS_update (GDS_stats, 1485 GNUNET_STATISTICS_update (GDS_stats,
1486 gettext_noop ("# REPLIES routed"), 1, 1486 gettext_noop ("# RESULT messages queued for transmission"), 1,
1487 GNUNET_NO); 1487 GNUNET_NO);
1488 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); 1488 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1489 pending->importance = 0; /* FIXME */ 1489 pending->importance = 0; /* FIXME */
diff --git a/src/dht/test_dht_multipeer.c b/src/dht/test_dht_multipeer.c
index 2fc439ecb..eb70424a3 100644
--- a/src/dht/test_dht_multipeer.c
+++ b/src/dht/test_dht_multipeer.c
@@ -250,19 +250,23 @@ struct StatValues
250{ 250{
251 const char *subsystem; 251 const char *subsystem;
252 const char *name; 252 const char *name;
253 unsigned long long total;
253}; 254};
254 255
255/** 256/**
256 * Statistics we print out. 257 * Statistics we print out.
257 */ 258 */
258static struct StatValues stats[] = { 259static struct StatValues stats[] = {
259 {"core", "# bytes decrypted"}, 260 {"core", "# bytes decrypted", 0},
260 {"core", "# bytes encrypted"}, 261 {"core", "# bytes encrypted", 0},
261 {"core", "# discarded CORE_SEND requests"}, 262 {"transport", "# bytes received via TCP", 0},
262 {"core", "# discarded lower priority CORE_SEND requests"}, 263 {"transport", "# bytes transmitted via TCP", 0},
263 {"transport", "# bytes received via TCP"}, 264 {"dht", "# PUT messages queued for transmission"},
264 {"transport", "# bytes transmitted via TCP"}, 265 {"dht", "# P2P PUT requests received"},
265 {"dht", "# FIXME"}, 266 {"dht", "# GET messages queued for transmission"},
267 {"dht", "# P2P GET requests received"},
268 {"dht", "# RESULT messages queued for transmission"},
269 {"dht", "# P2P RESULTS received"},
266 {NULL, NULL} 270 {NULL, NULL}
267}; 271};
268 272
@@ -283,6 +287,7 @@ print_stat (void *cls, const char *subsystem, const char *name, uint64_t value,
283{ 287{
284 struct StatMaster *sm = cls; 288 struct StatMaster *sm = cls;
285 289
290 stats[sm->value].total += value;
286 fprintf (stderr, "Peer %2u: %12s/%50s = %12llu\n", sm->daemon, subsystem, 291 fprintf (stderr, "Peer %2u: %12s/%50s = %12llu\n", sm->daemon, subsystem,
287 name, (unsigned long long) value); 292 name, (unsigned long long) value);
288 return GNUNET_OK; 293 return GNUNET_OK;
@@ -317,7 +322,9 @@ static void
317stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 322stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
318{ 323{
319 struct StatMaster *sm = cls; 324 struct StatMaster *sm = cls;
325 unsigned int i;
320 326
327 die_task = GNUNET_SCHEDULER_NO_TASK;
321 if (stats[sm->value].name != NULL) 328 if (stats[sm->value].name != NULL)
322 { 329 {
323 GNUNET_STATISTICS_get (sm->stat, 330 GNUNET_STATISTICS_get (sm->stat,
@@ -336,14 +343,21 @@ stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
336 if (sm->daemon == num_peers) 343 if (sm->daemon == num_peers)
337 { 344 {
338 GNUNET_free (sm); 345 GNUNET_free (sm);
339 GNUNET_SCHEDULER_add_now (&do_stop, NULL); 346 i = 0;
347 while (stats[i].name != NULL)
348 {
349 fprintf (stderr, "Total : %12s/%50s = %12llu\n", stats[i].subsystem,
350 stats[i].name, (unsigned long long) stats[i].total);
351 i++;
352 }
353 die_task = GNUNET_SCHEDULER_add_now (&do_stop, NULL);
340 return; 354 return;
341 } 355 }
342 sm->stat = 356 sm->stat =
343 GNUNET_STATISTICS_create ("<driver>", 357 GNUNET_STATISTICS_create ("<driver>",
344 GNUNET_TESTING_daemon_get (pg, 358 GNUNET_TESTING_daemon_get (pg,
345 sm->daemon)->cfg); 359 sm->daemon)->cfg);
346 GNUNET_SCHEDULER_add_now (&stat_run, sm); 360 die_task = GNUNET_SCHEDULER_add_now (&stat_run, sm);
347} 361}
348 362
349 363
@@ -384,13 +398,12 @@ finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
384 test_get); 398 test_get);
385 GNUNET_free (test_get); 399 GNUNET_free (test_get);
386 } 400 }
387 ok = 0;
388 sm = GNUNET_malloc (sizeof (struct StatMaster)); 401 sm = GNUNET_malloc (sizeof (struct StatMaster));
389 sm->stat = 402 sm->stat =
390 GNUNET_STATISTICS_create ("<driver>", 403 GNUNET_STATISTICS_create ("<driver>",
391 GNUNET_TESTING_daemon_get (pg, 404 GNUNET_TESTING_daemon_get (pg,
392 sm->daemon)->cfg); 405 sm->daemon)->cfg);
393 GNUNET_SCHEDULER_add_now (&stat_run, sm); 406 die_task = GNUNET_SCHEDULER_add_now (&stat_run, sm);
394} 407}
395 408
396 409
@@ -474,21 +487,25 @@ get_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
474 all_gets_tail, 487 all_gets_tail,
475 test_get); 488 test_get);
476 GNUNET_free (test_get); 489 GNUNET_free (test_get);
477 490 if ((gets_failed > 10) && (outstanding_gets == 0))
478 if ((gets_failed > 0) && (outstanding_gets == 0)) /* Had some failures */
479 { 491 {
492 /* Had more than 10% failures */
480 fprintf (stderr, 493 fprintf (stderr,
481 "%llu gets succeeded, %llu gets failed!\n", 494 "%llu gets succeeded, %llu gets failed!\n",
482 gets_completed, gets_failed); 495 gets_completed, gets_failed);
483 GNUNET_SCHEDULER_cancel (die_task); 496 GNUNET_SCHEDULER_cancel (die_task);
484 die_task = GNUNET_SCHEDULER_add_now (&end_badly, "not all gets succeeded"); 497 ok = 1;
498 die_task = GNUNET_SCHEDULER_add_now (&finish_testing, "not all gets succeeded");
485 return; 499 return;
486 } 500 }
487 501 if ( (gets_completed + gets_failed == num_peers * num_peers) &&
488 if ( (gets_completed == num_peers * num_peers) &&
489 (outstanding_gets == 0) ) /* All gets successful */ 502 (outstanding_gets == 0) ) /* All gets successful */
490 { 503 {
504 fprintf (stderr,
505 "%llu gets succeeded, %llu gets failed!\n",
506 gets_completed, gets_failed);
491 GNUNET_SCHEDULER_cancel (die_task); 507 GNUNET_SCHEDULER_cancel (die_task);
508 ok = 0;
492 die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL); 509 die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
493 } 510 }
494} 511}
diff --git a/src/hello/hello.c b/src/hello/hello.c
index b53bf62bc..c7db77a18 100644
--- a/src/hello/hello.c
+++ b/src/hello/hello.c
@@ -26,7 +26,7 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_hello_lib.h" 27#include "gnunet_hello_lib.h"
28#include "gnunet_protocols.h" 28#include "gnunet_protocols.h"
29#include "gnunet_server_lib.h" 29#include "gnunet_util_lib.h"
30 30
31/** 31/**
32 * A HELLO message is used to exchange information about 32 * A HELLO message is used to exchange information about
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index f4844821c..6b3ffe2af 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -138,6 +138,7 @@ typedef int (*GNUNET_FileNameCallback) (void *cls, const char *filename);
138 */ 138 */
139enum GNUNET_ErrorType 139enum GNUNET_ErrorType
140{ 140{
141 GNUNET_ERROR_TYPE_UNSPECIFIED = -1,
141 GNUNET_ERROR_TYPE_NONE = 0, 142 GNUNET_ERROR_TYPE_NONE = 0,
142 GNUNET_ERROR_TYPE_ERROR = 1, 143 GNUNET_ERROR_TYPE_ERROR = 1,
143 GNUNET_ERROR_TYPE_WARNING = 2, 144 GNUNET_ERROR_TYPE_WARNING = 2,
@@ -161,6 +162,15 @@ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind,
161 const char *component, const char *date, 162 const char *component, const char *date,
162 const char *message); 163 const char *message);
163 164
165
166/**
167 * Number of log calls to ignore.
168 */
169extern unsigned int skip_log;
170#if !defined(GNUNET_CULL_LOGGING)
171int
172GNUNET_get_log_call_status (int caller_level, const char *comp, const char *file, const char *function, int line);
173#endif
164/** 174/**
165 * Main log function. 175 * Main log function.
166 * 176 *
@@ -169,9 +179,29 @@ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind,
169 * @param ... arguments for format string 179 * @param ... arguments for format string
170 */ 180 */
171void 181void
172GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...); 182GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...);
173 183
184/* from glib */
185#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
186#define _GNUNET_BOOLEAN_EXPR(expr) \
187 __extension__ ({ \
188 int _gnunet_boolean_var_; \
189 if (expr) \
190 _gnunet_boolean_var_ = 1; \
191 else \
192 _gnunet_boolean_var_ = 0; \
193 _gnunet_boolean_var_; \
194})
195#define GN_LIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 1))
196#define GN_UNLIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 0))
197#else
198#define GN_LIKELY(expr) (expr)
199#define GN_UNLIKELY(expr) (expr)
200#endif
174 201
202#if !defined(GNUNET_LOG_CALL_STATUS)
203#define GNUNET_LOG_CALL_STATUS -1
204#endif
175 205
176/** 206/**
177 * Log function that specifies an alternative component. 207 * Log function that specifies an alternative component.
@@ -183,9 +213,35 @@ GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...);
183 * @param ... arguments for format string 213 * @param ... arguments for format string
184 */ 214 */
185void 215void
186GNUNET_log_from (enum GNUNET_ErrorType kind, const char *comp, 216GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
187 const char *message, ...); 217 const char *message, ...);
188 218
219#if !defined(GNUNET_CULL_LOGGING)
220#define GNUNET_log_from(kind,comp,...) do { int log_line = __LINE__;\
221 static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
222 if (GN_UNLIKELY(log_call_enabled == -1))\
223 log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), comp, __FILE__, __FUNCTION__, log_line);\
224 if (GN_UNLIKELY(skip_log > 0)) {skip_log--;}\
225 else {\
226 if (GN_UNLIKELY(log_call_enabled))\
227 GNUNET_log_from_nocheck (kind, comp, __VA_ARGS__);\
228 }\
229} while (0)
230
231#define GNUNET_log(kind,...) do { int log_line = __LINE__;\
232 static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
233 if (GN_UNLIKELY(log_call_enabled == -1))\
234 log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), NULL, __FILE__, __FUNCTION__, log_line);\
235 if (GN_UNLIKELY(skip_log > 0)) {skip_log--;}\
236 else {\
237 if (GN_UNLIKELY(log_call_enabled))\
238 GNUNET_log_nocheck (kind, __VA_ARGS__);\
239 }\
240} while (0)
241#else
242#define GNUNET_log(...)
243#define GNUNET_log_from(...)
244#endif
189 245
190/** 246/**
191 * Ignore the next n calls to the log function. 247 * Ignore the next n calls to the log function.
diff --git a/src/util/common_logging.c b/src/util/common_logging.c
index ff3ac12ee..16d367de8 100644
--- a/src/util/common_logging.c
+++ b/src/util/common_logging.c
@@ -115,6 +115,11 @@ static char last_bulk_comp[COMP_TRACK_SIZE + 1];
115static char *component; 115static char *component;
116 116
117/** 117/**
118 * Running component (without pid).
119 */
120static char *component_nopid;
121
122/**
118 * Minimum log level. 123 * Minimum log level.
119 */ 124 */
120static enum GNUNET_ErrorType min_level; 125static enum GNUNET_ErrorType min_level;
@@ -127,13 +132,94 @@ static struct CustomLogger *loggers;
127/** 132/**
128 * Number of log calls to ignore. 133 * Number of log calls to ignore.
129 */ 134 */
130static unsigned int skip_log; 135unsigned int skip_log;
131 136
132/** 137/**
133 * File descriptor to use for "stderr", or NULL for none. 138 * File descriptor to use for "stderr", or NULL for none.
134 */ 139 */
135static FILE *GNUNET_stderr; 140static FILE *GNUNET_stderr;
136 141
142/**
143 * Represents a single logging definition
144 */
145struct LogDef
146{
147 /**
148 * Component name. NULL means that this definition matches any component
149 */
150 char *component;
151
152 /**
153 * File name. NULL means that this definition matches any file
154 */
155 char *file;
156
157 /**
158 * Stores strlen(file)
159 */
160 int strlen_file;
161
162 /**
163 * Function name. NULL means that this definition matches any function
164 */
165 char *function;
166
167 /**
168 * Lowest line at which this definition matches.
169 * Defaults to 0. Must be <= to_line.
170 */
171 int from_line;
172
173 /**
174 * Highest line at which this definition matches.
175 * Defaults to INT_MAX. Must be >= from_line.
176 */
177 int to_line;
178
179 /**
180 * Maximal log level allowed for calls that match this definition.
181 * Calls with higher log level will be disabled.
182 * Must be >= 0
183 */
184 int level;
185
186 /**
187 * 1 if this definition comes from GNUNET_FORCE_LOG, which means that it
188 * overrides any configuration options. 0 otherwise.
189 */
190 int force;
191};
192
193/**
194 * Dynamic array of logging definitions
195 */
196struct LogDef *logdefs = NULL;
197
198/**
199 * Allocated size of logdefs array (in units)
200 */
201int logdefs_size = 0;
202
203/**
204 * The number of units used in logdefs array.
205 */
206int logdefs_len = 0;
207
208/**
209 * GNUNET_YES if GNUNET_LOG environment variable is already parsed.
210 */
211int gnunet_log_parsed = GNUNET_NO;
212
213/**
214 * GNUNET_YES if GNUNET_FORCE_LOG environment variable is already parsed.
215 */
216int gnunet_force_log_parsed = GNUNET_NO;
217
218/**
219 * GNUNET_YES if at least one definition with forced == 1 is available.
220 */
221int gnunet_force_log_present = GNUNET_NO;
222
137#ifdef WINDOWS 223#ifdef WINDOWS
138/** 224/**
139 * Contains the number of performance counts per second. 225 * Contains the number of performance counts per second.
@@ -151,6 +237,8 @@ LARGE_INTEGER performance_frequency;
151static enum GNUNET_ErrorType 237static enum GNUNET_ErrorType
152get_type (const char *log) 238get_type (const char *log)
153{ 239{
240 if (log == NULL)
241 return GNUNET_ERROR_TYPE_UNSPECIFIED;
154 if (0 == strcasecmp (log, _("DEBUG"))) 242 if (0 == strcasecmp (log, _("DEBUG")))
155 return GNUNET_ERROR_TYPE_DEBUG; 243 return GNUNET_ERROR_TYPE_DEBUG;
156 if (0 == strcasecmp (log, _("INFO"))) 244 if (0 == strcasecmp (log, _("INFO")))
@@ -163,9 +251,264 @@ get_type (const char *log)
163 return GNUNET_ERROR_TYPE_NONE; 251 return GNUNET_ERROR_TYPE_NONE;
164 return GNUNET_ERROR_TYPE_INVALID; 252 return GNUNET_ERROR_TYPE_INVALID;
165} 253}
254#if !defined(GNUNET_CULL_LOGGING)
255/**
256 * Utility function - reallocates logdefs array to be twice as large.
257 */
258static void
259resize_logdefs ()
260{
261 logdefs_size = (logdefs_size + 1) * 2;
262 logdefs = GNUNET_realloc (logdefs, logdefs_size * sizeof (struct LogDef));
263}
264
265/**
266 * Utility function - adds a parsed definition to logdefs array.
267 *
268 * @param component see struct LogDef, can't be NULL
269 * @param file see struct LogDef, can't be NULL
270 * @param function see struct LogDef, can't be NULL
271 * @param from_line see struct LogDef
272 * @param to_line see struct LogDef
273 * @param level see struct LogDef, must be >= 0
274 * @param force see struct LogDef
275 */
276static void
277add_definition (char *component, char *file, char *function, int from_line, int to_line, int level, int force)
278{
279 if (logdefs_size == logdefs_len)
280 resize_logdefs ();
281 struct LogDef n;
282 memset (&n, 0, sizeof (n));
283 if (strlen (component) > 0 && component[0] != '*')
284 n.component = strdup (component);
285 if (strlen (file) > 0 && file[0] != '*')
286 {
287 n.file = strdup (file);
288 n.strlen_file = strlen (file);
289 }
290 if (strlen (function) > 0 && function[0] != '*')
291 n.function = strdup (function);
292 n.from_line = from_line;
293 n.to_line = to_line;
294 n.level = level;
295 n.force = force;
296 logdefs[logdefs_len++] = n;
297}
298
299
300/**
301 * Decides whether a particular logging call should or should not be allowed
302 * to be made. Used internally by GNUNET_log*()
303 *
304 * @param caller_level loglevel the caller wants to use
305 * @param comp component name the caller uses (NULL means that global
306 * component name is used)
307 * @param file file name containing the logging call, usually __FILE__
308 * @param function function which tries to make a logging call,
309 * usually __FUNCTION__
310 * @param line line at which the call is made, usually __LINE__
311 * @return 0 to disallow the call, 1 to allow it
312 */
313int
314GNUNET_get_log_call_status (int caller_level, const char *comp, const char *file, const char *function, int line)
315{
316 struct LogDef *ld;
317 int i;
318 int force_only;
319 size_t strlen_file;
320 int matches = 0;
321
322 if (comp == NULL)
323 /* Use default component */
324 comp = component_nopid;
325
326 /* We have no definitions to override globally configured log level,
327 * so just use it right away.
328 */
329 if (min_level >= 0 && gnunet_force_log_present == GNUNET_NO)
330 return caller_level <= min_level;
331
332 /* Only look for forced definitions? */
333 force_only = min_level >= 0;
334 strlen_file = strlen (file);
335 for (i = 0; i < logdefs_len; i++)
336 {
337 ld = &logdefs[i];
338 if ((!force_only || ld->force) &&
339 (line >= ld->from_line && line <= ld->to_line) &&
340 (ld->component == NULL || strcmp (comp, ld->component) == 0) &&
341 (ld->file == NULL ||
342 (ld->strlen_file <= strlen_file &&
343 strcmp (&file[strlen_file - ld->strlen_file], ld->file) == 0)) &&
344 (ld->function == NULL || strcmp (function, ld->function) == 0)
345 )
346 {
347 /* This definition matched! */
348 matches += 1;
349 /* And if it allows the call to be made, then we're finished */
350 if (caller_level <= ld->level)
351 return 1;
352 }
353 }
354 /* If some definitions did match, but had too low loglevel to allow logging,
355 * don't check any further.
356 */
357 if (matches > 0)
358 return 0;
359 /* Otherwise use global level, if defined */
360 if (min_level >= 0)
361 return caller_level <= min_level;
362 /* All programs/services previously defaulted to WARNING.
363 * Now WE default to WARNING, and THEY default to NULL.
364 */
365 return caller_level <= GNUNET_ERROR_TYPE_WARNING;
366}
166 367
167 368
168/** 369/**
370 * Utility function - parses a definition
371 *
372 * Definition format:
373 * component;file;function;from_line-to_line;level[/component...]
374 * All entries are mandatory, but may be empty.
375 * Empty entries for component, file and function are treated as
376 * "matches anything".
377 * Empty line entry is treated as "from 0 to INT_MAX"
378 * Line entry with only one line is treated as "this line only"
379 * Entry for level MUST NOT be empty.
380 * Entries for component, file and function that consist of a
381 * single character "*" are treated (at the moment) the same way
382 * empty entries are treated (wildcard matching is not implemented (yet?)).
383 * file entry is matched to the end of __FILE__. That is, it might be
384 * a base name, or a base name with leading directory names (some compilers
385 * define __FILE__ to absolute file path).
386 *
387 * @param constname name of the environment variable from which to get the
388 * string to be parsed
389 * @param force 1 if definitions found in @constname are to be forced
390 * @return number of added definitions
391 */
392static int
393parse_definitions (const char *constname, int force)
394{
395 char *def;
396 const char *tmp;
397 char *comp = NULL;
398 char *file = NULL;
399 char *function = NULL;
400 char *p;
401 char *start;
402 char *t;
403 short state;
404 int level;
405 int from_line, to_line;
406 int counter = 0;
407 int keep_looking = 1;
408 tmp = getenv (constname);
409 if (tmp == NULL)
410 return 0;
411 def = strdup (tmp);
412 level = -1;
413 from_line = 0;
414 to_line = INT_MAX;
415 for (p = def, state = 0, start = def; keep_looking; p++)
416 {
417 switch (p[0])
418 {
419 case ';': /* found a field separator */
420 p[0] = '\0';
421 switch (state)
422 {
423 case 0: /* within a component name */
424 comp = start;
425 break;
426 case 1: /* within a file name */
427 file = start;
428 break;
429 case 2: /* within a function name */
430 /* after a file name there must be a function name */
431 function = start;
432 break;
433 case 3: /* within a from-to line range */
434 if (strlen (start) > 0)
435 {
436 errno = 0;
437 from_line = strtol (start, &t, 10);
438 if (errno != 0 || from_line < 0)
439 {
440 free (def);
441 return counter;
442 }
443 if (t < p && t[0] == '-')
444 {
445 errno = 0;
446 start = t + 1;
447 to_line = strtol (start, &t, 10);
448 if (errno != 0 || to_line < 0 || t != p)
449 {
450 free (def);
451 return counter;
452 }
453 }
454 else /* one number means "match this line only" */
455 to_line = from_line;
456 }
457 else /* default to 0-max */
458 {
459 from_line = 0;
460 to_line = INT_MAX;
461 }
462 break;
463 }
464 start = p + 1;
465 state += 1;
466 break;
467 case '\0': /* found EOL */
468 keep_looking = 0;
469 /* fall through to '/' */
470 case '/': /* found a definition separator */
471 switch (state)
472 {
473 case 4: /* within a log level */
474 p[0] = '\0';
475 state = 0;
476 level = get_type ((const char *) start);
477 if (level == GNUNET_ERROR_TYPE_INVALID || level == GNUNET_ERROR_TYPE_UNSPECIFIED)
478 {
479 free (def);
480 return counter;
481 }
482 add_definition (comp, file, function, from_line, to_line, level, force);
483 counter += 1;
484 start = p + 1;
485 break;
486 default:
487 break;
488 }
489 default:
490 break;
491 }
492 }
493 free (def);
494 return counter;
495}
496
497/**
498 * Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG.
499 */
500static void
501parse_all_definitions ()
502{
503 if (gnunet_log_parsed == GNUNET_NO)
504 parse_definitions ("GNUNET_LOG", 0);
505 gnunet_log_parsed = GNUNET_YES;
506 if (gnunet_force_log_parsed == GNUNET_NO)
507 gnunet_force_log_present = parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO;
508 gnunet_force_log_parsed = GNUNET_YES;
509}
510#endif
511/**
169 * Setup logging. 512 * Setup logging.
170 * 513 *
171 * @param comp default component to use 514 * @param comp default component to use
@@ -179,26 +522,24 @@ GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile)
179 FILE *altlog; 522 FILE *altlog;
180 int dirwarn; 523 int dirwarn;
181 char *fn; 524 char *fn;
182 const char *env_loglevel; 525 const char *env_logfile = NULL;
183 int env_minlevel = 0;
184 int env_min_force_level = 100000;
185 526
527 min_level = get_type (loglevel);
528#if !defined(GNUNET_CULL_LOGGING)
529 parse_all_definitions ();
530#endif
186#ifdef WINDOWS 531#ifdef WINDOWS
187 QueryPerformanceFrequency (&performance_frequency); 532 QueryPerformanceFrequency (&performance_frequency);
188#endif 533#endif
189 GNUNET_free_non_null (component); 534 GNUNET_free_non_null (component);
190 GNUNET_asprintf (&component, "%s-%d", comp, getpid ()); 535 GNUNET_asprintf (&component, "%s-%d", comp, getpid ());
191 env_loglevel = getenv ("GNUNET_LOGLEVEL"); 536 GNUNET_free_non_null (component_nopid);
192 if (env_loglevel != NULL) 537 component_nopid = strdup (comp);
193 env_minlevel = get_type (env_loglevel); 538
194 env_loglevel = getenv ("GNUNET_FORCE_LOGLEVEL"); 539 env_logfile = getenv ("GNUNET_FORCE_LOGFILE");
195 if (env_loglevel != NULL) 540 if (env_logfile != NULL)
196 env_min_force_level = get_type (env_loglevel); 541 logfile = env_logfile;
197 min_level = get_type (loglevel); 542
198 if (env_minlevel > min_level)
199 min_level = env_minlevel;
200 if (env_min_force_level < min_level)
201 min_level = env_min_force_level;
202 if (logfile == NULL) 543 if (logfile == NULL)
203 return GNUNET_OK; 544 return GNUNET_OK;
204 fn = GNUNET_STRINGS_filename_expand (logfile); 545 fn = GNUNET_STRINGS_filename_expand (logfile);
@@ -383,13 +724,6 @@ mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message,
383 char *buf; 724 char *buf;
384 va_list vacp; 725 va_list vacp;
385 726
386 if (skip_log > 0)
387 {
388 skip_log--;
389 return;
390 }
391 if ((kind & (~GNUNET_ERROR_TYPE_BULK)) > min_level)
392 return;
393 va_copy (vacp, va); 727 va_copy (vacp, va);
394 size = VSNPRINTF (NULL, 0, message, vacp) + 1; 728 size = VSNPRINTF (NULL, 0, message, vacp) + 1;
395 va_end (vacp); 729 va_end (vacp);
@@ -448,7 +782,7 @@ mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message,
448 * @param ... arguments for format string 782 * @param ... arguments for format string
449 */ 783 */
450void 784void
451GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...) 785GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...)
452{ 786{
453 va_list va; 787 va_list va;
454 788
@@ -468,12 +802,15 @@ GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...)
468 * @param ... arguments for format string 802 * @param ... arguments for format string
469 */ 803 */
470void 804void
471GNUNET_log_from (enum GNUNET_ErrorType kind, const char *comp, 805GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
472 const char *message, ...) 806 const char *message, ...)
473{ 807{
474 va_list va; 808 va_list va;
475 char comp_w_pid[128]; 809 char comp_w_pid[128];
476 810
811 if (comp == NULL)
812 comp = component_nopid;
813
477 va_start (va, message); 814 va_start (va, message);
478 GNUNET_snprintf (comp_w_pid, sizeof (comp_w_pid), "%s-%d", comp, getpid ()); 815 GNUNET_snprintf (comp_w_pid, sizeof (comp_w_pid), "%s-%d", comp, getpid ());
479 mylog (kind, comp_w_pid, message, va); 816 mylog (kind, comp_w_pid, message, va);
@@ -498,6 +835,8 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind)
498 return _("INFO"); 835 return _("INFO");
499 if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0) 836 if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0)
500 return _("DEBUG"); 837 return _("DEBUG");
838 if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0)
839 return _("NONE");
501 return _("INVALID"); 840 return _("INVALID");
502} 841}
503 842
diff --git a/src/util/program.c b/src/util/program.c
index d89b65a39..b09215343 100644
--- a/src/util/program.c
+++ b/src/util/program.c
@@ -210,7 +210,7 @@ GNUNET_PROGRAM_run (int argc, char *const *argv, const char *binaryName,
210 cnt += sizeof (defoptions) / sizeof (struct GNUNET_GETOPT_CommandLineOption); 210 cnt += sizeof (defoptions) / sizeof (struct GNUNET_GETOPT_CommandLineOption);
211 qsort (allopts, cnt, sizeof (struct GNUNET_GETOPT_CommandLineOption), 211 qsort (allopts, cnt, sizeof (struct GNUNET_GETOPT_CommandLineOption),
212 &cmd_sorter); 212 &cmd_sorter);
213 loglev = GNUNET_strdup ("WARNING"); 213 loglev = NULL;
214 cc.cfgfile = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE); 214 cc.cfgfile = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
215 lpfx = GNUNET_strdup (binaryName); 215 lpfx = GNUNET_strdup (binaryName);
216 if (NULL != (spc = strstr (lpfx, " "))) 216 if (NULL != (spc = strstr (lpfx, " ")))
@@ -248,7 +248,7 @@ GNUNET_PROGRAM_run (int argc, char *const *argv, const char *binaryName,
248 /* clean up */ 248 /* clean up */
249 GNUNET_CONFIGURATION_destroy (cfg); 249 GNUNET_CONFIGURATION_destroy (cfg);
250 GNUNET_free_non_null (cc.cfgfile); 250 GNUNET_free_non_null (cc.cfgfile);
251 GNUNET_free (loglev); 251 GNUNET_free_non_null (loglev);
252 GNUNET_free_non_null (logfile); 252 GNUNET_free_non_null (logfile);
253 return GNUNET_OK; 253 return GNUNET_OK;
254} 254}
diff --git a/src/util/service.c b/src/util/service.c
index dc6a7330e..ad74d2786 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1542,7 +1542,7 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName,
1542 err = 1; 1542 err = 1;
1543 do_daemonize = 0; 1543 do_daemonize = 0;
1544 logfile = NULL; 1544 logfile = NULL;
1545 loglev = GNUNET_strdup ("WARNING"); 1545 loglev = NULL;
1546 cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE); 1546 cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
1547 memset (&sctx, 0, sizeof (sctx)); 1547 memset (&sctx, 0, sizeof (sctx));
1548 sctx.options = opt; 1548 sctx.options = opt;
@@ -1611,7 +1611,7 @@ shutdown:
1611 GNUNET_free_non_null (sctx.addrs); 1611 GNUNET_free_non_null (sctx.addrs);
1612 GNUNET_free_non_null (sctx.addrlens); 1612 GNUNET_free_non_null (sctx.addrlens);
1613 GNUNET_free_non_null (logfile); 1613 GNUNET_free_non_null (logfile);
1614 GNUNET_free (loglev); 1614 GNUNET_free_non_null (loglev);
1615 GNUNET_free (cfg_fn); 1615 GNUNET_free (cfg_fn);
1616 GNUNET_free_non_null (sctx.v4_denied); 1616 GNUNET_free_non_null (sctx.v4_denied);
1617 GNUNET_free_non_null (sctx.v6_denied); 1617 GNUNET_free_non_null (sctx.v6_denied);