summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2009-08-14 15:05:12 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-08-20 15:47:34 -0400
commitc7916d6b820bde690145450ba02209e741154866 (patch)
tree8fa39e9d28e8d1f384471540e58cdc280975c72e
parentb776f0af14866051ab9dcdb696345643424261d5 (diff)
downloadsssd-c7916d6b820bde690145450ba02209e741154866.tar.gz
sssd-c7916d6b820bde690145450ba02209e741154866.tar.xz
sssd-c7916d6b820bde690145450ba02209e741154866.zip
ELAPI: Adding concept of targets
The targets are the destinations which caller wants to send the events to. The sinks are now on the second level under targets and constitute a so called fail over chain for a target. Such approach eliminates the need for complex routing function. The dispatcher keeps the list of targets in a collection. The element in the collection is the target context. Also gispatcher keeps the list of the sinks in a separate collection. Each target context has a list of the sinks associated with this target. But those are just pointers (at least for now) to the sinks form the list kept by dispatcher. I had to add some internal debug callbacks to be able to see that all the internals of the dispatcher are actually in order. See the conttent of config file for more comments. Also see information posted on SSSD wiki. https://fedorahosted.org/sssd/wiki/WikiPage/ELAPIInterface
-rw-r--r--common/collection/collection.h3
-rw-r--r--common/elapi/Makefile.am7
-rw-r--r--common/elapi/configure.ac2
-rw-r--r--common/elapi/elapi_event.c2
-rw-r--r--common/elapi/elapi_event.h1
-rw-r--r--common/elapi/elapi_internal.c513
-rw-r--r--common/elapi/elapi_log.c159
-rw-r--r--common/elapi/elapi_log.h40
-rw-r--r--common/elapi/elapi_priv.h110
-rw-r--r--common/elapi/elapi_test/Makefile.am38
-rw-r--r--common/elapi/elapi_test/configure.ac26
-rw-r--r--common/elapi/elapi_test/elapi_ut.c (renamed from common/elapi/elapi_ut.c)57
-rw-r--r--common/elapi/elapi_test/elapi_ut.conf97
-rw-r--r--common/elapi/elapi_test/m4/.dir0
-rw-r--r--common/elapi/elapi_ut.conf6
15 files changed, 899 insertions, 162 deletions
diff --git a/common/collection/collection.h b/common/collection/collection.h
index 6868cb6e8..e9533a456 100644
--- a/common/collection/collection.h
+++ b/common/collection/collection.h
@@ -443,6 +443,9 @@ int col_get_item_and_do(struct collection_item *ci, /* A collection of items */
* while the pointer to its data is in use.
* Working with the internals of the collection item structure directly
* may cause problems in future if the internal implementation changes.
+ * The caller needs to be aware that function does not return
+ * error if item is not found. The caller needs to check if
+ * item is not NULL to determine whether something was found.
*/
int col_get_item(struct collection_item *ci, /* Collection to find things in */
const char *property_to_find, /* Name to match */
diff --git a/common/elapi/Makefile.am b/common/elapi/Makefile.am
index 922744291..2ebf9e833 100644
--- a/common/elapi/Makefile.am
+++ b/common/elapi/Makefile.am
@@ -4,6 +4,8 @@ DEFAULT_CONF_APP_DIR=@elapiconfappdir@
APP_NAME=@appname@
APP_NAME_SIZE=@appnamesize@
+SUBDIRS = elapi_test
+
topdir=$(srcdir)/..
AM_CFLAGS = -DELAPI_DEFAULT_CONFIG_DIR=\"$(DEFAULT_CONF_DIR)\" \
@@ -37,8 +39,3 @@ libelapi_la_SOURCES = \
elapi_log.h \
elapi_async.h \
elapi.h
-
-# Build unit test
-noinst_PROGRAMS = elapi_ut
-elapi_ut_SOURCES = elapi_ut.c
-elapi_ut_LDADD = libelapi.la ../ini/libini_config.la ../collection/libcollection.la
diff --git a/common/elapi/configure.ac b/common/elapi/configure.ac
index 2ebf0d086..a4db41915 100644
--- a/common/elapi/configure.ac
+++ b/common/elapi/configure.ac
@@ -28,5 +28,7 @@ WITH_CONFIG_APP_DIR
WITH_APP_NAME
WITH_APP_NAME_SIZE
+AC_CONFIG_SUBDIRS([elapi_test])
+
AC_CONFIG_FILES([Makefile elapi.pc])
AC_OUTPUT
diff --git a/common/elapi/elapi_event.c b/common/elapi/elapi_event.c
index 97cb2a13b..9ca2c7381 100644
--- a/common/elapi/elapi_event.c
+++ b/common/elapi/elapi_event.c
@@ -209,7 +209,7 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
TRACE_INFO_NUMBER("gai_ret_host:", gai_ret_host);
TRACE_INFO_STRING("host:", host);
TRACE_INFO_STRING("address:", address);
- TRACE_INFO_STRING("they are:", strncasecmp(host, address, sizeof(address)) == 0 ? "same" : "different");
+ TRACE_INFO_STRING("they are:", ((strcasecmp(host, address) != 0) ? "different" : "same"));
/* Do we have a host meaningful host name? */
if ((gai_ret_host != EOK) ||
diff --git a/common/elapi/elapi_event.h b/common/elapi/elapi_event.h
index f18333962..27c297b18 100644
--- a/common/elapi/elapi_event.h
+++ b/common/elapi/elapi_event.h
@@ -68,6 +68,7 @@
#define E_BASE_HOSTEXT ( E_HAVE_HOSTALIAS | E_HAVE_HOSTIPS )
#define E_BASE_DEFV1 ( E_BASE_TIME | E_BASE_HOST | E_BASE_APP | E_HAVE_SEVERITY )
+
/* The default time stamp format */
#define E_TIMESTAMP_FORMAT "%F"
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");
+}
diff --git a/common/elapi/elapi_log.c b/common/elapi/elapi_log.c
index 7c0d72abc..122506e5a 100644
--- a/common/elapi/elapi_log.c
+++ b/common/elapi/elapi_log.c
@@ -71,7 +71,8 @@ static int elapi_close_registered = 0;
/* Internal function to log message using args */
-static int elapi_dsp_msg_with_vargs(struct elapi_dispatcher *dispatcher,
+static int elapi_dsp_msg_with_vargs(uint32_t target,
+ struct elapi_dispatcher *dispatcher,
struct collection_item *template,
va_list args)
{
@@ -98,7 +99,7 @@ static int elapi_dsp_msg_with_vargs(struct elapi_dispatcher *dispatcher,
}
/* Now log event */
- error = elapi_dsp_log(dispatcher, event);
+ error = elapi_dsp_log(target, dispatcher, event);
/* Destroy event */
elapi_destroy_event(event);
@@ -150,10 +151,10 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
}
/* Check that all the async data is present */
- if (!add_fd_add_fn) prm_cnt++;
- if (!add_fd_rem_fn) prm_cnt++;
- if (!add_timer_fn) prm_cnt++;
- if (!callers_data) prm_cnt++;
+ if (add_fd_add_fn) prm_cnt++;
+ if (add_fd_rem_fn) prm_cnt++;
+ if (add_timer_fn) prm_cnt++;
+ if (callers_data) prm_cnt++;
if ((prm_cnt > 0) && (prm_cnt < 4)) {
/* We got a mixture of NULLs and not NULLs.
@@ -213,10 +214,10 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
*/
memset(handle, 0, sizeof(struct elapi_dispatcher *));
handle->ini_config = NULL;
+ handle->target_list = NULL;
handle->sink_list = NULL;
- handle->sinks = NULL;
+ handle->targets = NULL;
handle->default_template = NULL;
- handle->need_to_free = 0;
/* Save application name in the handle */
if (appname != NULL) handle->appname = strdup(appname);
@@ -248,12 +249,13 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
}
return error;
}
+
/* Have to clean error set anyways */
free_ini_config_errors(error_set);
- /* Get sink list from configuration */
+ /* Get target list from configuration */
error = get_config_item(ELAPI_DISPATCHER,
- ELAPI_SINKS,
+ ELAPI_TARGETS,
handle->ini_config,
&item);
if (error) {
@@ -262,14 +264,23 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
return error;
}
- if (!item) {
- /* There is no list of sinks - use default list */
- handle->sinks = default_sinks;
+ /* 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 ENOKEY;
}
- else {
- /* Get one from config but make sure we free it later */
- handle->sinks = get_string_config_array(item, NULL, NULL, NULL);
- handle->need_to_free = 1;
+
+ /* 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_internal_construct_target_list(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 */
@@ -282,14 +293,6 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
handle->async_mode = 1;
}
- /* Create the list of sinks */
- error = elapi_internal_construct_sink_list(handle);
- if (error != EOK) {
- TRACE_ERROR_NUMBER("Failed to create sink list. Error", error);
- elapi_destroy_dispatcher(handle);
- return error;
- }
-
*dispatcher = handle;
TRACE_FLOW_STRING("elapi_create_dispatcher_adv", "Returning Success.");
@@ -328,19 +331,34 @@ void elapi_destroy_dispatcher(struct elapi_dispatcher *dispatcher)
if (dispatcher) {
TRACE_INFO_STRING("Deleting template if any...", "");
col_destroy_collection(dispatcher->default_template);
- TRACE_INFO_STRING("Closing sink handler.", "");
- (void)col_traverse_collection(dispatcher->sink_list,
- COL_TRAVERSE_ONELEVEL,
- elapi_internal_sink_cleanup_handler,
- NULL);
- TRACE_INFO_STRING("Deleting sink list.", "");
- col_destroy_collection(dispatcher->sink_list);
+
+ if (dispatcher->target_list) {
+ TRACE_INFO_STRING("Closing target list.", "");
+ (void)col_traverse_collection(dispatcher->target_list,
+ COL_TRAVERSE_ONELEVEL,
+ elapi_internal_target_cleanup_handler,
+ 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_internal_sink_cleanup_handler,
+ 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 config.", "");
free_ini_config(dispatcher->ini_config);
- TRACE_INFO_STRING("Deleting sink name array.", "");
- if (dispatcher->need_to_free) free_string_config_array(dispatcher->sinks);
+ TRACE_INFO_STRING("Deleting targets name array.", "");
+ free_string_config_array(dispatcher->targets);
TRACE_INFO_STRING("Freeing dispatcher.", "");
free(dispatcher);
}
@@ -349,10 +367,12 @@ void elapi_destroy_dispatcher(struct elapi_dispatcher *dispatcher)
}
/* Function to log an event */
-int elapi_dsp_log(struct elapi_dispatcher *dispatcher, struct collection_item *event)
+int elapi_dsp_log(uint32_t target,
+ struct elapi_dispatcher *dispatcher,
+ struct collection_item *event)
{
int error = EOK;
- struct elapi_sink_context sink_env;
+ struct elapi_target_pass_in_data target_data;
TRACE_FLOW_STRING("elapi_dsp_log", "Entry");
@@ -362,14 +382,18 @@ int elapi_dsp_log(struct elapi_dispatcher *dispatcher, struct collection_item *e
return EINVAL;
}
- sink_env.handle = dispatcher;
- sink_env.event = event;
+ /* Wrap parameters into one argument and pass on */
+ target_data.handle = dispatcher;
+ target_data.event = event;
+ target_data.target_mask = target;
+
+ TRACE_INFO_NUMBER("Target mask is:", target_data.target_mask);
- /* Logging an event is just iterating through the sinks and calling the sink_handler */
- error = col_traverse_collection(dispatcher->sink_list,
+ /* Logging an event is just iterating through the targets and calling the sink_handler */
+ error = col_traverse_collection(dispatcher->target_list,
COL_TRAVERSE_ONELEVEL,
- elapi_internal_sink_handler,
- (void *)(&sink_env));
+ elapi_internal_target_handler,
+ (void *)(&target_data));
TRACE_FLOW_NUMBER("elapi_dsp_log Exit. Returning", error);
return error;
@@ -384,7 +408,13 @@ int elapi_set_default_template(unsigned base, ...)
TRACE_FLOW_STRING("elapi_set_default_template", "Entry");
- if (global_dispatcher == NULL) elapi_init(NULL, NULL);
+ 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_template(global_dispatcher->default_template);
@@ -436,7 +466,8 @@ int elapi_get_default_template(struct collection_item **template)
/* Function to log raw key value pairs without creating an event */
-int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
+int elapi_dsp_msg(uint32_t target,
+ struct elapi_dispatcher *dispatcher,
struct collection_item *template,
...)
{
@@ -447,7 +478,7 @@ int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
va_start(args, template);
- error = elapi_dsp_msg_with_vargs(dispatcher, template, args);
+ error = elapi_dsp_msg_with_vargs(target, dispatcher, template, args);
va_end(args);
@@ -459,6 +490,7 @@ int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
/* Managing the sink collection */
int elapi_alter_dispatcher(struct elapi_dispatcher *dispatcher,
+ const char *target,
const char *sink,
int action)
{
@@ -468,7 +500,7 @@ int elapi_alter_dispatcher(struct elapi_dispatcher *dispatcher,
}
/* Get sink list */
-char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher)
+char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher, char *target)
{
/* FIXME: FUNCTION IS NOT IMPLEMENTED YET */
@@ -483,6 +515,22 @@ void elapi_free_sink_list(char **sink_list)
}
+/* 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. */
@@ -536,7 +584,7 @@ int elapi_create_simple_event(struct collection_item **event, ...)
}
/* Log key value pairs */
-int elapi_msg(struct collection_item *template, ...)
+int elapi_msg(uint32_t target, struct collection_item *template, ...)
{
int error = EOK;
va_list args;
@@ -556,7 +604,10 @@ int elapi_msg(struct collection_item *template, ...)
va_start(args, template);
- error = elapi_dsp_msg_with_vargs(global_dispatcher, use_template, args);
+ error = elapi_dsp_msg_with_vargs(target,
+ global_dispatcher,
+ use_template,
+ args);
va_end(args);
@@ -565,15 +616,21 @@ int elapi_msg(struct collection_item *template, ...)
}
/* Log event */
-int elapi_log(struct collection_item *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) elapi_init(NULL, NULL);
- error = elapi_dsp_log(global_dispatcher, event);
+ 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;
diff --git a/common/elapi/elapi_log.h b/common/elapi/elapi_log.h
index 6fff82b64..7d8a3b7d2 100644
--- a/common/elapi/elapi_log.h
+++ b/common/elapi/elapi_log.h
@@ -20,8 +20,18 @@
#ifndef ELAPI_LOG_H
#define ELAPI_LOG_H
+#include <stdint.h>
+
#include "elapi_async.h"
+/* Default values for targets -
+ * these constants match values in the default configuration.
+ */
+#define E_TARGET_DEBUG 0x00000001
+#define E_TARGET_AUDIT 0x00000002
+#define E_TARGET_LOG 0x00000004
+
+
/* Opaque dispatcher structure */
struct elapi_dispatcher;
@@ -51,10 +61,13 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher, /* Handle
void elapi_destroy_dispatcher(struct elapi_dispatcher *dispatcher);
/* Function to log an event */
-int elapi_dsp_log(struct elapi_dispatcher *dispatcher, struct collection_item *event);
+int elapi_dsp_log(uint32_t target,
+ struct elapi_dispatcher *dispatcher,
+ struct collection_item *event);
/* Function to log raw key value pairs without creating an event */
-int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
+int elapi_dsp_msg(uint32_t target,
+ struct elapi_dispatcher *dispatcher,
struct collection_item *template,
...);
@@ -62,11 +75,18 @@ int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
/* Managing the sink collection */
int elapi_alter_dispatcher(struct elapi_dispatcher *dispatcher, /* Dispatcher */
+ const char *target, /* Target to look for */
const char *sink, /* Sink to change */
int action); /* Action to perform for sink */
+/* Get target list */
+char **elapi_get_target_list(struct elapi_dispatcher *dispatcher);
+
+/* Free target list */
+void elapi_free_target_list(char **target_list);
+
/* Get sink list */
-char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher);
+char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher, char *target);
/* Free sink list */
void elapi_free_sink_list(char **sink_list);
@@ -102,13 +122,19 @@ void elapi_free_sink_list(char **sink_list);
int elapi_init(const char *appname, const char *config_path);
/* Log key value pairs */
-int elapi_msg(struct collection_item *template, ...);
-
+int elapi_msg(uint32_t target,
+ struct collection_item *template, ...);
/* Log event */
-int elapi_log(struct collection_item *event);
+int elapi_log(uint32_t target,
+ struct collection_item *event);
+
+/* Corresponding wrapping macroses */
+#define ELAPI_EVT_DEBUG(event) elapi_log(E_TARGET_DEBUG, event)
+#define ELAPI_EVT_LOG(event) elapi_log(E_TARGET_LOG, event)
+#define ELAPI_EVT_AUDIT(event) elapi_log(E_TARGET_AUDIT, event)
-/* Get dispatcher if you want to add sink to a default dispatcher or do some advanced operations */
+/* Get dispatcher if you want to do some advanced operations */
struct elapi_dispatcher *elapi_get_dispatcher(void);
/* Close audit */
diff --git a/common/elapi/elapi_priv.h b/common/elapi/elapi_priv.h
index c536f4ecf..0fa01b406 100644
--- a/common/elapi/elapi_priv.h
+++ b/common/elapi/elapi_priv.h
@@ -20,6 +20,8 @@
#ifndef ELAPI_PRIV_H
#define ELAPI_PRIV_H
+#include <stdint.h>
+
#include "collection.h"
#include "elapi_async.h"
/* Classes of the collections used by ELAPI internally */
@@ -27,22 +29,37 @@
#define COL_CLASS_ELAPI_EVENT COL_CLASS_ELAPI_BASE + 0
#define COL_CLASS_ELAPI_TEMPLATE COL_CLASS_ELAPI_BASE + 1
#define COL_CLASS_ELAPI_SINK COL_CLASS_ELAPI_BASE + 2
+#define COL_CLASS_ELAPI_TARGET COL_CLASS_ELAPI_BASE + 3
+#define COL_CLASS_ELAPI_SINK_REF COL_CLASS_ELAPI_BASE + 4
/* Names for the collections */
#define E_TEMPLATE_NAME "template"
#define E_EVENT_NAME "event"
-
+/* Constants used in INI file and in
+ * the internal collection objects.
+ */
#define ELAPI_DISPATCHER "dispatcher"
#define ELAPI_SINKS "sinks"
+#define ELAPI_TARGETS "targets"
+#define ELAPI_SINK_REFS "srefs"
+#define ELAPI_TARGET_VALUE "value"
+#define ELAPI_SINK_PROVIDER "provider"
+
+#define ELAPI_TARGET_ALL 0xFFFF /* 65k targets should be enough */
struct elapi_dispatcher {
- char **sinks;
- int need_to_free;
+ /* Application name */
char *appname;
- /*event_router_fn router; - FIXME - not defined yet */
+ /* List of target names and chars */
+ char **targets;
+ /* Collection of targets */
+ struct collection_item *target_list;
+ /* Counter of the targets */
+ int target_counter;
+ /* Collection of sinks */
struct collection_item *sink_list;
- int sink_counter;
+ /* Configuration */
struct collection_item *ini_config;
/* Default event template */
struct collection_item *default_template;
@@ -51,16 +68,47 @@ struct elapi_dispatcher {
elapi_rem_fd add_fd_rem_fn;
elapi_add_timer add_timer_fn;
void *callers_data;
- int async_mode;
+ uint32_t async_mode;
};
-/* Structure to pass data from logging function to sinks */
-struct elapi_sink_context {
+/* Structure to pass data from logging function to targets */
+struct elapi_target_pass_in_data {
struct collection_item *event;
struct elapi_dispatcher *handle;
- char *format;
- char *previous;
- int previous_status;
+ uint32_t target_mask;
+};
+
+/* This is a structure that holds the information
+ * about the target.
+ */
+struct elapi_target_context {
+ /* Value associted with the
+ * target in the config file.
+ */
+ uint32_t target_value;
+ /* Collection of pointers to sink objects */
+ struct collection_item *sink_ref_list;
+ /* FIXME - other things that belong here are:
+ * state of the chain
+ * reference to the current sink
+ * reference to the preferred sink
+ * etc.
+ */
+};
+
+/* The structure that describes the sink in the dispatcher */
+struct elapi_sink_context {
+ /* Inpit queue of a sink */
+ struct collection_item *in_queue;
+ /* Pending list */
+ struct collection_item *pending;
+ /* FIXME: add:
+ * sink's error status
+ * sink's common config data (common between all sinks)
+ * sink personal specific config data (config data specific to this sink)
+ */
+ /* Is this a sink or async sink */
+ uint32_t async_mode;
};
/* The structure to hold a command and a result of the command execution */
@@ -102,13 +150,45 @@ int elapi_internal_sink_cleanup_handler(const char *sink,
/* Create list of the sinks */
int elapi_internal_construct_sink_list(struct elapi_dispatcher *handle);
-/* Function to add a sink to the collection */
-int elapi_internal_add_sink_to_collection(struct collection_item *sink_list,
- char *sink,
- char *appname);
+/* Function to add a sink based on configuration */
+int elapi_internal_add_sink(struct collection_item **sink_ref,
+ char *sink,
+ struct elapi_dispatcher *handle);
+
+/* Create target object */
+int elapi_internal_create_target(struct elapi_target_context **context,
+ char *target,
+ struct elapi_dispatcher *handle);
+
+/* Destroy target object */
+void elapi_internal_destroy_target(struct elapi_target_context *context);
+
+/* Internal target cleanup function */
+int elapi_internal_target_cleanup_handler(const char *sink,
+ int sink_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop);
+
+/* 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);
+
+/* Create list of targets for a dispatcher */
+int elapi_internal_construct_target_list(struct elapi_dispatcher *handle);
/* Send ELAPI config errors into a file */
void elapi_internal_dump_errors_to_file(struct collection_item *error_list);
+/* Print dispatcher internals for testing and debugin purposes */
+void elapi_internal_print_dispatcher(struct elapi_dispatcher *handle);
+
#endif
diff --git a/common/elapi/elapi_test/Makefile.am b/common/elapi/elapi_test/Makefile.am
new file mode 100644
index 000000000..b16102c83
--- /dev/null
+++ b/common/elapi/elapi_test/Makefile.am
@@ -0,0 +1,38 @@
+TRACE_LEVEL=@TRACE_VAR@
+
+topdir=$(srcdir)/../..
+
+AM_CFLAGS = -DELAPI_DEFAULT_CONFIG_DIR=\"$(srcdir)\" \
+ -DELAPI_DEFAULT_CONFIG_APP_DIR=\"$(srcdir)\" \
+ -DELAPI_DEFAULT_APP_NAME=\"elapi_ut\" \
+ -DELAPI_DEFAULT_APP_NAME_SIZE=127
+
+if HAVE_GCC
+ AM_CFLAGS += \
+ -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual \
+ -Wcast-align -Wwrite-strings
+endif
+
+AM_CPPFLAGS = -I$(topdir) -I$(topdir)/ini -I$(topdir)/trace -I$(topdir)/collection -I$(topdir)/elapi $(TRACE_LEVEL)
+
+ACLOCAL_AMFLAGS = -I m4
+
+# Build library
+noinst_LTLIBRARIES = libelapi_test.la
+libelapi_test_la_SOURCES = \
+ ../elapi_event.c \
+ ../elapi_log.c \
+ ../elapi_internal.c \
+ ../elapi_event.h \
+ ../elapi_priv.h \
+ ../elapi_sink.h \
+ ../elapi_log.h \
+ ../elapi_async.h \
+ ../elapi.h
+
+# Build unit test
+check_PROGRAMS = elapi_ut
+elapi_ut_SOURCES = elapi_ut.c
+elapi_ut_LDADD = libelapi_test.la ../../ini/libini_config.la ../../collection/libcollection.la
+
+TESTS = elapi_ut
diff --git a/common/elapi/elapi_test/configure.ac b/common/elapi/elapi_test/configure.ac
new file mode 100644
index 000000000..f2431bd38
--- /dev/null
+++ b/common/elapi/elapi_test/configure.ac
@@ -0,0 +1,26 @@
+AC_INIT([elapi],[0.0.1],[freeipa-devel@redhat.com])
+AC_CONFIG_SRCDIR([elapi_ut.c])
+AC_CONFIG_AUX_DIR([build])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_PROG_CC
+AC_PROG_LIBTOOL
+AC_CONFIG_MACRO_DIR([m4])
+AC_PROG_INSTALL
+
+AM_CONDITIONAL([HAVE_GCC], [test "$ac_cv_prog_gcc" = yes])
+
+m4_pattern_allow([AM_SILENT_RULES])
+AM_SILENT_RULES
+
+AC_CONFIG_HEADERS([config.h])
+
+# Enable trace build
+AC_ARG_ENABLE([trace],
+ [AS_HELP_STRING([--enable-trace[=LEVEL]],[build with low level tracing enabled])],
+ [trace_level="$enableval"],
+ [trace_level="0"])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])])
+
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/common/elapi/elapi_ut.c b/common/elapi/elapi_test/elapi_ut.c
index 2866411f6..ed4342212 100644
--- a/common/elapi/elapi_ut.c
+++ b/common/elapi/elapi_test/elapi_ut.c
@@ -18,11 +18,15 @@
*/
#include <stdio.h>
+#include <stdarg.h>
#define TRACE_HOME
#include "trace.h"
#include "elapi.h"
#include "collection_tools.h"
+/* THIS IS A PRIVATE HEADER - included for debugging purposes only! */
+#include "elapi_priv.h"
+
int simple_event_test(void)
{
int error = 0;
@@ -64,25 +68,55 @@ int simple_event_test(void)
E_EOARG);
if (error) {
- printf("Failed to set create event! %d\n", error);
+ printf("Failed to create simple event! %d\n", error);
+ return error;
+ }
+
+ error = ELAPI_EVT_DEBUG(event);
+ if (error) {
+ printf("Failed to log event to debug ! %d\n", error);
+ elapi_destroy_event(event);
return error;
}
- error = elapi_log(event);
+ error = ELAPI_EVT_LOG(event);
+ if (error) {
+ printf("Failed to log event to log ! %d\n", error);
+ elapi_destroy_event(event);
+ return error;
+ }
+
+ error = ELAPI_EVT_AUDIT(event);
+
+ if (error) {
+ printf("Failed to log event to audit ! %d\n", error);
+ elapi_destroy_event(event);
+ return error;
+ }
elapi_destroy_event(event);
+ error = elapi_msg(E_TARGET_DEBUG, NULL, "a", "b", "c", "d", E_EOARG);
if (error) {
- printf("Failed to log event! %d\n", error);
+ printf("Failed to log \"debug\" event! %d\n", error);
return error;
}
- error = elapi_msg(NULL, "a", "b", "c", "d", E_EOARG);
+ error = elapi_msg(E_TARGET_LOG, NULL, "a", "b", "c", "d", E_EOARG);
if (error) {
- printf("Failed to log event! %d\n", error);
+ printf("Failed to log \"log\" event! %d\n", error);
return error;
}
+ error = elapi_msg(E_TARGET_AUDIT, NULL, "a", "b", "c", "d", E_EOARG);
+ if (error) {
+ printf("Failed to log \"audit\" event! %d\n", error);
+ return error;
+ }
+
+ /* Internal function to print dispatcher guts */
+ elapi_internal_print_dispatcher(elapi_get_dispatcher());
+
printf("Simple test success!\n");
return error;
@@ -137,7 +171,7 @@ int complex_event_test(void)
col_debug_collection(template, COL_TRAVERSE_FLAT);
col_debug_collection(event, COL_TRAVERSE_FLAT);
- error = elapi_log(event);
+ error = elapi_log(E_TARGET_DEBUG, event);
elapi_destroy_event(event);
@@ -245,7 +279,7 @@ int complex_event_test(void)
return error;
}
- error = elapi_dsp_log(dispatcher, event);
+ error = elapi_dsp_log(E_TARGET_DEBUG, dispatcher, event);
elapi_destroy_event(event);
@@ -256,7 +290,7 @@ int complex_event_test(void)
return error;
}
- error = elapi_dsp_log(dispatcher, event_copy);
+ error = elapi_dsp_log(E_TARGET_DEBUG, dispatcher, event_copy);
elapi_destroy_event(event_copy);
@@ -266,14 +300,14 @@ int complex_event_test(void)
return error;
}
- error = elapi_dsp_msg(dispatcher, template, "a", "b", "c", "d", E_EOARG);
+ error = elapi_dsp_msg(E_TARGET_DEBUG, dispatcher, template, "a", "b", "c", "d", E_EOARG);
if (error) {
elapi_destroy_event_template(template);
printf("Failed to log event! %d\n", error);
return error;
}
- error = elapi_dsp_msg(dispatcher, NULL, "a", "b", "c", "d", E_EOARG);
+ error = elapi_dsp_msg(E_TARGET_DEBUG, dispatcher, NULL, "a", "b", "c", "d", E_EOARG);
if (error) {
elapi_destroy_event_template(template);
printf("Failed to log event! %d\n", error);
@@ -281,6 +315,9 @@ int complex_event_test(void)
}
elapi_destroy_event_template(template);
+
+ elapi_internal_print_dispatcher(dispatcher);
+
elapi_destroy_dispatcher(dispatcher);
return error;
diff --git a/common/elapi/elapi_test/elapi_ut.conf b/common/elapi/elapi_test/elapi_ut.conf
new file mode 100644
index 000000000..d15a4550d
--- /dev/null
+++ b/common/elapi/elapi_test/elapi_ut.conf
@@ -0,0 +1,97 @@
+; This is a sample configuration file for ELAPI
+
+; The dispatcher section defines general configuration
+; for the ELAPI. It has following configuration parameters:
+;
+; targets - (required)
+; Defines possible logical destinations where message can be sent.
+; It is one of the arguments of the calling interface. It is numeric.
+; It is done this way for performance reasons so it is faster to compare.
+; But in the configuration it is easier to deal with targets as strings.
+; To overcome this issue each target is assigned a number in the INI file.
+; The ELAPI convention is to have three default targets:
+; "debug", "audit" and "log" but application developers can add others as needed.
+; The default value for debug target is 1, for audit 2 and log is 4.
+; Changing the value defined for debug to be 7 ( logical OR of 1, 2 and 4)
+; will result in all messages sent into debug log.
+; This might be convenient during troubleshooting and would allow seeing all
+; events emitted by the application in one place.
+; If you want the event to be sent into two targets at the same time
+; add a target with different name but same value.
+; For example if the log events need to go to local and remote files
+; in parallel you would create another target: logremote
+; and give it same value as log (which by convention is 4)
+
+
+
+[dispatcher]
+targets=debug, audit, log
+
+; Inside section for each target the following parameters can be defined:
+;
+; value - (optional)
+; Stores the value associated with this target.
+; If the bit-wise AND of this value and the value provided by caller
+; of the interface is greater than 0 the event is logged into the
+; target destination. If omitted all events are sent to this target.
+; sinks - (required)
+; Defines the list of the sink names that need to be loaded
+; each will have its own section.
+; Only one of the sinks is active - first in the list.
+; The list contains sinks in the fail over order.
+;
+
+[debug]
+value = 1
+sinks = debugfile, stderr
+
+[audit]
+value = 2
+sinks = auditfile, syslog
+
+[log]
+value = 4
+sinks = logfile, syslog
+
+; Each sink needs to have it's own section.
+;
+; COMMON FOR EVERY SINK
+;
+; provider - (required)
+; Defines the name of the sink or the special reserved word to
+; indecate that it is a sink provided natively by ELAPI library.
+;
+; Special sinks provided natively by ELAPI are:
+; file
+; stderr
+; syslog
+;
+; Example:
+; provider=file
+;
+; this would mean the destination for this sink is a file.
+;
+; If the sink is provided as an external plugin
+; the syntax should be the following:
+;
+; provider=custom_audit
+;
+; In this case the ELAPI will try to load shared library with the name
+; constructed using specified value. In the given example
+; ELAPI will try to load libelapi_sink_custom_audit.so library.
+; The general pattern is: libelapi_sink_<source>.so
+
+[debugfile]
+provider=file
+
+[logfile]
+provider=file
+
+[auditfile]
+provider=file
+
+[stderr]
+provider=stderr
+
+[syslog]
+provider=syslog
diff --git a/common/elapi/elapi_test/m4/.dir b/common/elapi/elapi_test/m4/.dir
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/common/elapi/elapi_test/m4/.dir
diff --git a/common/elapi/elapi_ut.conf b/common/elapi/elapi_ut.conf
deleted file mode 100644
index 19cbeb719..000000000
--- a/common/elapi/elapi_ut.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-[dispatcher]
-sinks = foo, bar, baz
-
-
-
-; test