⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 error.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
字号:
/*     This file is part of GNUnet.     (C) 2006, 2008 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     option) any later version.     GNUnet is distributed in the hope that it will be useful, but     WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     General Public License for more details.     You should have received a copy of the GNU General Public License     along with GNUnet; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file util/error/error.c * @brief error handling API * * @author Christian Grothoff */#include "platform.h"#include "gnunet_util.h"#ifdef MINGW#include <conio.h>#endif/** * After how many seconds do we always print * that "message X was repeated N times"? */#define BULK_DELAY_THRESHOLD (90 * GNUNET_CRON_SECONDS)/** * After how many repetitions do we always print * that "message X was repeated N times"? (even if * we have not yet reached the delay threshold) */#define BULK_REPEAT_THRESHOLD 1000/** * How many characters do we use for matching of * bulk messages? */#define BULK_TRACK_SIZE 256/** * How many characters can a date/time string * be at most? */#define DATE_STR_SIZE 64/** * Default context for logging errors; used * if NULL is passed to GNUNET_GE_LOG. */static struct GNUNET_GE_Context *defaultContext;typedef struct GNUNET_GE_Context{  /**   * Mask that determines which events to log.   */  GNUNET_GE_KIND mask;  /**   * Handler to call for each event.   */  GNUNET_GE_LogHandler handler;  /**   * Extra argument to handler.   */  void *cls;  /**   * Function to call to destroy this context.   */  GNUNET_GE_CtxFree destruct;  GNUNET_GE_Confirm confirm;  /**   * The last "bulk" error message that we have been logging.   * Note that this message maybe truncated to the first BULK_TRACK_SIZE   * characters, in which case it is NOT 0-terminated!   */  char last_bulk[BULK_TRACK_SIZE];  /**   * Type of the last bulk message.   */  GNUNET_GE_KIND last_bulk_kind;  /**   * Time of the last bulk error message (0 for none)   */  GNUNET_CronTime last_bulk_time;  /**   * Number of times that bulk message has been repeated since.   */  unsigned int last_bulk_repeat;} GNUNET_GE_Context;/** * Does the given event match the mask? * @param have the event type * @param mask the filter mask */intGNUNET_GE_applies (GNUNET_GE_KIND have, GNUNET_GE_KIND mask){  GNUNET_GE_KIND both = mask & have;  return ((both & GNUNET_GE_EVENTKIND) &&          (both & GNUNET_GE_USERKIND) && (both & GNUNET_GE_ROUTEKIND));}static voidflush_bulk (struct GNUNET_GE_Context *ctx, const char *datestr){  char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];  GNUNET_CronTime now;  int rev;  char *last;    if ( (ctx == NULL) ||       (ctx->last_bulk_time == 0) ||        (ctx->last_bulk_repeat == 0) )    return;  now = GNUNET_get_time ();  rev = 0;  last = memchr (ctx->last_bulk, '\0', BULK_TRACK_SIZE);  if (last == NULL)    last = &ctx->last_bulk[BULK_TRACK_SIZE - 1];  else if (last != ctx->last_bulk)    last--;  if (last[0] == '\n')    {      rev = 1;      last[0] = '\0';    }  snprintf (msg,            sizeof (msg),            _("Message `%.*s' repeated %u times in the last %llus\n"),            BULK_TRACK_SIZE,            ctx->last_bulk,            ctx->last_bulk_repeat,            (now - ctx->last_bulk_time) / GNUNET_CRON_SECONDS);  if (rev == 1)    last[0] = '\n';  if (ctx != NULL)    ctx->handler (ctx->cls, ctx->last_bulk_kind, datestr, msg);  else    fprintf (stderr, "%s %s", datestr, msg);  ctx->last_bulk_time = now;  ctx->last_bulk_repeat = 0;}voidGNUNET_GE_LOG (struct GNUNET_GE_Context *ctx, GNUNET_GE_KIND kind,               const char *message, ...){  va_list va;  char date[DATE_STR_SIZE];  time_t timetmp;  struct tm *tmptr;  size_t size;  char *buf;  GNUNET_CronTime now;  if (ctx == NULL)    ctx = defaultContext;  if ((ctx != NULL) && (!GNUNET_GE_applies (kind, ctx->mask)))    return;  if ((ctx == NULL) &&      (((kind & (GNUNET_GE_IMMEDIATE | GNUNET_GE_BULK)) == 0) ||       ((kind & (GNUNET_GE_FATAL | GNUNET_GE_ERROR)) == 0)))    return;  va_start (va, message);  size = VSNPRINTF (NULL, 0, message, va) + 1;  va_end (va);  buf = malloc (size);  if (buf == NULL)    return;                     /* oops */  va_start (va, message);  VSNPRINTF (buf, size, message, va);  va_end (va);  time (&timetmp);  memset (date, 0, DATE_STR_SIZE);  tmptr = localtime (&timetmp);  strftime (date, DATE_STR_SIZE, "%b %d %H:%M:%S", tmptr);  now = GNUNET_get_time ();  if ((ctx != NULL) &&      ((kind & GNUNET_GE_BULK) != 0))    {      if ((ctx->last_bulk_time != 0) &&          (0 == strncmp (buf, ctx->last_bulk, sizeof (ctx->last_bulk))))        {          ctx->last_bulk_repeat++;          if ((now - ctx->last_bulk_time > BULK_DELAY_THRESHOLD) ||              (ctx->last_bulk_repeat > BULK_REPEAT_THRESHOLD))            flush_bulk (ctx, date);	  free (buf);          return;        }      else        {          if (ctx->last_bulk_time != 0)            flush_bulk (ctx, date);          strncpy (ctx->last_bulk, buf, sizeof (ctx->last_bulk));          ctx->last_bulk_repeat = 0;          ctx->last_bulk_time = now;          ctx->last_bulk_kind = kind;        }    }  if ( (ctx != NULL) &&       ((now - ctx->last_bulk_time > BULK_DELAY_THRESHOLD) ||	(ctx->last_bulk_repeat > BULK_REPEAT_THRESHOLD)) )    {      flush_bulk (ctx, date);      ctx->last_bulk_time = 0;    }  if (ctx != NULL)    ctx->handler (ctx->cls, kind, date, buf);  else    fprintf (stderr, "%s %s", date, buf);  free (buf);}/** * @brief Get user confirmation (e.g. before the app shuts down and closes the *        error message */voidGNUNET_GE_CONFIRM (struct GNUNET_GE_Context *ctx){  if (ctx == NULL)    {      /* @TODO: we probably ought to get confirmations in all graphical         environments */#ifdef WINDOWS      /* Console open? */      if (GetStdHandle (STD_ERROR_HANDLE) != NULL)        {          fprintf (stderr, _("\nPress any key to continue\n"));          getch ();        }#endif    }  else if (ctx->confirm)    ctx->confirm (ctx->cls);}/** * Create a log context that calls a callback function * for matching events. * * @param mask which events is this handler willing to process? *        an event must be non-zero in all 3 GNUNET_GE_KIND categories *        to be passed to this handler */struct GNUNET_GE_Context *GNUNET_GE_create_context_callback (GNUNET_GE_KIND mask,                                   GNUNET_GE_LogHandler handler,                                   void *ctx,                                   GNUNET_GE_CtxFree liberator,                                   GNUNET_GE_Confirm confirm){  GNUNET_GE_Context *ret;  ret = malloc (sizeof (GNUNET_GE_Context));  if (ret == NULL)    return NULL;  memset (ret, 0, sizeof (GNUNET_GE_Context));  ret->mask = mask;  ret->handler = handler;  ret->cls = ctx;  ret->destruct = liberator;  ret->confirm = confirm;  return ret;}/** * Free a log context. */voidGNUNET_GE_free_context (GNUNET_GE_Context * ctx){  char date[DATE_STR_SIZE];  time_t timetmp;  struct tm *tmptr;  if (ctx == NULL)    return;  time (&timetmp);  memset (date, 0, DATE_STR_SIZE);  tmptr = localtime (&timetmp);  strftime (date, DATE_STR_SIZE, "%b %d %H:%M:%S", tmptr);  flush_bulk (ctx, date);  if (ctx->destruct != NULL)    ctx->destruct (ctx->cls);  free (ctx);}/** * Would an event of this kind be possibly * processed by the logger? * @param ctx the logger * @param have the kind of event */intGNUNET_GE_isLogged (GNUNET_GE_Context * ctx, GNUNET_GE_KIND kind){  if (ctx == NULL)    return GNUNET_YES;  return GNUNET_GE_applies (kind, ctx->mask);}/** * Convert a textual description of a loglevel * to the respective GNUNET_GE_KIND. * @returns GNUNET_GE_INVALID if log does not parse */GNUNET_GE_KINDGNUNET_GE_getKIND (const char *log){  if (0 == strcasecmp (log, _("DEBUG")))    return GNUNET_GE_DEBUG;  if (0 == strcasecmp (log, _("STATUS")))    return GNUNET_GE_STATUS;  if (0 == strcasecmp (log, _("WARNING")))    return GNUNET_GE_WARNING;  if (0 == strcasecmp (log, _("ERROR")))    return GNUNET_GE_ERROR;  if (0 == strcasecmp (log, _("FATAL")))    return GNUNET_GE_FATAL;  if (0 == strcasecmp (log, _("USER")))    return GNUNET_GE_USER;  if (0 == strcasecmp (log, _("ADMIN")))    return GNUNET_GE_ADMIN;  if (0 == strcasecmp (log, _("DEVELOPER")))    return GNUNET_GE_DEVELOPER;  if (0 == strcasecmp (log, _("REQUEST")))    return GNUNET_GE_REQUEST;  if (0 == strcasecmp (log, _("BULK")))    return GNUNET_GE_BULK;  if (0 == strcasecmp (log, _("IMMEDIATE")))    return GNUNET_GE_IMMEDIATE;  if (0 == strcasecmp (log, _("ALL")))    return GNUNET_GE_ALL;  return GNUNET_GE_INVALID;}/** * Convert KIND to String */const char *GNUNET_GE_kindToString (GNUNET_GE_KIND kind){  if ((kind & GNUNET_GE_DEBUG) > 0)    return _("DEBUG");  if ((kind & GNUNET_GE_STATUS) > 0)    return _("STATUS");  if ((kind & GNUNET_GE_INFO) > 0)    return _("INFO");  if ((kind & GNUNET_GE_WARNING) > 0)    return _("WARNING");  if ((kind & GNUNET_GE_ERROR) > 0)    return _("ERROR");  if ((kind & GNUNET_GE_FATAL) > 0)    return _("FATAL");  if ((kind & GNUNET_GE_USER) > 0)    return _("USER");  if ((kind & GNUNET_GE_ADMIN) > 0)    return _("ADMIN");  if ((kind & GNUNET_GE_DEVELOPER) > 0)    return _("DEVELOPER");  if ((kind & GNUNET_GE_REQUEST) > 0)    return _("REQUEST");  if ((kind & GNUNET_GE_BULK) > 0)    return _("BULK");  if ((kind & GNUNET_GE_IMMEDIATE) > 0)    return _("IMMEDIATE");  return _("NOTHING");}typedef struct{  struct GNUNET_GE_Context *c1;  struct GNUNET_GE_Context *c2;} CPair;static voidmultiplexer (void *ctx, GNUNET_GE_KIND kind, const char *date,             const char *msg){  CPair *pair = ctx;  if (GNUNET_GE_applies (kind, pair->c1->mask))    pair->c1->handler (pair->c1->cls, kind, date, msg);  if (GNUNET_GE_applies (kind, pair->c2->mask))    pair->c2->handler (pair->c2->cls, kind, date, msg);}static voidmulti_confirm (void *ctx){  CPair *pair = ctx;  if (pair->c1->confirm)    pair->c1->confirm (pair->c1->cls);  if (pair->c2->confirm)    pair->c2->confirm (pair->c2->cls);}static voidpairdestruct (void *ctx){  CPair *pair = ctx;  GNUNET_GE_free_context (pair->c1);  GNUNET_GE_free_context (pair->c2);  free (ctx);}/** * Create a context that sends events to two other contexts. * Note that the client must stop using ctx1/ctx2 henceforth. */struct GNUNET_GE_Context *GNUNET_GE_create_context_multiplexer (struct GNUNET_GE_Context *ctx1,                                      struct GNUNET_GE_Context *ctx2){  CPair *cls;  GNUNET_GE_Context *ret;  cls = malloc (sizeof (CPair));  if (cls == NULL)    return NULL;  cls->c1 = ctx1;  cls->c2 = ctx2;  ret = malloc (sizeof (GNUNET_GE_Context));  if (ret == NULL)    {      free (cls);      return NULL;    }  memset (ret, 0, sizeof (GNUNET_GE_Context));  ret->cls = cls;  ret->handler = &multiplexer;  ret->mask = ctx1->mask | ctx2->mask;  ret->destruct = &pairdestruct;  ret->confirm = &multi_confirm;  return ret;}voidGNUNET_GE_setDefaultContext (struct GNUNET_GE_Context *ctx){  defaultContext = ctx;}/* end of error.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -