From: Sebastian Harl Date: Sun, 10 Mar 2013 19:24:41 +0000 (+0100) Subject: utils error: Added module for error reporting. X-Git-Tag: sysdb-0.1.0~435 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=19d7d13262095deccad56275584aef7c2e6c5dee utils error: Added module for error reporting. This module will transparently store error information for each thread (similar to errno). Support functions to store and retrieve error messages are available on top of that. Once the error message has been passed to SysDB, it will log the entire message. Currently, only printing to the standard error channel are available. --- diff --git a/src/Makefile.am b/src/Makefile.am index b75bfff..9de8dd0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,6 +24,7 @@ libsysdb_la_SOURCES = \ core/plugin.c include/core/plugin.h \ core/store.c include/core/store.h \ include/utils/data.h \ + utils/error.c include/utils/error.h \ utils/llist.c include/utils/llist.h \ utils/string.c include/utils/string.h \ utils/time.c include/utils/time.h \ diff --git a/src/include/utils/error.h b/src/include/utils/error.h new file mode 100644 index 0000000..8b2a177 --- /dev/null +++ b/src/include/utils/error.h @@ -0,0 +1,116 @@ +/* + * SysDB - src/include/utils/error.h + * Copyright (C) 2013 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * SysDB error handling: + * Error handling in SysDB is done on a by-thread basis, that is, each thread + * will use its own memory region to store information about the last reported + * error. + * Once the error message has been passed to SysDB, it will log the entire + * message at once. XXX: currently, SysDB only supports printing the error to + * the standard error channel; support for other logging backends will be + * added later in a modular fashion. + */ + +#ifndef SDB_UTILS_ERROR_H +#define SDB_UTILS_ERROR_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* max length of any error message */ +#ifndef SDB_MAX_ERROR +# define SDB_MAX_ERROR 4096 +#endif /* ! SDB_MAX_ERROR */ + +/* On Linux systems and possibly others, this should be the same as the LOG_ + * constants defined by syslog. */ +enum { + SDB_LOG_EMERG = 0, + SDB_LOG_ERR = 3, + SDB_LOG_WARNING = 4, + SDB_LOG_NOTICE = 5, + SDB_LOG_INFO = 6, + SDB_LOG_DEBUG = 7, +}; +#define SDB_LOG_PRIO_TO_STRING(prio) \ + (((prio) == SDB_LOG_EMERG) ? "EMERG" \ + : ((prio) == SDB_LOG_ERR) ? "ERR" \ + : ((prio) == SDB_LOG_WARNING) ? "WARNING" \ + : ((prio) == SDB_LOG_NOTICE) ? "NOTICE" \ + : ((prio) == SDB_LOG_INFO) ? "INFO" \ + : ((prio) == SDB_LOG_DEBUG) ? "DEBUG" : "UNKNOWN") + +/* + * sdb_error_set: + * Set the current error message. The string will be formated in printf-style + * using the specified format and arguments and logged with the specified + * priority. XXX: SDB_LOG_EMERG might, at some point and/or depending on + * configuration, try a clean shut-down of the process. + */ +int +sdb_error_set(int prio, const char *fmt, ...); + +/* + * sdb_error_start, sdb_error_append, sdb_error_end: + * Compose the current error message from multiple parts. The error message + * will only be logged after calling sdb_error_finish(). + * See sdb_error_set for details. + */ +int +sdb_error_start(int prio, const char *fmt, ...); +int +sdb_error_append(const char *fmt, ...); +int +sdb_error_finish(void); + +/* + * sdb_error_get: + * Get the current error message. The string returned by this function is + * owned by SysDB and might point to static memory -- do not modify or free + * it. + */ +const char * +sdb_error_get(void); + +/* + * sdb_error_get_prio: + * Get the priority of the current error message -- see the SDB_LOG_ constants + * for details. + */ +int +sdb_error_get_prio(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ! SDB_UTILS_ERROR_H */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/utils/error.c b/src/utils/error.c new file mode 100644 index 0000000..34213b3 --- /dev/null +++ b/src/utils/error.c @@ -0,0 +1,237 @@ +/* + * SysDB - src/utils/error.c + * Copyright (C) 2013 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "utils/error.h" + +#include + +#include +#include +#include + +/* + * private data types + */ + +typedef struct { + int prio; + char msg[SDB_MAX_ERROR]; + _Bool finalized; +} sdb_error_ctx_t; +#define SDB_ERROR_INIT { -1, "", 1 } + +/* + * private variables + */ + +static sdb_error_ctx_t default_error_ctx = SDB_ERROR_INIT; + +static pthread_key_t error_ctx_key; +static _Bool error_ctx_key_initialized = 0; + +/* + * private helper functions + */ + +static void +sdb_error_ctx_init(void) +{ + if (error_ctx_key_initialized) + return; + + pthread_key_create(&error_ctx_key, NULL); + error_ctx_key_initialized = 1; +} /* sdb_error_init */ + +static sdb_error_ctx_t * +sdb_error_ctx_create(void) +{ + sdb_error_ctx_t *ctx; + + ctx = malloc(sizeof(*ctx)); + if (! ctx) + return NULL; + + *ctx = default_error_ctx; + + if (! error_ctx_key_initialized) + sdb_error_ctx_init(); + pthread_setspecific(error_ctx_key, ctx); + return ctx; +} /* sdb_error_ctx_create */ + +static sdb_error_ctx_t * +sdb_error_get_ctx(void) +{ + sdb_error_ctx_t *ctx; + + if (! error_ctx_key_initialized) + sdb_error_ctx_init(); + ctx = pthread_getspecific(error_ctx_key); + + if (! ctx) + ctx = sdb_error_ctx_create(); + if (! ctx) + return NULL; + return ctx; +} /* sdb_error_get_ctx */ + +static int +sdb_error_clear(void) +{ + sdb_error_ctx_t *ctx; + + ctx = sdb_error_get_ctx(); + if (! ctx) + return -1; + + ctx->prio = -1; + ctx->msg[0] = '\0'; + ctx->finalized = 1; + return 0; +} /* sdb_error_clear */ + +static int +sdb_error_vappend(int prio, const char *fmt, va_list ap) +{ + sdb_error_ctx_t *ctx; + size_t len; + + ctx = sdb_error_get_ctx(); + if (! ctx) + return -1; + + len = strlen(ctx->msg); + if (len >= sizeof(ctx->msg)) + return 0; /* nothing written */ + + if (prio >= 0) + ctx->prio = prio; + + ctx->finalized = 0; + return vsnprintf(ctx->msg + len, sizeof(ctx->msg) - len, fmt, ap); +} /* sdb_error_vappend */ + +static int +sdb_error_log(void) +{ + sdb_error_ctx_t *ctx; + int ret; + + ctx = sdb_error_get_ctx(); + if (! ctx) + return -1; + + if (ctx->finalized) + return 0; + + ret = fprintf(stderr, "[%s] %s\n", + SDB_LOG_PRIO_TO_STRING(ctx->prio), ctx->msg); + ctx->finalized = 1; + return ret; +} /* sdb_error_log */ + +/* + * public API + */ + +int +sdb_error_set(int prio, const char *fmt, ...) +{ + va_list ap; + int ret; + + if (sdb_error_clear()) + return -1; + + va_start(ap, fmt); + ret = sdb_error_vappend(prio, fmt, ap); + va_end(ap); + + sdb_error_log(); + return ret; +} /* sdb_error_set */ + +int +sdb_error_start(int prio, const char *fmt, ...) +{ + va_list ap; + int ret; + + if (sdb_error_clear()) + return -1; + + va_start(ap, fmt); + ret = sdb_error_vappend(prio, fmt, ap); + va_end(ap); + + return ret; +} /* sdb_error_start */ + +int +sdb_error_append(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = sdb_error_vappend(/* dont change prio */ -1, fmt, ap); + va_end(ap); + + return ret; +} /* sdb_error_append */ + +int +sdb_error_finish(void) +{ + return sdb_error_log(); +} /* sdb_error_finish */ + +const char * +sdb_error_get(void) +{ + sdb_error_ctx_t *ctx; + + ctx = sdb_error_get_ctx(); + if (! ctx) + return "success"; + return ctx->msg; +} /* sdb_error_get */ + +int +sdb_error_get_prio(void) +{ + sdb_error_ctx_t *ctx; + + ctx = sdb_error_get_ctx(); + if (! ctx) + return -1; + return ctx->prio; +} /* sdb_error_get_prio */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ +