summaryrefslogtreecommitdiffstats
path: root/elapi/elapi_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'elapi/elapi_internal.c')
-rw-r--r--elapi/elapi_internal.c753
1 files changed, 0 insertions, 753 deletions
diff --git a/elapi/elapi_internal.c b/elapi/elapi_internal.c
deleted file mode 100644
index fbbc015..0000000
--- a/elapi/elapi_internal.c
+++ /dev/null
@@ -1,753 +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 <errno.h> /* for errors */
-#include <stdio.h> /* for printf() - temporarily */
-#include <stdlib.h> /* for malloc() */
-
-#include "elapi_priv.h"
-#include "elapi_event.h"
-#include "elapi_sink.h"
-#include "trace.h"
-#include "config.h"
-#include "ini_config.h"
-
-#include "collection_tools.h" /*temporarily */
-
-/* Buffer size for time string */
-#define MAX_TIMESTR 200
-
-/* I was told during review that I have to hard code the name.
- * So it is hardcoded now.
- */
-#define ELAPI_DEFAULT_ERROR_FILE "elapiconf.err"
-
-/* Handler for logging through the targets */
-int elapi_tgt_cb(const char *target,
- int target_len,
- int type,
- void *data,
- int length,
- void *passed_data,
- int *stop)
-{
- int error = EOK;
- struct elapi_tgt_data *target_data;
- struct elapi_tgt_ctx *context;
-
- TRACE_FLOW_STRING("elapi_tgt_cb", "Entry.");
-
- /* Skip header */
- if (type == COL_TYPE_COLLECTION) {
- TRACE_FLOW_STRING("elapi_tgt_cb - skip header", "Exit.");
- return EOK;
- }
-
- target_data = (struct elapi_tgt_data *)(passed_data);
- context = *((struct elapi_tgt_ctx **)(data));
-
- /* Check if we need to log this event into this target */
- TRACE_INFO_NUMBER("EVENT IS LOGGED INTO:", target_data->target_mask);
- TRACE_INFO_NUMBER("TARGET VALUE IS:", context->target_value);
-
- if ((target_data->target_mask & context->target_value) == 0) {
- TRACE_INFO_STRING("Current event will NOT be logged into the target:", target);
- return EOK;
- }
-
- TRACE_INFO_STRING("Current event will be logged into the target:", target);
-
- /* Log event */
- error = elapi_tgt_submit(target_data->handle, context, target_data->event);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to submit event to target", error);
- return error;
- }
-
- TRACE_FLOW_STRING("elapi_tgt_cb", "Exit.");
- return EOK;
-}
-
-/* Internal target cleanup function */
-int elapi_tgt_free_cb(const char *target,
- int target_len,
- int type,
- void *data,
- int length,
- void *passed_data,
- int *stop)
-{
- TRACE_FLOW_STRING("elapi_tgt_free_cb", "Entry.");
-
- /* Skip header */
- if (type == COL_TYPE_COLLECTION) {
- TRACE_FLOW_STRING("elapi_tgt_free_cb - skip header", "Exit.");
- return EOK;
- }
-
- elapi_tgt_destroy(*((struct elapi_tgt_ctx **)(data)));
-
- TRACE_FLOW_STRING("elapi_tgt_free_cb", "Exit.");
- return EOK;
-}
-
-/* Function to add a sink to the collection */
-/* This function belongs to this module.
- * It adds sink into the collection
- * of sinks inside dispatcher and puts
- * reference into the target's reference list.
- */
-/* FIXME - other arguments might be added later */
-int elapi_sink_add(struct collection_item **sink_ref,
- const char *sink,
- struct elapi_dispatcher *handle)
-{
- int error = EOK;
- struct elapi_sink_ctx *sink_context = NULL;
-
- TRACE_FLOW_STRING("elapi_sink_add", "Entry");
-
- TRACE_INFO_STRING("Evaluating sink:", sink);
- TRACE_INFO_NUMBER("Sink reference before call:", *sink_ref);
-
- /* Get the sink from the list */
- error = col_get_item(handle->sink_list,
- sink,
- COL_TYPE_ANY,
- COL_TRAVERSE_DEFAULT,
- sink_ref);
-
- TRACE_INFO_NUMBER("Sink evaluation returned", error);
- TRACE_INFO_NUMBER("Sink reference after call:", *sink_ref);
-
- if (error) {
- TRACE_ERROR_NUMBER("Search returned error", error);
- return error;
- }
-
- if (!(*sink_ref)) {
- TRACE_FLOW_STRING("No such sink yet, adding new sink:", sink);
-
- /* Create a sink object */
- error = elapi_sink_create(&sink_context, sink, handle->ini_config, handle->appname);
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to add sink data as property", error);
- /* If create failed there is nothing to destroy */
- return error;
- }
-
- /* If there was an internal error but sink is optional
- * no error is returned but context is NULL.
- * We need to check for this situation.
- */
- if (sink_context) {
- TRACE_FLOW_STRING("Loaded sink:", sink);
- /* We got a valid sink so add it to the collection */
- error = col_add_binary_property_with_ref(handle->sink_list,
- NULL,
- sink,
- (void *)(&sink_context),
- sizeof(struct elapi_sink_ctx *),
- sink_ref);
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to add sink data as property", error);
- elapi_sink_destroy(sink_context);
- return error;
- }
- }
- else {
- *sink_ref = NULL;
- TRACE_FLOW_STRING("Setting sink reference to NULL", "");
- }
- }
-
- TRACE_FLOW_NUMBER("elapi_sink_add returning", error);
- return error;
-}
-
-/* Destroy target object */
-void elapi_tgt_destroy(struct elapi_tgt_ctx *context)
-{
- TRACE_FLOW_STRING("elapi_tgt_destroy", "Entry.");
-
- TRACE_INFO_NUMBER("Target address in cleanup:", context);
-
- if (context) {
- TRACE_INFO_STRING("Deleting the list of references to sinks", "");
- col_destroy_collection(context->sink_ref_list);
- /* FIXME - add other cleanup for other things that will be a part
- * of the target context.
- */
- free(context);
- }
-
- TRACE_FLOW_STRING("elapi_tgt_destroy", "Exit.");
-
-}
-
-/* Allocate target context and load sinks to it */
-int elapi_tgt_create(struct elapi_tgt_ctx **context,
- const char *target,
- struct elapi_dispatcher *handle)
-{
- int error = EOK;
- struct collection_item *sink_cfg_item = NULL;
- struct collection_item *value_cfg_item = NULL;
- struct elapi_tgt_ctx *target_context;
- char **sinks;
- char **current_sink;
- struct collection_item *sink_ref;
- unsigned count;
-
- TRACE_FLOW_STRING("elapi_tgt_create", "Entry.");
-
- /* Get list of sinks for this target from config */
- error = get_config_item(target,
- ELAPI_SINKS,
- handle->ini_config,
- &sink_cfg_item);
- if (error) {
- TRACE_ERROR_NUMBER("Attempt to read configuration returned error", error);
- return error;
- }
-
- /* Do we have sinks? */
- if (sink_cfg_item == NULL) {
- /* There is no list of targets this is bad configuration - return error */
- TRACE_ERROR_STRING("Required key is missing in the configuration.", "Fatal Error!");
- return ENOENT;
- }
-
- /* Allocate context */
- target_context = (struct elapi_tgt_ctx *)calloc(1, sizeof(struct elapi_tgt_ctx));
- if (target_context == NULL) {
- TRACE_ERROR_NUMBER("Memory allocation failed. Error", ENOMEM);
- return ENOMEM;
- }
-
- /* Assign target's value */
- error = get_config_item(target,
- ELAPI_TARGET_VALUE,
- handle->ini_config,
- &value_cfg_item);
- if (error) {
- TRACE_ERROR_NUMBER("Attempt to read configuration returned error", error);
- elapi_tgt_destroy(target_context);
- return error;
- }
-
- /* Do we have value? */
- if (value_cfg_item == NULL) {
- TRACE_INFO_STRING("Value for target is not defined.", "Assume ANY.");
- target_context->target_value = ELAPI_TARGET_ALL;
- }
- else {
- target_context->target_value = (uint32_t)get_unsigned_config_value(value_cfg_item,
- 1,
- ELAPI_TARGET_ALL,
- &error);
- /* NOTE: I will check and fail here on error rather than do a best effort
- * for now. We can switch to less rigorous checking when the INI
- * validation library/utility becomes available.
- */
- if (error) {
- TRACE_ERROR_NUMBER("Failed to convert value form INI file", error);
- elapi_tgt_destroy(target_context);
- return error;
- }
- }
-
- TRACE_INFO_NUMBER("Value for target is:", target_context->target_value);
-
-
- /* Allocate collection to store sink references for this target */
- error = col_create_collection(&(target_context->sink_ref_list),
- ELAPI_SINK_REFS,
- COL_CLASS_ELAPI_SINK_REF);
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to create sink collection. Error", error);
- elapi_tgt_destroy(target_context);
- return error;
- }
-
- /* Get list of sinks from config. Make sure we free it later */
- sinks = get_string_config_array(sink_cfg_item, NULL, NULL, NULL);
-
- /* For each sink in the list create sink context object and load sink */
- current_sink = sinks;
- while (*current_sink != NULL) {
-
- TRACE_INFO_STRING("Current sink", *current_sink);
-
- /* Load sink if it is not loaded yet */
- sink_ref = NULL;
- error = elapi_sink_add(&sink_ref,
- *current_sink,
- handle);
- if (error) {
- /* NOTE - we might decide to lax some of the checks
- * like this later and be satisfied with at least one
- * sink in the list. Subject for discussion...
- */
- TRACE_ERROR_NUMBER("Failed to add sink", error);
- elapi_tgt_destroy(target_context);
- free_string_config_array(sinks);
- return error;
- }
-
- /* It might be that is was an error wit the optional sink so
- * we need to check if the reference is not NULL;
- */
- if (sink_ref) {
- /* Add reference to it into the target object */
- error = col_add_binary_property(target_context->sink_ref_list, NULL,
- *current_sink, (void *)(&sink_ref),
- sizeof(struct collection_item *));
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to add sink reference", error);
- elapi_tgt_destroy(target_context);
- free_string_config_array(sinks);
- return error;
- }
- }
- else {
- TRACE_INFO_STRING("Sink reference is NULL.", "Skipping the sink");
- }
- current_sink++;
- }
-
- free_string_config_array(sinks);
-
- /* Get count of the references in the list */
- error = col_get_collection_count(target_context->sink_ref_list, &count);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to get count", error);
- elapi_tgt_destroy(target_context);
- return error;
- }
-
- /* Check count */
- if (count <= 1) {
- /* Nothing but header? - Bad! */
- TRACE_ERROR_NUMBER("No sinks loaded for target!", "This is a fatal error!");
- elapi_tgt_destroy(target_context);
- return ENOENT;
- }
-
- *context = target_context;
-
- TRACE_FLOW_STRING("elapi_tgt_create", "Exit.");
- return EOK;
-}
-
-
-/* Function to create a list of targets */
-int elapi_tgt_mklist(struct elapi_dispatcher *handle)
-{
- int error = EOK;
- char **current_target;
- struct elapi_tgt_ctx *context;
-
-
- TRACE_FLOW_STRING("elapi_tgt_mklist", "Entry");
-
- /* Allocate collection to store target */
- error = col_create_collection(&(handle->target_list),
- ELAPI_TARGETS,
- COL_CLASS_ELAPI_TARGET);
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to create target collection. Error", error);
- /* No cleanup here.
- * The calling function will call a cleanup
- * of the dispatcher as a whole.*/
- return error;
- }
-
- /* Allocate collection to store sinks */
- error = col_create_collection(&(handle->sink_list),
- ELAPI_SINKS,
- COL_CLASS_ELAPI_SINK);
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to create sink collection. Error", error);
- /* No cleanup here.
- * The calling function will call a cleanup
- * of the dispatcher as a whole.*/
- return error;
- }
-
- current_target = handle->targets;
- handle->target_counter = 0;
-
- /* Add targets as properties to the target collection */
- while (*current_target != NULL) {
-
- TRACE_INFO_STRING("Current target", *current_target);
-
- /* Allocate target context and load sinks to it */
- context = NULL;
- error = elapi_tgt_create(&context,
- *current_target,
- handle);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to create target", error);
- return error;
- }
-
- TRACE_INFO_NUMBER("Target address:", context);
-
- /* Add created target to the list of targets */
- error = col_add_binary_property(handle->target_list, NULL,
- *current_target, (void *)(&context),
- sizeof(struct elapi_tgt_ctx *));
- if (error != 0) {
- TRACE_ERROR_NUMBER("Failed to add sink data as property", error);
- /* Need to clean allocated context here if we failed to add it */
- elapi_tgt_destroy(context);
- return error;
- }
-
- handle->target_counter++;
- current_target++;
- }
-
- /* Check if we have any targets available */
- if (handle->target_counter == 0) {
- TRACE_ERROR_STRING("No targets", "");
- return ENOENT;
- }
-
- TRACE_FLOW_STRING("elapi_tgt_mklist", "Returning success");
- return EOK;
-}
-
-/* Submit event into the target */
-/* FIXME: do we need the whole dispatcher here?
- * probably not.
- * Need to sort out what parts of it we actually
- * need and pass them explicitely.
- * The point is that the target should not
- * know or care about the dispatcher internals
- * passing it here is a violation of the
- * several desing patterns so it should be
- * eventually fixed.
- */
-int elapi_tgt_submit(struct elapi_dispatcher *handle,
- struct elapi_tgt_ctx *context,
- struct collection_item *event)
-{
- int error = EOK;
- struct collection_iterator *iterator;
- struct collection_item *sink_item;
- struct elapi_sink_ctx *ctx;
-
- TRACE_FLOW_STRING("elapi_tgt_submit", "Entry");
-
- /* FIXME: General logic of the function
- * should be the following:
- * Get the list of the sinks
- * For each sink
- * Get its status
- * Check if the sink is active
- * If it is active log into it
- * In error fail over to the next one
- * else done
- * else (not active) is it revivable?
- * If so is it time to revive?
- * If so mark as active and log into it
- * If error fail over
- * else done
- * else fail over
- * else fail over
- * else fail over
- * End for each sink
- *
- * This logic will be implemented
- * in the later patches
- * for now we will try
- * all the sinks without checking status.
- */
-
- error = col_bind_iterator(&iterator, context->sink_ref_list,
- COL_TRAVERSE_DEFAULT);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to bind iterator.", error);
- return error;
- }
-
- while(1) {
- /* Loop through the sink references */
- error = col_iterate_collection(iterator, &sink_item);
- if (error) {
- TRACE_ERROR_NUMBER("Error iterating event:", error);
- col_unbind_iterator(iterator);
- return error;
- }
-
- /* Are we done ? */
- if (sink_item == NULL) break;
-
- /* Skip headers */
- if (col_get_item_type(sink_item) == COL_TYPE_COLLECTION) continue;
-
-
- /* Dereference the sink item to get context */
- sink_item = *((struct collection_item **)(col_get_item_data(sink_item)));
- ctx = *((struct elapi_sink_ctx **)(col_get_item_data(sink_item)));
-
- /* FIXME: Check the sink status */
-
- /* FIXME other parameters might be required... */
- error = elapi_sink_submit(ctx, event);
- if (error) {
- TRACE_ERROR_NUMBER("Error submitting event:", error);
- col_unbind_iterator(iterator);
- return error;
- }
-
- }
-
- col_unbind_iterator(iterator);
-
- TRACE_FLOW_STRING("elapi_tgt_submit", "Exit");
- return EOK;
-
-}
-
-
-/* If we failed to read configuration record this in the local file */
-void elapi_dump_ini_err(struct collection_item *error_list)
-{
- FILE *efile;
- char timestr[MAX_TIMESTR];
- time_t time_in_sec;
- struct tm *time_as_struct;
- struct tm time_data;
-
- TRACE_FLOW_STRING("elapi_dump_ini_err", "Entry point");
-
- efile = fopen(ELAPI_DEFAULT_ERROR_FILE, "a");
- if (efile == NULL) {
- TRACE_ERROR_STRING("No output available.", "Returning.");
- return;
- }
-
- time_in_sec = time(NULL);
- time_as_struct = localtime_r(&time_in_sec, &time_data);
-
- fprintf(efile, "\n\n%*s\n\n", 80, "=");
-
- if ((time_as_struct != NULL) &&
- (strftime(timestr, sizeof(timestr), E_TIMESTAMP_FORMAT, time_as_struct) == 0)) {
- fprintf(efile, "%s\n", timestr);
- }
- else {
- TRACE_FLOW_STRING("elapi_internal_dump_errors_to_file", "Was not able to process time.");
- }
-
- fprintf(efile, "\n");
- print_file_parsing_errors(efile, error_list);
-
- fclose(efile);
- TRACE_FLOW_STRING("elapi_dump_ini_err", "Exit");
-}
-
-/****************************************************************************/
-/* Functions below are added for debugging purposes */
-/****************************************************************************/
-#ifdef ELAPI_VERBOSE
-
-void elapi_print_sink_ctx(struct elapi_sink_ctx *sink_context)
-{
- /* This will not print well on 64 bit but it is just debugging
- * so it is OK to have it.
- */
- printf("Printing sink context using address %p\n", sink_context);
-
- printf("Mode: %s\n", sink_context->async_mode ? "true" : "false");
- if (sink_context->in_queue) col_print_collection(sink_context->in_queue);
- else printf("Queue is not initialized.\n");
-
- if (sink_context->pending) col_print_collection(sink_context->pending);
- else printf("Pending list is not initialized.\n");
-
- if (sink_context->sink_cfg.provider) printf("Provider: %s\n",
- sink_context->sink_cfg.provider);
- else printf("Provider is not defined.\n");
-
- printf("Is provider required? %s\n", ((sink_context->sink_cfg.required > 0) ? "Yes" : "No"));
- printf("On error: %s\n", ((sink_context->sink_cfg.onerror == 0) ? "retry" : "fail"));
- printf("Timout: %d\n", sink_context->sink_cfg.timeout);
- printf("Sync configuration: %s\n", sink_context->sink_cfg.synch ? "true" : "false");
-
- if (sink_context->sink_cfg.priv_ctx) printf("Private context allocated.\n");
- else printf("Private context is NULL.\n");
-
- if (sink_context->sink_cfg.libhandle) printf("Lib handle is allocated.\n");
- else printf("Lib handle is NULL.\n");
-
- if (sink_context->sink_cfg.ability) printf("Capability function is present\n");
- else printf("NO capability function.\n");
-
- if (sink_context->sink_cfg.cpb_cb.init_cb) printf("Init callback is OK.\n");
- else printf("Init callback is missing.\n");
-
- if (sink_context->sink_cfg.cpb_cb.submit_cb) printf("Submit callback is OK.\n");
- else printf("Submit callback is missing.\n");
-
- if (sink_context->sink_cfg.cpb_cb.close_cb) printf("Close callback is OK.\n");
- else printf("Close callback is missing.\n");
-
-
-}
-
-/* Handler for printing target internals */
-static int elapi_sink_ref_dbg_cb(const char *sink,
- int sink_len,
- int type,
- void *data,
- int length,
- void *passed_data,
- int *stop)
-{
- struct collection_item *sink_item;
- struct elapi_sink_ctx *sink_context;
-
- /* Skip header */
- if (type == COL_TYPE_COLLECTION) {
- return EOK;
- }
-
- sink_item = *((struct collection_item **)(data));
-
- printf("\nReferenced sink name is: %s\n", col_get_item_property(sink_item, NULL));
-
- sink_context = *((struct elapi_sink_ctx **)(col_get_item_data(sink_item)));
-
- elapi_print_sink_ctx(sink_context);
-
-
- return EOK;
-}
-
-/* Handler for printing sink internals */
-static int elapi_sink_dbg_cb(const char *sink,
- int sink_len,
- int type,
- void *data,
- int length,
- void *passed_data,
- int *stop)
-{
- struct elapi_sink_ctx *sink_context;
-
- /* Skip header */
- if (type == COL_TYPE_COLLECTION) {
- return EOK;
- }
-
- sink_context = *((struct elapi_sink_ctx **)(data));
-
- printf("\nSink name is: %s\n", sink);
-
- elapi_print_sink_ctx(sink_context);
-
- return EOK;
-}
-
-/* Handler for printing target internals */
-static int elapi_tgt_dbg_cb(const char *target,
- int target_len,
- int type,
- void *data,
- int length,
- void *passed_data,
- int *stop)
-{
- struct elapi_tgt_ctx *context;
-
- /* Skip header */
- if (type == COL_TYPE_COLLECTION) {
- return EOK;
- }
-
- context = *((struct elapi_tgt_ctx **)(data));
-
- printf("\nTarget value for target \"%s\" is %d\n", target, context->target_value);
- printf("\nReferenced sinks:\n\n");
-
- (void)col_traverse_collection(context->sink_ref_list,
- COL_TRAVERSE_ONELEVEL,
- elapi_sink_ref_dbg_cb,
- NULL);
-
- return EOK;
-}
-
-
-
-/* Internal function to print dispatcher internals - useful for testing */
-void elapi_print_dispatcher(struct elapi_dispatcher *handle)
-{
- char **current_target;
-
- printf("\nPRINTING DISPATCHER INTERNALS\n\n");
-
- printf("Application name: %s\n", handle->appname != NULL ? handle->appname : "(null)");
- printf("List of target names:\n");
-
- current_target = handle->targets;
- while (*current_target != NULL) {
- printf(" %s\n",*current_target);
- current_target++;
- }
-
- printf("Target counter: %d\n", handle->target_counter);
- printf("\n\nTarget collection:\n\n");
- if (handle->target_list) col_debug_collection(handle->target_list, COL_TRAVERSE_DEFAULT);
-
-
- printf("\n\nSink collection:\n\n");
- if (handle->sink_list) col_debug_collection(handle->sink_list, COL_TRAVERSE_DEFAULT);
- printf("\n\nConfig collection:\n\n");
- if (handle->ini_config) col_debug_collection(handle->ini_config, COL_TRAVERSE_DEFAULT);
- printf("\nDefault template:\n\n");
- if (handle->default_tpl) col_debug_collection(handle->default_tpl, COL_TRAVERSE_DEFAULT);
-
- printf("\n\nDeep target inspection:\n\n");
- if (handle->target_list) {
- (void)col_traverse_collection(handle->target_list,
- COL_TRAVERSE_ONELEVEL,
- elapi_tgt_dbg_cb,
- NULL);
- }
- printf("\n\nDeep sink inspection:\n\n");
- if (handle->sink_list) {
- (void)col_traverse_collection(handle->sink_list,
- COL_TRAVERSE_ONELEVEL,
- elapi_sink_dbg_cb,
- NULL);
- }
- /* FIXME: Async data... */
-
- printf("DISPATCHER END\n\n");
- fflush(stdout);
-}
-
-#endif