/*
This file is part of GNUnet.
- (C) 2006, 2008, 2009 Christian Grothoff (and other contributing authors)
+ (C) 2006-2013 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
+ by the Free Software Foundation; either version 3, or (at your
option) any later version.
GNUnet is distributed in the hope that it will be useful, but
/**
* @file util/common_logging.c
* @brief error handling API
- *
* @author Christian Grothoff
*/
#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_strings_lib.h"
-#include "gnunet_time_lib.h"
-
+#include "gnunet_util_lib.h"
#include <regex.h>
+
/**
* After how many milliseconds do we always print
* that "message X was repeated N times"? Use 12h.
*/
-#define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000)
+#define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000LL * 1000LL)
/**
* After how many repetitions do we always print
/**
* Number of log calls to ignore.
*/
-unsigned int skip_log;
+int skip_log = 0;
/**
* File descriptor to use for "stderr", or NULL for none.
* Rotate logs, deleting the oldest log.
*
* @param new_name new name to add to the rotation
- */
+ */
static void
log_rotate (const char *new_name)
{
GNUNET_free (discard);
}
rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup (new_name);
- rotation_off++;
+ rotation_off++;
}
static int
setup_log_file (const struct tm *tm)
{
- static char last_fn[PATH_MAX + 1];
+ static char last_fn[PATH_MAX + 1];
char fn[PATH_MAX + 1];
int dirwarn;
int altlog_fd;
int dup_return;
FILE *altlog;
-
+ char *leftsquare;
+
if (NULL == log_file_name)
return GNUNET_SYSERR;
if (0 == strftime (fn, sizeof (fn), log_file_name, tm))
return GNUNET_SYSERR;
+ leftsquare = strrchr (fn, '[');
+ if ( (NULL != leftsquare) && (']' == leftsquare[1]) )
+ {
+ char *logfile_copy = GNUNET_strdup (fn);
+ logfile_copy[leftsquare - fn] = '\0';
+ logfile_copy[leftsquare - fn + 1] = '\0';
+ snprintf (fn, PATH_MAX, "%s%d%s",
+ logfile_copy, getpid (), &logfile_copy[leftsquare - fn + 2]);
+ GNUNET_free (logfile_copy);
+ }
if (0 == strcmp (fn, last_fn))
return GNUNET_OK; /* no change */
log_rotate (last_fn);
fn);
return GNUNET_SYSERR;
}
- GNUNET_stderr = altlog;
+ GNUNET_stderr = altlog;
return GNUNET_OK;
}
* @param comp default component to use
* @param loglevel what types of messages should be logged
* @param logfile which file to write log messages to (can be NULL)
- * @return GNUNET_OK on success
+ * @return #GNUNET_OK on success
*/
int
-GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile)
+GNUNET_log_setup (const char *comp,
+ const char *loglevel,
+ const char *logfile)
{
const char *env_logfile;
const struct tm *tm;
GNUNET_free (pos);
}
+#if WINDOWS
+CRITICAL_SECTION output_message_cs;
+#endif
+
/**
* Actually output the log message.
const char *datestr, const char *msg)
{
struct CustomLogger *pos;
-
+#if WINDOWS
+ EnterCriticalSection (&output_message_cs);
+#endif
if (NULL != GNUNET_stderr)
{
FPRINTF (GNUNET_stderr, "%s %s %s %s", datestr, comp,
pos->logger (pos->logger_cls, kind, comp, datestr, msg);
pos = pos->next;
}
+#if WINDOWS
+ LeaveCriticalSection (&output_message_cs);
+#endif
}
char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
int rev;
char *last;
- char *ft;
+ const char *ft;
- if ((last_bulk_time.abs_value == 0) || (last_bulk_repeat == 0))
+ if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat))
return;
rev = 0;
last = memchr (last_bulk, '\0', BULK_TRACK_SIZE);
last[0] = '\0';
}
ft = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration
- (last_bulk_time));
+ (last_bulk_time), GNUNET_YES);
snprintf (msg, sizeof (msg),
_("Message `%.*s' repeated %u times in the last %s\n"),
BULK_TRACK_SIZE, last_bulk, last_bulk_repeat, ft);
- GNUNET_free (ft);
if (rev == 1)
last[0] = '\n';
output_message (last_bulk_kind, last_bulk_comp, datestr, msg);
/**
* Ignore the next n calls to the log function.
*
- * @param n number of log calls to ignore
- * @param check_reset GNUNET_YES to assert that the log skip counter is currently zero
+ * @param n number of log calls to ignore (could be negative)
+ * @param check_reset #GNUNET_YES to assert that the log skip counter is currently zero
*/
void
-GNUNET_log_skip (unsigned int n, int check_reset)
+GNUNET_log_skip (int n,
+ int check_reset)
{
int ok;
ok = (0 == skip_log);
skip_log = 0;
if (check_reset)
- GNUNET_assert (ok);
+ GNUNET_break (ok);
}
else
{
}
+/**
+ * Get the number of log calls that are going to be skipped
+ *
+ * @return number of log calls to be ignored
+ */
+int
+GNUNET_get_log_skip ()
+{
+ return skip_log;
+}
+
+
/**
* Output a log message using the default mechanism.
*
* @param va arguments to the format string "message"
*/
static void
-mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message,
+mylog (enum GNUNET_ErrorType kind,
+ const char *comp,
+ const char *message,
va_list va)
{
char date[DATE_STR_SIZE];
memset (date, 0, DATE_STR_SIZE);
{
char buf[size];
+ long long offset;
#ifdef WINDOWS
LARGE_INTEGER pc;
time_t timetmp;
+ offset = GNUNET_TIME_get_offset ();
time (&timetmp);
+ timetmp += offset / 1000;
tmptr = localtime (&timetmp);
pc.QuadPart = 0;
QueryPerformanceCounter (&pc);
struct timeval timeofday;
gettimeofday (&timeofday, NULL);
+ offset = GNUNET_TIME_get_offset ();
+ if (offset > 0)
+ {
+ timeofday.tv_sec += offset / 1000LL;
+ timeofday.tv_usec += (offset % 1000LL) * 1000LL;
+ if (timeofday.tv_usec > 1000000LL)
+ {
+ timeofday.tv_usec -= 1000000LL;
+ timeofday.tv_sec++;
+ }
+ }
+ else
+ {
+ timeofday.tv_sec += offset / 1000LL;
+ if (timeofday.tv_usec > - (offset % 1000LL) * 1000LL)
+ {
+ timeofday.tv_usec += (offset % 1000LL) * 1000LL;
+ }
+ else
+ {
+ timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL;
+ timeofday.tv_sec--;
+ }
+ }
tmptr = localtime (&timeofday.tv_sec);
if (NULL == tmptr)
{
strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr);
snprintf (date, sizeof (date), date2, timeofday.tv_usec);
}
-#endif
+#endif
VSNPRINTF (buf, size, message, va);
- (void) setup_log_file (tmptr);
+ if (NULL != tmptr)
+ (void) setup_log_file (tmptr);
if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
- (last_bulk_time.abs_value != 0) &&
+ (0 != last_bulk_time.abs_value_us) &&
(0 == strncmp (buf, last_bulk, sizeof (last_bulk))))
{
last_bulk_repeat++;
- if ((GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value >
- BULK_DELAY_THRESHOLD) || (last_bulk_repeat > BULK_REPEAT_THRESHOLD))
+ if ( (GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value_us >
+ BULK_DELAY_THRESHOLD) ||
+ (last_bulk_repeat > BULK_REPEAT_THRESHOLD) )
flush_bulk (date);
return;
}
* @param ... arguments for format string
*/
void
-GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...)
+GNUNET_log_nocheck (enum GNUNET_ErrorType kind,
+ const char *message, ...)
{
va_list va;
*
* @param pid the peer identity
* @return string form of the pid; will be overwritten by next
- * call to GNUNET_i2s.
+ * call to #GNUNET_i2s.
*/
const char *
GNUNET_i2s (const struct GNUNET_PeerIdentity *pid)
{
- static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
-
- GNUNET_CRYPTO_hash_to_enc (&pid->hashPubKey, &ret);
- ret.encoding[4] = '\0';
- return (const char *) ret.encoding;
+ static char buf[256];
+ char *ret;
+
+ ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key);
+ strcpy (buf, ret);
+ GNUNET_free (ret);
+ buf[4] = '\0';
+ return buf;
}
*
* @param pid the peer identity
* @return string form of the pid; will be overwritten by next
- * call to GNUNET_i2s.
+ * call to #GNUNET_i2s_full.
*/
const char *
GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid)
{
- static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
+ static char buf[256];
+ char *ret;
- GNUNET_CRYPTO_hash_to_enc (&pid->hashPubKey, &ret);
- return (const char *) ret.encoding;
+ ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key);
+ strcpy (buf, ret);
+ GNUNET_free (ret);
+ return buf;
}
* in the entire API that is NOT reentrant!
*
* @param addr the address
- * @param addrlen the length of the address
+ * @param addrlen the length of the address in @a addr
* @return nicely formatted string for the address
- * will be overwritten by next call to GNUNET_a2s.
+ * will be overwritten by next call to #GNUNET_a2s.
*/
const char *
GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen)
return "<unbound UNIX client>";
un = (const struct sockaddr_un *) addr;
off = 0;
- if (un->sun_path[0] == '\0')
+ if ('\0' == un->sun_path[0])
off++;
- snprintf (buf, sizeof (buf), "%s%.*s", (off == 1) ? "@" : "",
+ memset (buf, 0, sizeof (buf));
+ snprintf (buf, sizeof (buf) - 1, "%s%.*s", (off == 1) ? "@" : "",
(int) (addrlen - sizeof (sa_family_t) - 1 - off),
&un->sun_path[off]);
return buf;
}
+/**
+ * Log error message about missing configuration option.
+ *
+ * @param kind log level
+ * @param section section with missing option
+ * @param option name of missing option
+ */
+void
+GNUNET_log_config_missing (enum GNUNET_ErrorType kind,
+ const char *section,
+ const char *option)
+{
+ GNUNET_log (kind,
+ _("Configuration fails to specify option `%s' in section `%s'!\n"),
+ option,
+ section);
+}
+
+
+/**
+ * Log error message about invalid configuration option value.
+ *
+ * @param kind log level
+ * @param section section with invalid option
+ * @param option name of invalid option
+ * @param required what is required that is invalid about the option
+ */
+void
+GNUNET_log_config_invalid (enum GNUNET_ErrorType kind,
+ const char *section,
+ const char *option,
+ const char *required)
+{
+ GNUNET_log (kind,
+ _("Configuration specifies invalid value for option `%s' in section `%s': %s\n"),
+ option, section, required);
+}
+
+
/**
* Initializer
*/
#ifdef MINGW
GNInitWinEnv (NULL);
#endif
+#if WINDOWS
+ if (!InitializeCriticalSectionAndSpinCount (&output_message_cs, 0x00000400))
+ GNUNET_abort ();
+#endif
}
*/
void __attribute__ ((destructor)) GNUNET_util_cl_fini ()
{
+#if WINDOWS
+ DeleteCriticalSection (&output_message_cs);
+#endif
#ifdef MINGW
GNShutdownWinEnv ();
#endif