diff options
Diffstat (limited to 'elapi/elapi_log.c')
-rw-r--r-- | elapi/elapi_log.c | 767 |
1 files changed, 0 insertions, 767 deletions
diff --git a/elapi/elapi_log.c b/elapi/elapi_log.c deleted file mode 100644 index 22a375b..0000000 --- a/elapi/elapi_log.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - ELAPI - - Implementation of the ELAPI logging interface. - - Copyright (C) Dmitri Pal <dpal@redhat.com> 2009 - - This program 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 3 of the License, or - (at your option) any later version. - This program 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 this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define _GNU_SOURCE -#include <sys/types.h> /* for stat() */ -#include <sys/stat.h> /* for stat() */ -#include <unistd.h> /* for stat() */ -#include <errno.h> /* for errors */ -#include <string.h> /* for memset() and other */ -#include <stdarg.h> /* for va_arg() */ -#include <stdlib.h> /* for free() */ - - -#include "elapi_priv.h" -#include "elapi_event.h" -#include "elapi_log.h" -#include "ini_config.h" -#include "trace.h" -#include "config.h" - - -/* Pointer to default global dispatcher */ -struct elapi_dispatcher *global_dispatcher = NULL; - - -/* Per review I was told to hard cord this name. So be it... */ -#define ELAPI_CONFIG_FILE_NAME "elapi.conf" - -/* Default config file */ -static char default_config_file[] = ELAPI_DEFAULT_CONFIG_DIR "/" ELAPI_CONFIG_FILE_NAME; -/* Default config dir */ -static char default_config_dir[] = ELAPI_DEFAULT_CONFIG_APP_DIR; - - -/* Was a cleanup callback registered ? */ -static int elapi_close_registered = 0; - - -/* Internal function to log message using args */ -static int elapi_dsp_msg_with_vargs(uint32_t target, - struct elapi_dispatcher *dispatcher, - struct collection_item *tpl, - va_list args) -{ - int error = EOK; - struct collection_item *event; - - TRACE_FLOW_STRING("elapi_dsp_msg_with_vargs", "Entry"); - - if (!dispatcher) { - TRACE_ERROR_NUMBER("Invalid argument", EINVAL); - return EINVAL; - } - - /* Create event */ - error = elapi_create_event_with_vargs(&event, - tpl, - NULL, - 0, - args); - - if (error) { - TRACE_ERROR_NUMBER("Failed to create event", error); - return error; - } - - /* Now log event */ - error = elapi_dsp_log(target, dispatcher, event); - - /* Destroy event */ - elapi_destroy_event(event); - - if (error) { - TRACE_ERROR_NUMBER("Failed to log event", error); - return error; - } - - TRACE_FLOW_STRING("elapi_dsp_msg_with_vargs", "Exit"); - return error; -} - - -/********** Main functions of the interface **********/ -/* Function to free the async context */ -void elapi_destroy_asctx(struct elapi_async_ctx *ctx) -{ - TRACE_FLOW_STRING("elapi_destroy_asctx", "Entry"); - - free(ctx); - - TRACE_FLOW_STRING("elapi_destroy_asctx", "Exit"); -} - -/* Function to validate the consistency of the - * async context */ -static int elapi_check_asctx(struct elapi_async_ctx *ctx) -{ - int error = EOK; - - TRACE_FLOW_STRING("elapi_check_asctx", "Entry"); - - /* Check callbacks */ - if ((ctx->add_fd_cb == NULL) || - (ctx->rem_fd_cb == NULL) || - (ctx->set_fd_cb == NULL) || - (ctx->add_tm_cb == NULL) || - (ctx->rem_tm_cb == NULL)) { - TRACE_ERROR_NUMBER("One of the callbacks is missing. Error", EINVAL); - return EINVAL; - } - - /* We do not check the data pointers. - * Why? Becuase thought it is a bad approach - * the data the callbacks will use - * can be a global (bad but can be!). - * So forcing caller to provide non-NULL - * data pointers is a bit too much. - */ - - TRACE_FLOW_STRING("elapi_check_asctx", "Exit"); - return error; -} - -/* Interface to create the async context */ -int elapi_create_asctx(struct elapi_async_ctx **ctx, - elapi_add_fd add_fd_cb, - elapi_rem_fd rem_fd_cb, - elapi_set_fd set_fd_cb, - void *ext_fd_data, - elapi_add_tm add_tm_cb, - elapi_rem_tm rem_tm_cb, - void *ext_tm_data) -{ - int error = EOK; - struct elapi_async_ctx *ctx_new; - - TRACE_FLOW_STRING("elapi_create_asctx", "Entry"); - - /* Allocate data, copy it and then check. - * Why this order? Why not check first - * without allocating memory and wasting - * cycles for it? - * Becuase the check function can be used - * in other place to validate that the context - * is correct. Allocating and freeing - * data is not an overhead since - * it is going to catch development - * error that would not exist in the final - * product. Otherwise the progam just - * would not run. - */ - - ctx_new = (struct elapi_async_ctx *)malloc(sizeof(struct elapi_async_ctx)); - if (ctx_new == NULL) { - TRACE_ERROR_NUMBER("Failed to allocate memory for the context", ENOMEM); - return ENOMEM; - } - - ctx_new->add_fd_cb = add_fd_cb; - ctx_new->rem_fd_cb = rem_fd_cb; - ctx_new->set_fd_cb = set_fd_cb; - ctx_new->add_tm_cb = add_tm_cb; - ctx_new->rem_tm_cb = rem_tm_cb; - ctx_new->ext_fd_data = ext_fd_data; - ctx_new->ext_tm_data = ext_tm_data; - - error = elapi_check_asctx(ctx_new); - if (error) { - TRACE_ERROR_NUMBER("Check context failed", error); - elapi_destroy_asctx(ctx_new); - return error; - } - - *ctx = ctx_new; - - TRACE_FLOW_STRING("elapi_create_asctx", "Exit"); - return error; -} - -/* Function to create a dispatcher */ -int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher, - const char *appname, - const char *config_path, - struct elapi_async_ctx *async_ctx) -{ - struct elapi_dispatcher *handle = NULL; - struct collection_item *error_set = NULL; - int error = EOK; - struct collection_item *item = NULL; - const char *config_file = NULL; - const char *config_dir = NULL; - struct stat stat_data; - - TRACE_FLOW_STRING("elapi_create_dispatcher_adv", "Entry point"); - - /* Make sure the memory for handle is passed in */ - if (dispatcher == NULL) { - TRACE_ERROR_STRING("elapi_create_dispatcher_adv", "Invalid parameter."); - return EINVAL; - } - - /* Make sure we got the right constant */ - TRACE_INFO_NUMBER("ELAPI_DEFAULT_APP_NAME_SIZE = ", ELAPI_DEFAULT_APP_NAME_SIZE); - - if ((appname != NULL) && (strlen(appname) > ELAPI_DEFAULT_APP_NAME_SIZE)) { - TRACE_ERROR_STRING("elapi_create_dispatcher", "Application name is too long."); - return EINVAL; - } - - /* Check if context is valid */ - if (async_ctx) { - error = elapi_check_asctx(async_ctx); - if (error) { - TRACE_ERROR_NUMBER("Check context failed", error); - return error; - } - } - - /* Check what is passed in the config_path */ - if (config_path) { - /* What is it ? */ - if(stat(config_path, &stat_data)) { - error = errno; - TRACE_ERROR_NUMBER("Invalid path assume defaults. Error", error); - config_file = default_config_file; - config_dir = default_config_dir; - } - else { - if (S_ISREG(stat_data.st_mode)) { - config_file = config_path; - config_dir = NULL; - TRACE_INFO_STRING("Will use config file", config_file); - } - else if (S_ISDIR(stat_data.st_mode)) { - config_file = NULL; - config_dir = config_path; - TRACE_INFO_STRING("Will use directory", config_dir); - } - else { - config_file = default_config_file; - config_dir = default_config_dir; - } - } - } - else { - config_file = default_config_file; - config_dir = default_config_dir; - } - - TRACE_INFO_STRING("FILE:", config_file); - TRACE_INFO_STRING("DIR:", config_dir); - - /* Allocate memory */ - handle = (struct elapi_dispatcher *) calloc(1, sizeof(struct elapi_dispatcher)); - if (handle == NULL) { - TRACE_ERROR_NUMBER("Memory allocation failed. Error", ENOMEM); - return ENOMEM; - } - - /* Save application name in the handle */ - if (appname != NULL) handle->appname = strdup(appname); - else handle->appname = strdup(ELAPI_DEFAULT_APP_NAME); - - TRACE_FLOW_STRING("Application name:", handle->appname); - - /* Check error */ - if (handle->appname == NULL) { - TRACE_ERROR_NUMBER("Memory allocation failed. Error", ENOMEM); - elapi_destroy_dispatcher(handle); - return ENOMEM; - } - - /* Read the ELAPI configuration and store it in the dispatcher handle */ - error = config_for_app(handle->appname, - config_file, - config_dir, - &(handle->ini_config), - INI_STOP_ON_ANY, - &error_set); - if (error) { - TRACE_ERROR_NUMBER("Attempt to read configuration returned error", error); - elapi_destroy_dispatcher(handle); - if (error_set) { - elapi_dump_ini_err(error_set); - free_ini_config_errors(error_set); - } - return error; - } - - /* Have to clean error set anyways */ - free_ini_config_errors(error_set); - - /* Get target list from configuration */ - error = get_config_item(ELAPI_DISPATCHER, - ELAPI_TARGETS, - handle->ini_config, - &item); - if (error) { - TRACE_ERROR_NUMBER("Attempt to read configuration returned error", error); - elapi_destroy_dispatcher(handle); - return error; - } - - /* Do we have targets? */ - if (item == NULL) { - /* There is no list of targets this is bad configuration - return error */ - TRACE_ERROR_STRING("No targets in the config file.", "Fatal error!"); - elapi_destroy_dispatcher(handle); - return ENOENT; - } - - /* Get one from config but make sure we free it later */ - handle->targets = get_string_config_array(item, NULL, NULL, NULL); - - /* Create the list of targets */ - error = elapi_tgt_mklist(handle); - if (error != EOK) { - TRACE_ERROR_NUMBER("Failed to create target list. Error", error); - elapi_destroy_dispatcher(handle); - return error; - } - - /* Populate async processing data if any */ - if (async_ctx) { - TRACE_INFO_STRING("Async data is present", ""); - handle->async_ctx = malloc(sizeof(struct elapi_async_ctx)); - if (handle->async_ctx != NULL) { - TRACE_ERROR_NUMBER("Failed to allocate async context", ENOMEM); - elapi_destroy_dispatcher(handle); - return ENOMEM; - } - /* Copy async data */ - memcpy(handle->async_ctx, async_ctx, sizeof(struct elapi_async_ctx)); - } - else { - TRACE_INFO_STRING("No async data present", ""); - handle->async_ctx = NULL; - } - - /* Build the list of the items we know how to resolve */ - error = elapi_init_resolve_list(&(handle->resolve_list)); - if (error != EOK) { - TRACE_ERROR_NUMBER("Failed to create list of resolvers. Error", error); - elapi_destroy_dispatcher(handle); - return error; - } - - *dispatcher = handle; - - TRACE_FLOW_STRING("elapi_create_dispatcher_adv", "Returning Success."); - return EOK; - -} - -/* Simple dispatcher */ -int elapi_create_dispatcher(struct elapi_dispatcher **dispatcher, - const char *appname, - const char *config_path) -{ - int error = EOK; - - TRACE_FLOW_STRING("elapi_create_dispatcher", "Entry."); - - /* Will have more parmeters in future */ - error = elapi_create_dispatcher_adv(dispatcher, - appname, - config_path, - NULL); - - TRACE_FLOW_STRING("elapi_create_dispatcher", "Exit."); - return error; - -} - -/* Function to clean memory associated with the dispatcher */ -void elapi_destroy_dispatcher(struct elapi_dispatcher *dispatcher) -{ - TRACE_FLOW_STRING("elapi_destroy_dispatcher", "Entry."); - - if (dispatcher) { - TRACE_INFO_STRING("Deleting template if any...", ""); - col_destroy_collection(dispatcher->default_tpl); - - if (dispatcher->target_list) { - TRACE_INFO_STRING("Closing target list.", ""); - (void)col_traverse_collection(dispatcher->target_list, - COL_TRAVERSE_ONELEVEL, - elapi_tgt_free_cb, - NULL); - - TRACE_INFO_STRING("Deleting target list.", ""); - col_destroy_collection(dispatcher->target_list); - } - - if (dispatcher->sink_list) { - TRACE_INFO_STRING("Closing sink list.", ""); - (void)col_traverse_collection(dispatcher->sink_list, - COL_TRAVERSE_ONELEVEL, - elapi_sink_free_cb, - NULL); - TRACE_INFO_STRING("Deleting target list.", ""); - col_destroy_collection(dispatcher->sink_list); - } - - TRACE_INFO_STRING("Freeing application name.", ""); - free(dispatcher->appname); - TRACE_INFO_STRING("Freeing async context.", ""); - free(dispatcher->async_ctx); - TRACE_INFO_STRING("Freeing config.", ""); - free_ini_config(dispatcher->ini_config); - TRACE_INFO_STRING("Deleting targets name array.", ""); - free_string_config_array(dispatcher->targets); - TRACE_INFO_STRING("Unbind resolver iterator.", ""); - col_unbind_iterator(dispatcher->resolve_list); - TRACE_INFO_STRING("Freeing dispatcher.", ""); - free(dispatcher); - } - - TRACE_FLOW_STRING("elapi_destroy_dispatcher", "Exit."); -} - -/* Function to log an event */ -int elapi_dsp_log(uint32_t target, - struct elapi_dispatcher *dispatcher, - struct collection_item *event) -{ - int error = EOK; - struct elapi_tgt_data target_data; - struct collection_item *resolved_event; - - TRACE_FLOW_STRING("elapi_dsp_log", "Entry"); - - if ((dispatcher == NULL) || - (event == NULL)) { - TRACE_ERROR_STRING("elapi_dsp_log", "ERROR Invalid argument"); - return EINVAL; - } - - /* Create a resolved event */ - error = elapi_resolve_event(&resolved_event, event, dispatcher); - if (error) { - TRACE_ERROR_NUMBER("Failed to create event context. Error", error); - return error; - } - - /* Wrap parameters into one argument and pass on */ - target_data.handle = dispatcher; - target_data.event = resolved_event; - target_data.target_mask = target; - - TRACE_INFO_NUMBER("Target mask is:", target_data.target_mask); - - /* Logging an event is just iterating through the targets and calling a callback */ - error = col_traverse_collection(dispatcher->target_list, - COL_TRAVERSE_ONELEVEL, - elapi_tgt_cb, - (void *)(&target_data)); - - elapi_destroy_event(resolved_event); - - TRACE_FLOW_NUMBER("elapi_dsp_log Exit. Returning", error); - return error; -} - -/* Initializes default internal template */ -int elapi_set_default_tplt(unsigned base, ...) -{ - int error = EOK; - struct collection_item *tpl = NULL; - va_list args; - - TRACE_FLOW_STRING("elapi_set_default_tplt", "Entry"); - - if (global_dispatcher == NULL) { - error = elapi_init(NULL, NULL); - if (error) { - TRACE_ERROR_NUMBER("Failed to init ELAPI", error); - return error; - } - } - - /* Clean previous instance of the default template */ - elapi_destroy_event_tplt(global_dispatcher->default_tpl); - global_dispatcher->default_tpl = NULL; - - /* Process varible arguments */ - va_start(args, base); - - /* Create template out of base and args */ - error = elapi_create_event_tplt_with_vargs(&tpl, - base, - args); - va_end(args); - - if (error) { - TRACE_ERROR_NUMBER("Failed to create template. Error", error); - return error; - } - - global_dispatcher->default_tpl = tpl; - - TRACE_FLOW_STRING("elapi_set_default_tplt", "Exit"); - return error; -} - -/* There is one default template associated with the dispatcher */ -int elapi_get_default_tplt(struct collection_item **tpl) -{ - int error = EOK; - - TRACE_FLOW_STRING("elapi_get_default_tplt", "Entry"); - - if ((global_dispatcher == NULL) || - (global_dispatcher->default_tpl == NULL)) { - TRACE_INFO_STRING("Default template does not exit", ""); - - error = elapi_set_default_tplt(E_BASE_DEFV1, E_EOARG); - if (error) { - TRACE_ERROR_NUMBER("Set default template returned error", error); - return error; - } - } - - *tpl = global_dispatcher->default_tpl; - TRACE_FLOW_NUMBER("elapi_get_default_tplt. Exit returning", error); - return error; -} - - - -/* Function to log raw key value pairs without creating an event */ -int elapi_dsp_msg(uint32_t target, - struct elapi_dispatcher *dispatcher, - struct collection_item *tpl, - ...) -{ - int error = EOK; - va_list args; - - TRACE_FLOW_STRING("elapi_dsp_msg", "Entry"); - - va_start(args, tpl); - - error = elapi_dsp_msg_with_vargs(target, dispatcher, tpl, args); - - va_end(args); - - TRACE_FLOW_STRING("elapi_dsp_msg.", "Exit"); - return error; -} - -/********** Advanced dispatcher managment functions **********/ - -/* Managing the sink collection */ -int elapi_alter_dispatcher(struct elapi_dispatcher *dispatcher, - const char *target, - const char *sink, - int action) -{ - - /* FIXME: FUNCTION IS NOT IMPLEMENTED YET */ - return EOK; -} - -/* Get sink list */ -char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher, char *target) -{ - - /* FIXME: FUNCTION IS NOT IMPLEMENTED YET */ - return NULL; -} - -/* Free sink list */ -void elapi_free_sink_list(char **sink_list) -{ - - /* FIXME: FUNCTION IS NOT IMPLEMENTED YET */ - -} - -/* Get target list */ -char **elapi_get_target_list(struct elapi_dispatcher *dispatcher) -{ - - /* FIXME: FUNCTION IS NOT IMPLEMENTED YET */ - return NULL; -} - -/* Free target list */ -void elapi_free_target_list(char **target_list) -{ - - /* FIXME: FUNCTION IS NOT IMPLEMENTED YET */ - -} - - -/******************** High level interface ************************************/ -/* This interface is not thread safe but hides the dispatcher. */ - -/* This function will use internal default template */ -int elapi_create_simple_event(struct collection_item **event, ...) -{ - int error = EOK; - struct collection_item *evt = NULL; - va_list args; - struct collection_item *tpl = NULL; - - TRACE_FLOW_STRING("elapi_create_simple_event", "Entry"); - - /* Check storage */ - if (event == NULL ) { - TRACE_ERROR_STRING("Event storage must be provided", ""); - return EINVAL; - } - - *event = NULL; - - /* Get default template */ - error = elapi_get_default_tplt(&tpl); - if (error) { - TRACE_ERROR_NUMBER("Failed to get default template. Error", error); - return error; - } - - va_start(args, event); - - /* Create event */ - error = elapi_create_event_with_vargs(&evt, - tpl, - NULL, - 0, - args); - - va_end(args); - - if (error) { - TRACE_ERROR_NUMBER("Failed to create event using arg list. Error", error); - col_destroy_collection(evt); - return error; - } - - *event = evt; - - TRACE_FLOW_STRING("elapi_create_simple_event", "Exit"); - return error; -} - -/* Log key value pairs */ -int elapi_msg(uint32_t target, struct collection_item *tpl, ...) -{ - int error = EOK; - va_list args; - struct collection_item *use_tpl; - - TRACE_FLOW_STRING("elapi_msg", "Entry"); - - if (!tpl) { - /* Get default template */ - error = elapi_get_default_tplt(&use_tpl); - if (error) { - TRACE_ERROR_NUMBER("Failed to get default template. Error", error); - return error; - } - } - else use_tpl = tpl; - - va_start(args, tpl); - - error = elapi_dsp_msg_with_vargs(target, - global_dispatcher, - use_tpl, - args); - - va_end(args); - - TRACE_FLOW_NUMBER("elapi_msg Exit:", error); - return error; -} - -/* Log event */ -int elapi_log(uint32_t target, struct collection_item *event) -{ - int error; - - TRACE_FLOW_STRING("elapi_log", "Entry"); - - /* If dispatcher was not initialized do it automatically */ - if (global_dispatcher == NULL) { - error = elapi_init(NULL, NULL); - if (error) { - TRACE_ERROR_NUMBER("Failed to init ELAPI", error); - return error; - } - } - error = elapi_dsp_log(target, global_dispatcher, event); - - TRACE_FLOW_NUMBER("elapi_log Exit:", error); - return error; -} - -/* Get dispatcher if you want to add sink to a default dispatcher or do some advanced operations */ -struct elapi_dispatcher *elapi_get_dispatcher(void) -{ - TRACE_FLOW_STRING("elapi_get_dispatcher was called.", "Returning default dispatcher."); - return global_dispatcher; - -} - -/* Close ELAPI */ -void elapi_close(void) -{ - TRACE_FLOW_STRING("elapi_close","Entry"); - - /* Destroy global dispatcher */ - elapi_destroy_dispatcher(global_dispatcher); - global_dispatcher = NULL; - - TRACE_FLOW_STRING("elapi_close","Exit"); -} - -/* Function to initialize ELAPI library in the single threaded applications */ -int elapi_init(const char *appname, const char *config_path) -{ - int error = EOK; - - TRACE_FLOW_STRING("elapi_init","Entry"); - - /* Clean the dispatcher if needed */ - elapi_close(); - - /* Create global dispatcher */ - error = elapi_create_dispatcher(&global_dispatcher, appname, config_path); - if (error) { - TRACE_ERROR_NUMBER("Failed to create default dispatcher. Error", error); - return error; - } - - /* Install a cleanup callback */ - if (!elapi_close_registered) { - if (atexit(elapi_close)) { - TRACE_ERROR_NUMBER("Failed to install cleanup callback. Error", ENOSYS); - /* NOTE: Could not find a better error for this case */ - return ENOSYS; - } - elapi_close_registered = 1; - } - - TRACE_FLOW_NUMBER("elapi_init Exit:",error); - return error; -} |