summaryrefslogtreecommitdiffstats
path: root/elapi/elapi_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'elapi/elapi_log.c')
-rw-r--r--elapi/elapi_log.c767
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;
-}