summaryrefslogtreecommitdiffstats
path: root/common/elapi/elapi_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/elapi/elapi_internal.c')
-rw-r--r--common/elapi/elapi_internal.c513
1 files changed, 446 insertions, 67 deletions
diff --git a/common/elapi/elapi_internal.c b/common/elapi/elapi_internal.c
index 2e93a355c..c5ec12474 100644
--- a/common/elapi/elapi_internal.c
+++ b/common/elapi/elapi_internal.c
@@ -20,6 +20,7 @@
#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"
@@ -38,7 +39,74 @@
*/
#define ELAPI_DEFAULT_ERROR_FILE "elapiconf.err"
-/* Handler for logging through the sinks */
+/* Handler for logging through the targets */
+int elapi_internal_target_handler(const char *target,
+ int target_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop)
+{
+ struct elapi_target_pass_in_data *target_data;
+ struct elapi_target_context *context;
+
+ TRACE_FLOW_STRING("elapi_internal_target_handler", "Entry.");
+
+ /* Skip header */
+ if (type == COL_TYPE_COLLECTION) {
+ TRACE_FLOW_STRING("elapi_internal_target_handler - skip header", "Exit.");
+ return EOK;
+ }
+
+ target_data = (struct elapi_target_pass_in_data *)(passed_data);
+ context = *((struct elapi_target_context **)(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);
+
+ /* FIXME THIS IS A PLACEHOLDER FUNCTION FOR NOW */
+
+ printf("\n\n\nPROCESSING EVENT:\n");
+ col_debug_collection(target_data->event, COL_TRAVERSE_DEFAULT);
+
+ TRACE_FLOW_STRING("elapi_internal_target_handler", "Exit.");
+ return EOK;
+}
+
+/* Internal target cleanup function */
+int elapi_internal_target_cleanup_handler(const char *target,
+ int target_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop)
+{
+ TRACE_FLOW_STRING("elapi_internal_target_cleanup_handler", "Entry.");
+
+ /* Skip header */
+ if (type == COL_TYPE_COLLECTION) {
+ TRACE_FLOW_STRING("elapi_internal_target_cleanup_handler - skip header", "Exit.");
+ return EOK;
+ }
+
+ elapi_internal_destroy_target(*((struct elapi_target_context **)(data)));
+
+ TRACE_FLOW_STRING("elapi_internal_target_cleanup_handler", "Exit.");
+ return EOK;
+}
+
+
+
int elapi_internal_sink_handler(const char *sink,
int sink_len,
int type,
@@ -47,18 +115,17 @@ int elapi_internal_sink_handler(const char *sink,
void *passed_data,
int *stop)
{
- struct elapi_sink_context *sink_env;
TRACE_FLOW_STRING("elapi_internal_sink_handler", "Entry.");
/* FIXME THIS IS A PLACEHOLDER FUNCTION FOR NOW */
- sink_env = (struct elapi_sink_context *)(passed_data);
-
+ /* Skip header */
if (type == COL_TYPE_COLLECTION) {
- printf("\n\n\nPROCESSING EVENT:\n");
- col_debug_collection(sink_env->event, COL_TRAVERSE_DEFAULT);
+ TRACE_FLOW_STRING("elapi_internal_sink_handler - skip header", "Exit.");
+ return EOK;
}
- else printf("Sink: %s\n", sink);
+
+ printf("Sink: %s\n", sink);
TRACE_FLOW_STRING("elapi_internal_sink_handler", "Exit.");
return EOK;
@@ -77,74 +144,268 @@ int elapi_internal_sink_cleanup_handler(const char *sink,
/* FIXME THIS IS A PLACEHOLDER FUNCTION FOR NOW */
- if (type != COL_TYPE_COLLECTION) printf("Cleaning Sink: %s\n", sink);
+ printf("Cleaning Sink: %s\n", sink);
TRACE_FLOW_STRING("elapi_internal_sink_cleanup_handler", "Exit.");
return EOK;
}
/* Function to add a sink to the collection */
-int elapi_internal_add_sink_to_collection(struct collection_item *sink_list,
- char *sink,
- char *appname)
+/* FIXME - other arguments might be added later */
+int elapi_internal_add_sink(struct collection_item **sink_ref,
+ char *sink,
+ struct elapi_dispatcher *handle)
{
int error = EOK;
- int found = 0;
- struct sink_descriptor sink_data;
-
- TRACE_FLOW_STRING("elapi_internal_add_sink_to_collection", "Entry");
- error = col_is_item_in_collection(sink_list,
- sink,
- COL_TYPE_ANY,
- COL_TRAVERSE_DEFAULT,
- &found);
+ struct elapi_sink_context sink_context;
+ struct collection_item *provider_cfg_item = NULL;
+
+ TRACE_FLOW_STRING("elapi_internal_add_sink", "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;
}
- /* Check if it was found */
- if (found) {
- TRACE_ERROR_NUMBER("Attempt to add an exiting sink.", "");
- return EINVAL;
+ if (!(*sink_ref)) {
+ TRACE_FLOW_STRING("No such sink yet, adding new sink:", sink);
+
+ /* First check if this sink is properly configured and get its provider */
+ error = get_config_item(sink,
+ ELAPI_SINK_PROVIDER,
+ handle->ini_config,
+ &provider_cfg_item);
+ if (error) {
+ TRACE_ERROR_NUMBER("Attempt to read provider attribute returned error", error);
+ return error;
+ }
+
+ /* Do we have provider? */
+ if (provider_cfg_item == NULL) {
+ /* There is no provider - return error */
+ TRACE_ERROR_STRING("Required key is missing in the configuration.", "Fatal Error!");
+ return ENOKEY;
+ }
+
+
+ /* FIXME: PLACEHOLDER
+ * This is the area where the actual sink is loaded.
+ * CODE WILL BE ADDED HERE...
+ */
+ sink_context.async_mode = 0;
+ sink_context.in_queue = NULL;
+ sink_context.pending = NULL;
+
+ /* 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_context),
+ sink_ref);
+ if (error != 0) {
+ TRACE_ERROR_NUMBER("Failed to add sink data as property", error);
+ return error;
+ }
}
- /* Save the pointer to application name into the sink's data block */
- sink_data.dblock.appname = appname;
- TRACE_INFO_STRING("add_sink_to_list - saving appname:", sink_data.dblock.appname);
+ TRACE_FLOW_NUMBER("elapi_internal_add_sink returning", error);
+ return error;
+}
+
+/* Destroy target object */
+void elapi_internal_destroy_target(struct elapi_target_context *context)
+{
+ TRACE_FLOW_STRING("elapi_internal_destroy_target", "Entry.");
- /* Try to load the sink library */
+ TRACE_INFO_NUMBER("Target address in cleanup:", context);
- /* FIXME - we need to have at least one sink implemented to enable this code.
- * It is a placeholder for now.
- error = load_sink(&sink_data, sink);
- if (error != 0) {
- DEBUG_NUMBER("Failed to load sink", error);
+ 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_internal_destroy_target", "Exit.");
+
+}
+
+/* Allocate target context and load sinks to it */
+int elapi_internal_create_target(struct elapi_target_context **context,
+ 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_target_context *target_context;
+ char **sinks;
+ char **current_sink;
+ struct collection_item *sink_ref;
+
+ TRACE_FLOW_STRING("elapi_internal_create_target", "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 ENOKEY;
+ }
+
+ /* Allocate context */
+ target_context = (struct elapi_target_context *)malloc(sizeof(struct elapi_target_context));
+ if (target_context == NULL) {
+ TRACE_ERROR_NUMBER("Memory allocation failed. Error", target_context);
+ return ENOMEM;
+ }
+
+ /* Initialize the allocatable items so that we can call destroy function
+ * in case of error.
+ * FIXME - add initialization here for other elements as they are added.
+ */
+
+ target_context->sink_ref_list = NULL;
- /* We got a valid sink so add it to the collection */
- error = col_add_binary_property(sink_list, NULL,
- sink, (void *)(&sink_data),
- sizeof(struct sink_descriptor));
+ /* 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_internal_destroy_target(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_internal_destroy_target(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 add sink data as property", error);
+ TRACE_ERROR_NUMBER("Failed to create sink collection. Error", error);
+ elapi_internal_destroy_target(target_context);
return error;
}
- TRACE_FLOW_NUMBER("elapi_internal_add_sink_to_collection returning", error);
- 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_internal_add_sink(&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_internal_destroy_target(target_context);
+ free_string_config_array(sinks);
+ return error;
+ }
+
+ /* 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_internal_destroy_target(target_context);
+ free_string_config_array(sinks);
+ return error;
+ }
+
+ current_sink++;
+ }
+
+ free_string_config_array(sinks);
+
+ *context = target_context;
+
+ TRACE_FLOW_STRING("elapi_internal_create_target", "Exit.");
+ return EOK;
}
-/* Function to create a list of sinks */
-int elapi_internal_construct_sink_list(struct elapi_dispatcher *handle)
+
+/* Function to create a list of targets */
+int elapi_internal_construct_target_list(struct elapi_dispatcher *handle)
{
int error = EOK;
- char **current_sink;
+ char **current_target;
+ struct elapi_target_context *context;
- TRACE_FLOW_STRING("elapi_internal_construct_sink_list", "Entry");
+
+ TRACE_FLOW_STRING("elapi_internal_construct_target_list", "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),
@@ -158,41 +419,53 @@ int elapi_internal_construct_sink_list(struct elapi_dispatcher *handle)
return error;
}
- current_sink = handle->sinks;
- handle->sink_counter = 0;
+ current_target = handle->targets;
+ handle->target_counter = 0;
- /* Add sinks as properties to the sink collection */
- while (*current_sink != NULL) {
+ /* Add targets as properties to the target collection */
+ while (*current_target != NULL) {
- TRACE_INFO_STRING("Current sink", *current_sink);
- TRACE_INFO_STRING("Will use appname:", handle->appname);
+ TRACE_INFO_STRING("Current target", *current_target);
- /* Load sink */
- error = elapi_internal_add_sink_to_collection(handle->sink_list,
- *current_sink,
- handle->appname);
- if ((error != 0) && (error != ELIBACC)) {
- TRACE_ERROR_NUMBER("Failed to add sink", error);
- /* No cleanup here. */
+ /* Allocate target context and load sinks to it */
+ context = NULL;
+ error = elapi_internal_create_target(&context,
+ *current_target,
+ handle);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create target", error);
return error;
}
- handle->sink_counter++;
- current_sink++;
+ 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_target_context *));
+ 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_internal_destroy_target(context);
+ return error;
+ }
+
+ handle->target_counter++;
+ current_target++;
}
- /* Check if we have any sinks available */
- if (handle->sink_counter == 0) {
- TRACE_ERROR_NUMBER("No sinks", ELIBACC);
- /* No cleanup here. */
- /* Return "Cannot access a needed shared library" */
- return ELIBACC;
+ /* Check if we have any targets available */
+ if (handle->target_counter == 0) {
+ TRACE_ERROR_STRING("No targets", "");
+ return ENOKEY;
}
- TRACE_FLOW_STRING("elapi_internal_construct_sink_list", "Returning success");
+ TRACE_FLOW_STRING("elapi_internal_construct_target_list", "Returning success");
return EOK;
}
+
+
/* If we failed to read configuration record this in the local file */
void elapi_internal_dump_errors_to_file(struct collection_item *error_list)
{
@@ -229,3 +502,109 @@ void elapi_internal_dump_errors_to_file(struct collection_item *error_list)
fclose(efile);
TRACE_FLOW_STRING("elapi_internal_dump_errors_to_file", "Exit");
}
+
+
+/* Handler for printing target internals */
+static int elapi_internal_sink_ref_debug_handler(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_context *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_context *)(col_get_item_data(sink_item));
+
+ 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");
+
+ return EOK;
+}
+
+
+
+/* Handler for printing target internals */
+static int elapi_internal_target_debug_handler(const char *target,
+ int target_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop)
+{
+ struct elapi_target_context *context;
+
+ /* Skip header */
+ if (type == COL_TYPE_COLLECTION) {
+ return EOK;
+ }
+
+ context = *((struct elapi_target_context **)(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_internal_sink_ref_debug_handler,
+ NULL);
+
+ return EOK;
+}
+
+
+/* Internal function to print dispatcher internals - useful for testing */
+void elapi_internal_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_template) col_debug_collection(handle->default_template, 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_internal_target_debug_handler,
+ NULL);
+ }
+ /* FIXME: Async data... */
+
+ printf("DISPATCHER END\n\n");
+}