summaryrefslogtreecommitdiff
path: root/common/elapi
diff options
context:
space:
mode:
Diffstat (limited to 'common/elapi')
-rw-r--r--common/elapi/Makefile.am19
-rw-r--r--common/elapi/conf_macros.m456
-rw-r--r--common/elapi/configure.ac6
-rw-r--r--common/elapi/elapi.h1
-rw-r--r--common/elapi/elapi_async.h72
-rw-r--r--common/elapi/elapi_event.c363
-rw-r--r--common/elapi/elapi_event.h40
-rw-r--r--common/elapi/elapi_internal.c231
-rw-r--r--common/elapi/elapi_log.c631
-rw-r--r--common/elapi/elapi_log.h117
-rw-r--r--common/elapi/elapi_priv.h82
-rw-r--r--common/elapi/elapi_sink.h78
-rw-r--r--common/elapi/elapi_ut.c83
-rw-r--r--common/elapi/elapi_ut.conf6
14 files changed, 1522 insertions, 263 deletions
diff --git a/common/elapi/Makefile.am b/common/elapi/Makefile.am
index 49c9b518..92274429 100644
--- a/common/elapi/Makefile.am
+++ b/common/elapi/Makefile.am
@@ -1,15 +1,23 @@
TRACE_LEVEL=@TRACE_VAR@
+DEFAULT_CONF_DIR=@elapiconfdir@
+DEFAULT_CONF_APP_DIR=@elapiconfappdir@
+APP_NAME=@appname@
+APP_NAME_SIZE=@appnamesize@
topdir=$(srcdir)/..
-AM_CFLAGS =
+AM_CFLAGS = -DELAPI_DEFAULT_CONFIG_DIR=\"$(DEFAULT_CONF_DIR)\" \
+ -DELAPI_DEFAULT_CONFIG_APP_DIR=\"$(DEFAULT_CONF_APP_DIR)\" \
+ -DELAPI_DEFAULT_APP_NAME=\"$(APP_NAME)\" \
+ -DELAPI_DEFAULT_APP_NAME_SIZE=$(APP_NAME_SIZE)
+
if HAVE_GCC
AM_CFLAGS += \
-Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual \
-Wcast-align -Wwrite-strings
endif
-AM_CPPFLAGS = -I$(topdir) -I$(topdir)/trace -I$(topdir)/collection $(TRACE_LEVEL)
+AM_CPPFLAGS = -I$(topdir) -I$(topdir)/ini -I$(topdir)/trace -I$(topdir)/collection $(TRACE_LEVEL)
ACLOCAL_AMFLAGS = -I m4
@@ -21,11 +29,16 @@ dist_noinst_DATA = elapi.pc
noinst_LTLIBRARIES = libelapi.la
libelapi_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
noinst_PROGRAMS = elapi_ut
elapi_ut_SOURCES = elapi_ut.c
-elapi_ut_LDADD = ../collection/libcollection.la libelapi.la
+elapi_ut_LDADD = libelapi.la ../ini/libini_config.la ../collection/libcollection.la
diff --git a/common/elapi/conf_macros.m4 b/common/elapi/conf_macros.m4
new file mode 100644
index 00000000..e20dfdba
--- /dev/null
+++ b/common/elapi/conf_macros.m4
@@ -0,0 +1,56 @@
+
+AC_DEFUN([WITH_CONFIG_DIR],
+ [ AC_ARG_WITH([config-dir],
+ [AC_HELP_STRING([--with-config-dir=DIR],
+ [The name of the default ELAPI config directory [SYSCONFDIR/elapi]]
+ )
+ ]
+ )
+ elapiconfdir="$sysconfdir/elapi"
+ if test x"$with_config_dir" != x; then
+ elapiconfdir=$with_config_dir
+ fi
+ AC_SUBST(elapiconfdir)
+ ])
+
+AC_DEFUN([WITH_CONFIG_APP_DIR],
+ [ AC_ARG_WITH([config-app-dir],
+ [AC_HELP_STRING([--with-config-app-dir=DIR],
+ [The name of the ELAPI application config directory [SYSCONFDIR/elapi/apps.d]]
+ )
+ ]
+ )
+ elapiconfappdir="$sysconfdir/elapi/apps.d"
+ if test x"$with_config_app_dir" != x; then
+ elapiconfappdir=$with_config_app_dir
+ fi
+ AC_SUBST(elapiconfappdir)
+ ])
+
+AC_DEFUN([WITH_APP_NAME],
+ [ AC_ARG_WITH([app-name],
+ [AC_HELP_STRING([--with-app-name=<name>],
+ [The name of the default ELAPI application [default]]
+ )
+ ]
+ )
+ appname="default"
+ if test x"$with_app_name" != x; then
+ appname=$with_app_name
+ fi
+ AC_SUBST(appname)
+ ])
+
+AC_DEFUN([WITH_APP_NAME_SIZE],
+ [ AC_ARG_WITH([app-name-size],
+ [AC_HELP_STRING([--with-app-name-size=<size>],
+ [The maximum size of the name for an ELAPI application [127]]
+ )
+ ]
+ )
+ appnamesize="127"
+ if test x"$with_app_name_size" != x; then
+ appnamesize=$with_app_name_size
+ fi
+ AC_SUBST(appnamesize)
+ ])
diff --git a/common/elapi/configure.ac b/common/elapi/configure.ac
index e5c19ae7..2ebf0d08 100644
--- a/common/elapi/configure.ac
+++ b/common/elapi/configure.ac
@@ -21,6 +21,12 @@ AC_ARG_ENABLE([trace],
[trace_level="0"])
AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])])
+m4_include(conf_macros.m4)
+
+WITH_CONFIG_DIR
+WITH_CONFIG_APP_DIR
+WITH_APP_NAME
+WITH_APP_NAME_SIZE
AC_CONFIG_FILES([Makefile elapi.pc])
AC_OUTPUT
diff --git a/common/elapi/elapi.h b/common/elapi/elapi.h
index d4e9da4e..21f68d3f 100644
--- a/common/elapi/elapi.h
+++ b/common/elapi/elapi.h
@@ -21,5 +21,6 @@
#define ELAPI_H
#include "elapi_event.h"
+#include "elapi_log.h"
#endif
diff --git a/common/elapi/elapi_async.h b/common/elapi/elapi_async.h
new file mode 100644
index 00000000..24cb7f8b
--- /dev/null
+++ b/common/elapi/elapi_async.h
@@ -0,0 +1,72 @@
+/*
+ ELAPI
+
+ Header file for the ELAPI async processing 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/>.
+*/
+
+#ifndef ELAPI_ASYNC_H
+#define ELAPI_ASYNC_H
+
+#include <sys/time.h>
+
+/* Signature ELAPI callback function that
+ * should be called when the event loop got an event on the
+ * socket or file descriptor.
+ * ELAPI will always try to write to sockets in async way
+ * if the sink has this capability.
+ * So this is the callback that will always be
+ * invoked when we get ACK from the process receiving events.
+ */
+typedef int (*elapi_fd_callback)(int fd, /* File descriptor */
+ void *elapi_data); /* ELAPI supplied data */
+
+/* Signature ELAPI callback function that
+ * should be called when the event loop got a timer driven event.
+ */
+typedef int (*elapi_timer_callback)(void *elapi_data); /* ELAPI supplied data */
+
+/* Signature of the supplied by caller function that ELAPI
+ * will call to add the fd into the application event processing loop.
+ */
+typedef int (*elapi_add_fd)(int fd, /* File descriptor to add */
+ void *callers_data, /* Data that the function
+ * would need to do its work */
+ elapi_fd_callback handle, /* Callback to call when event happens */
+ void *elapi_data); /* Data to pass to the callback */
+
+/* Signature of the supplied by caller function that ELAPI
+ * will call to remove the fd from the application event processing loop.
+ * The implementation of the function should assume that
+ * ELAPI will close file/socket descriptor after colling this function.
+ */
+typedef int (*elapi_rem_fd)(int fd, /* File descriptor to add */
+ void *callers_data); /* Data that the function
+ * would need to do its work */
+
+/* Signature of the supplied by caller function that ELAPI
+ * will call to add a new timer event to the application event processing loop.
+ */
+typedef int (*elapi_add_timer)(struct timeval timer, /* Timer */
+ void *callers_data, /* Data that the function
+ * would need to do its work */
+ elapi_timer_callback handle, /* Callback to call when event happens */
+ void *elapi_data); /* Data to pass to the callback */
+
+
+
+
+
+#endif
diff --git a/common/elapi/elapi_event.c b/common/elapi/elapi_event.c
index fe3b3a5e..97cb2a13 100644
--- a/common/elapi/elapi_event.c
+++ b/common/elapi/elapi_event.c
@@ -58,12 +58,9 @@ const char *str_no = "no";
const char *str_true = "true";
const char *str_false = "false";
-/* Default event template */
-struct collection_item *default_template = NULL;
-
/* Function to add host identity information to the template */
-int add_host_identity(struct collection_item *tpl, unsigned base)
+static int add_host_identity(struct collection_item *tpl, unsigned base)
{
char hostname[NI_MAXHOST + 1];
int error = EOK;
@@ -79,8 +76,6 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
TRACE_FLOW_STRING("add_host_identity", "Entry");
- memset(hostname, 0, sizeof(hostname));
-
/* The goal here to collect information about the host.
* there is no need to actually use it for establishing
* any connections.
@@ -92,7 +87,7 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
/* If we are not asked for ip then say we already have it */
if (!(base & E_HAVE_HOSTIP)) set_ip = 1;
- if (getifaddrs(&ifaddr) == 0) {
+ if (getifaddrs(&ifaddr) == EOK) {
TRACE_FLOW_STRING("getifaddrs", "Ok");
@@ -117,9 +112,11 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
if (family == AF_INET || family == AF_INET6) {
TRACE_FLOW_NUMBER("Got right family", family);
- /* Make sure the address is cleared - will help in comparisons */
- memset(host, 0, sizeof(host));
- memset(address, 0, sizeof(address));
+
+ /* getnameinfo function claims that it returns NULL
+ * terminated strings. Well...
+ * We will trust it here and not clear memory using memset.
+ */
gai_ret_host = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
@@ -146,10 +143,14 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
hnm = NULL;
/* Use host name returned by gethostname() as main host name */
- if (!gethostname(hostname, NI_MAXHOST)) hnm = hostname;
+ if (gethostname(hostname, NI_MAXHOST) == EOK) {
+ /* Make sure hostname is NULL terminated */
+ hostname[NI_MAXHOST] = '\0';
+ hnm = hostname;
+ }
else {
/* We we able to get a host name ? */
- if (gai_ret_host == 0) {
+ if (gai_ret_host == EOK) {
TRACE_INFO_STRING("getnameinfo returned:", host);
hnm = host;
}
@@ -157,9 +158,9 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
/* Do we have a host meaningful host name? */
if ((hnm) &&
- ((strncasecmp(hnm, LOCALHOST, sizeof(LOCALHOST)) == 0 ) ||
- (strncasecmp(hnm, LOCALHOSTDOMAIN, sizeof(LOCALHOSTDOMAIN)) == 0 ) ||
- (strncasecmp(hnm, address, sizeof(address) == 0)))) hnm = NULL;
+ ((strcasecmp(hnm, LOCALHOST) == 0 ) ||
+ (strcasecmp(hnm, LOCALHOSTDOMAIN) == 0 ) ||
+ (strcasecmp(hnm, address) == 0))) hnm = NULL;
/* If host name is not NULL it would work for us */
if (hnm) {
@@ -181,10 +182,10 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
TRACE_FLOW_STRING("Address is not set", "");
haddr = NULL;
- if (gai_ret_addr == 0) {
+ if (gai_ret_addr == EOK) {
TRACE_INFO_STRING("getnameinfo returned:", address);
- if ((strncasecmp(address, LOCALADDRESS, sizeof(LOCALADDRESS)) != 0 ) &&
- (strncasecmp(address, LOCALADDRESSV6, sizeof(LOCALADDRESSV6)) != 0 )) {
+ if ((strcasecmp(address, LOCALADDRESS) != 0 ) &&
+ (strcasecmp(address, LOCALADDRESSV6) != 0 )) {
TRACE_INFO_STRING("Not an unhelpful address", "");
haddr = address;
}
@@ -211,11 +212,11 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
TRACE_INFO_STRING("they are:", strncasecmp(host, address, sizeof(address)) == 0 ? "same" : "different");
/* Do we have a host meaningful host name? */
- if ((gai_ret_host != 0) ||
- ((gai_ret_host == 0) &&
- ((strncasecmp(host, LOCALHOST, sizeof(LOCALHOST)) == 0 ) ||
- (strncasecmp(host, LOCALHOSTDOMAIN, sizeof(LOCALHOSTDOMAIN)) == 0 ) ||
- (strncasecmp(host, address, sizeof(address)) == 0)))) hnm = NULL;
+ if ((gai_ret_host != EOK) ||
+ ((gai_ret_host == EOK) &&
+ ((strcasecmp(host, LOCALHOST) == 0 ) ||
+ (strcasecmp(host, LOCALHOSTDOMAIN) == 0 ) ||
+ (strcasecmp(host, address) == 0)))) hnm = NULL;
else hnm = host;
if (hnm) {
@@ -233,10 +234,10 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
if ((set_ip) && (base & E_HAVE_HOSTIPS)) {
/* Do we have a host meaningful host name? */
- if ((gai_ret_addr != 0) ||
- ((gai_ret_addr == 0) &&
- ((strncasecmp(address, LOCALADDRESS, sizeof(LOCALADDRESS)) == 0 ) ||
- (strncasecmp(address, LOCALADDRESSV6, sizeof(LOCALADDRESSV6)) == 0 )))) haddr = address;
+ if ((gai_ret_addr != EOK) ||
+ ((gai_ret_addr == EOK) &&
+ ((strcasecmp(address, LOCALADDRESS) == 0 ) ||
+ (strcasecmp(address, LOCALADDRESSV6) == 0 )))) haddr = address;
else haddr = address;
if (haddr) {
@@ -286,7 +287,7 @@ int add_host_identity(struct collection_item *tpl, unsigned base)
static int add_base_elements(struct collection_item *tpl, unsigned base)
{
int error = EOK;
- int pass_base;
+ unsigned pass_base;
TRACE_FLOW_STRING("add_base_elements", "Entry");
@@ -309,6 +310,15 @@ static int add_base_elements(struct collection_item *tpl, unsigned base)
}
}
+ if (base & E_HAVE_OFFSET) {
+ /* Value does not matter */
+ error = col_add_int_property(tpl, NULL, E_OFFSET, 0);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to add UTC time. Error", error);
+ return error;
+ }
+ }
+
if (base & E_HAVE_PID) {
/* Value is the current pid */
error = col_add_long_property(tpl, NULL, E_PID, (long)getpid());
@@ -361,12 +371,12 @@ static int add_base_elements(struct collection_item *tpl, unsigned base)
/* Internal untility function to tokenize a string */
-static int interprete_key(char *key,
- int *type,
- char **property,
- int *prop_len,
- int *has_len,
- int *bool_type)
+static int interpret_key(char *key,
+ int *type,
+ char **property,
+ int *prop_len,
+ int *has_len,
+ int *bool_type)
{
int adjust_by = 0;
char *start = NULL;
@@ -374,7 +384,7 @@ static int interprete_key(char *key,
char *end = NULL;
int ret = E_LIST_EMPTY;
- TRACE_FLOW_STRING("interprete_key", "Entry");
+ TRACE_FLOW_STRING("interpret_key", "Entry");
TRACE_INFO_STRING("Key", key);
@@ -533,7 +543,7 @@ static int interprete_key(char *key,
TRACE_INFO_NUMBER("Returning Has length:", *has_len);
- TRACE_FLOW_STRING("interprete_key", "Exit");
+ TRACE_FLOW_STRING("interpret_key", "Exit");
return ret;
}
@@ -544,14 +554,14 @@ static int convert_bool(char *data_str, unsigned char *data_bool)
TRACE_FLOW_STRING("convert_bool", "Called");
TRACE_INFO_STRING("Data", data_str);
- if ((strncasecmp(data_str, str_true, sizeof(str_true)) == 0) ||
- (strncasecmp(data_str, str_yes, sizeof(str_yes)) == 0)) {
+ if ((strcasecmp(data_str, str_true) == 0) ||
+ (strcasecmp(data_str, str_yes) == 0)) {
TRACE_INFO_STRING("Matched TRUE", "");
*data_bool = '\1';
return 1;
}
- if ((strncasecmp(data_str, str_false, sizeof(str_false)) == 0) ||
- (strncasecmp(data_str, str_no, sizeof(str_no)) == 0)) {
+ if ((strcasecmp(data_str, str_false) == 0) ||
+ (strcasecmp(data_str, str_no) == 0)) {
TRACE_INFO_STRING("Matched FALSE", "");
*data_bool = '\0';
return 1;
@@ -599,7 +609,7 @@ static int process_arg_list(struct collection_item *col,
return EINVAL;
}
- /* Interprete the key.
+ /* Interpret the key.
* It can be just " key ",
* it can be " - key ",
* or it can be a formatted string
@@ -607,12 +617,12 @@ static int process_arg_list(struct collection_item *col,
* Function will deal with all cases.
* Passed in variables initialized and updated inside
*/
- ret = interprete_key(arg,
- &type,
- &property,
- &prop_len,
- &has_len,
- &bool_type);
+ ret = interpret_key(arg,
+ &type,
+ &property,
+ &prop_len,
+ &has_len,
+ &bool_type);
if (ret == E_LIST_LAST) {
TRACE_INFO_STRING("Process found last key", arg);
@@ -621,12 +631,16 @@ static int process_arg_list(struct collection_item *col,
if ((ret == E_LIST_ADD) || (ret == E_LIST_REMOVE)) {
/* We need to create a dup of the string */
- propcopy = strndup(property, prop_len);
+ propcopy = malloc(prop_len + 1);
if (propcopy == NULL) {
TRACE_ERROR_STRING("Failed to allocate property", arg);
return ENOMEM;
}
+ /* Copy property */
+ memcpy(propcopy, property, prop_len);
+ propcopy[prop_len] = '\0';
+
TRACE_INFO_STRING("Processing property", propcopy);
/* Are we supposed to add? */
@@ -759,45 +773,18 @@ static int process_arg_list(struct collection_item *col,
return error;
}
-static int get_default_template(struct collection_item **template)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("get_default_template", "Entry");
-
- if (!default_template) {
- TRACE_INFO_STRING("Default template does not exit", "");
- error = elapi_set_default_template(E_BASE_DEFV1);
- if (error) {
- TRACE_ERROR_NUMBER("Set default template returned error", error);
- return error;
- }
- }
- *template = default_template;
- TRACE_FLOW_NUMBER("get_default_template. Exit returning", error);
- return error;
-}
-
-/* Cleanup callback installed when global template is used */
-void clean_template(void)
-{
- TRACE_FLOW_STRING("clean_template", "Entry");
- elapi_destroy_event_template(default_template);
- TRACE_FLOW_STRING("clean_template", "Exit");
-}
/*****************************************************************************/
-
/* Create event template */
-int elapi_create_event_template(struct collection_item **template,
- unsigned base, ...)
+int elapi_create_event_template_with_vargs(struct collection_item **template,
+ unsigned base,
+ va_list args)
{
int error = EOK;
struct collection_item *tpl = NULL;
- va_list args;
- TRACE_FLOW_STRING("elapi_create_event_template", "Entry");
+ TRACE_FLOW_STRING("elapi_create_event_template_with_vargs", "Entry");
if (template == NULL ) {
TRACE_ERROR_STRING("Template storage must be provided", "");
@@ -821,14 +808,9 @@ int elapi_create_event_template(struct collection_item **template,
return error;
}
- /* Process varible arguments */
- va_start(args, base);
-
/* Process variable argument list */
error = process_arg_list(tpl, args);
- va_end(args);
-
if (error) {
TRACE_ERROR_NUMBER("Failed to process argument list. Error", error);
col_destroy_collection(tpl);
@@ -837,6 +819,30 @@ int elapi_create_event_template(struct collection_item **template,
*template = tpl;
+ TRACE_FLOW_STRING("elapi_create_event_template_with_vargs", "Exit");
+ return error;
+}
+
+
+/* Create event template */
+int elapi_create_event_template(struct collection_item **template,
+ unsigned base, ...)
+{
+ int error = EOK;
+ va_list args;
+
+ TRACE_FLOW_STRING("elapi_create_event_template", "Entry");
+
+ /* Process varible arguments */
+ va_start(args, base);
+
+ /* Create template using arguments */
+ error = elapi_create_event_template_with_vargs(template,
+ base,
+ args);
+
+ va_end(args);
+
TRACE_FLOW_STRING("elapi_create_event_template", "Exit");
return error;
}
@@ -851,30 +857,24 @@ void elapi_destroy_event_template(struct collection_item *template)
TRACE_FLOW_STRING("elapi_destroy_event_template", "Exit");
}
-/* Create event */
-int elapi_create_event(struct collection_item **event,
- struct collection_item *template,
- struct collection_item *collection,
- int mode, ...)
+
+/* Create event from template, colection and arguments */
+int elapi_create_event_with_vargs(struct collection_item **event,
+ struct collection_item *template,
+ struct collection_item *collection,
+ int mode, va_list args)
{
int error = EOK;
struct collection_item *evt = NULL;
- va_list args;
- TRACE_FLOW_STRING("elapi_create_event", "Entry");
+ TRACE_FLOW_STRING("elapi_create_event_with_vargs", "Entry");
/* Check storage */
- if (event == NULL ) {
+ if (event == NULL) {
TRACE_ERROR_STRING("Event storage must be provided", "");
return EINVAL;
}
- /* Check for template */
- if (template == NULL ) {
- TRACE_ERROR_STRING("Template argument is missing", "");
- return EINVAL;
- }
-
*event = NULL;
/* Create collection */
@@ -885,13 +885,16 @@ int elapi_create_event(struct collection_item **event,
}
/* Add elements from the template */
- error = col_add_collection_to_collection(evt, NULL, NULL,
- (struct collection_item *)template,
- COL_ADD_MODE_FLAT);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to add elements from the template. Error", error);
- col_destroy_collection(evt);
- return error;
+ /* Check for template */
+ if (template != NULL) {
+ error = col_add_collection_to_collection(evt, NULL, NULL,
+ (struct collection_item *)template,
+ COL_ADD_MODE_FLAT);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to add elements from the template. Error", error);
+ col_destroy_collection(evt);
+ return error;
+ }
}
/* Add elements from the template */
@@ -904,14 +907,9 @@ int elapi_create_event(struct collection_item **event,
}
}
- /* Process varible arguments */
- va_start(args, mode);
-
/* Process variable argument list */
error = process_arg_list(evt, args);
- va_end(args);
-
if (error) {
TRACE_ERROR_NUMBER("Failed to process argument list. Error", error);
col_destroy_collection(evt);
@@ -920,6 +918,32 @@ int elapi_create_event(struct collection_item **event,
*event = evt;
+ TRACE_FLOW_STRING("elapi_create_event_with_vargs", "Exit");
+ return error;
+}
+
+
+/* Create event a wrapper around a function with arg list */
+int elapi_create_event(struct collection_item **event,
+ struct collection_item *template,
+ struct collection_item *collection,
+ int mode, ...)
+{
+ int error = EOK;
+ va_list args;
+
+ TRACE_FLOW_STRING("elapi_create_event", "Entry");
+
+ va_start(args, mode);
+
+ error = elapi_create_event_with_vargs(event,
+ template,
+ collection,
+ mode,
+ args);
+ va_end(args);
+
+
TRACE_FLOW_STRING("elapi_create_event", "Exit");
return error;
}
@@ -992,122 +1016,3 @@ void elapi_destroy_event(struct collection_item *event)
TRACE_FLOW_STRING("elapi_destroy_event", "Exit");
}
-
-/* Initializes default internal template */
-int elapi_set_default_template(unsigned base, ...)
-{
- int error = EOK;
- struct collection_item *tpl;
- va_list args;
-
- TRACE_FLOW_STRING("elapi_set_default_template", "Entry");
-
- /* Clean previous instance of the default template */
- elapi_destroy_event_template(default_template);
- default_template = NULL;
-
- /* Create collection */
- error = col_create_collection(&tpl, E_TEMPLATE_NAME, COL_CLASS_ELAPI_TEMPLATE);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to create collection. Error", error);
- return error;
- }
-
- /* Add elements using base mask */
- error = add_base_elements(tpl, base);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to add base elements. Error", error);
- col_destroy_collection(tpl);
- return error;
- }
-
- /* Process varible arguments */
- va_start(args, base);
-
- /* Process variable argument list */
- error = process_arg_list(tpl, args);
-
- va_end(args);
-
- if (error) {
- TRACE_ERROR_NUMBER("Failed to process argument list. Error", error);
- col_destroy_collection(tpl);
- return error;
- }
-
- /* Install a cleanup callback */
- if (atexit(clean_template)) {
- TRACE_ERROR_NUMBER("Failed to install cleanup callback. Error", ENOSYS);
- col_destroy_collection(tpl);
- /* NOTE: Could not find a better error for this case */
- return ENOSYS;
- }
-
- default_template = tpl;
-
- TRACE_FLOW_STRING("elapi_set_default_template", "Exit");
- return error;
-}
-
-
-/* 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 *template;
-
- 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;
-
- error = get_default_template(&template);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to get default template. Error", error);
- return error;
- }
-
- /* Create collection */
- error = col_create_collection(&evt, E_EVENT_NAME, COL_CLASS_ELAPI_EVENT);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to create collection. Error", error);
- return error;
- }
-
- /* Add elements from the template */
- error = col_add_collection_to_collection(evt, NULL, NULL,
- template,
- COL_ADD_MODE_FLAT);
-
- if (error) {
- TRACE_ERROR_NUMBER("Failed to add elements from the template. Error", error);
- col_destroy_collection(evt);
- return error;
- }
-
- /* Process varible arguments */
- va_start(args, event);
-
- /* Process variable argument list */
- error = process_arg_list(evt, args);
-
- va_end(args);
-
- if (error) {
- TRACE_ERROR_NUMBER("Failed to process argument list. Error", error);
- col_destroy_collection(evt);
- return error;
- }
-
- *event = evt;
-
- TRACE_FLOW_STRING("elapi_create_simple_event", "Exit");
- return error;
-}
diff --git a/common/elapi/elapi_event.h b/common/elapi/elapi_event.h
index d1e0dd12..f1833396 100644
--- a/common/elapi/elapi_event.h
+++ b/common/elapi/elapi_event.h
@@ -23,16 +23,17 @@
#include "collection.h"
/* Possible predefined elements of the event */
-#define E_TIMESTAMP "stamp" /* string - the value is the format for strftime()
- * default is standard format for current locale. */
-#define E_UTCTIME "time" /* int - UTC time as unix time in seconds since 1970 */
-#define E_PID "pid" /* int - Process ID of the current process */
-#define E_APPNAME "appnm" /* string - Name of the current application */
-#define E_HOSTNAME "host" /* string - Name of the current host */
-#define E_HOSTIP "ip" /* string - IP address */
-#define E_SEVERITY "sev" /* int - Same as "priority" in syslog() */
-#define E_HOSTALIAS "halias" /* string - List of alternative host names */
-#define E_HOSTIPS "iplist" /* string - List of alternative IP addresses */
+#define E_TIMESTAMP "__stamp__" /* string - the value is the format for strftime()
+ * default is standard format for current locale. */
+#define E_UTCTIME "__time__" /* int - UTC time as unix time in seconds since 1970 */
+#define E_OFFSET "__loco__" /* int - local time displacement */
+#define E_PID "__pid__" /* int - Process ID of the current process */
+#define E_APPNAME "__appnm__" /* string - Name of the current application */
+#define E_HOSTNAME "__host__" /* string - Name of the current host */
+#define E_HOSTIP "__ip__" /* string - IP address */
+#define E_SEVERITY "__sev__" /* int - Same as "priority" in syslog() */
+#define E_HOSTALIAS "__halias__" /* string - List of alternative host names */
+#define E_HOSTIPS "__iplist__" /* string - List of alternative IP addresses */
/* There is a special optional attribute of the event named "message".
* It is a string that contains text specific to each event.
@@ -43,7 +44,7 @@
* The token %(server) will be replaced by value
* in the attribute "server" in the event.
*/
-#define E_MESSAGE "message"
+#define E_MESSAGE "__message__"
/* Base argument in the template creation function is a bit mask.
* Each supported predefined element corresponds to its bit in
@@ -51,23 +52,24 @@
*/
#define E_HAVE_TIMESTAMP 0x00000001
#define E_HAVE_UTCTIME 0x00000002
-#define E_HAVE_PID 0x00000004
+#define E_HAVE_OFFSET 0x00000004
#define E_HAVE_APPNAME 0x00000010
#define E_HAVE_HOSTNAME 0x00000020
#define E_HAVE_HOSTIP 0x00000040
#define E_HAVE_SEVERITY 0x00000100
#define E_HAVE_HOSTALIAS 0x00000200
#define E_HAVE_HOSTIPS 0x00000400
+#define E_HAVE_PID 0x00001000
/* Convenient bitmasks */
-#define E_BASE_TIME ( E_HAVE_TIMESTAMP | E_HAVE_UTCTIME )
+#define E_BASE_TIME ( E_HAVE_TIMESTAMP | E_HAVE_UTCTIME | E_HAVE_OFFSET)
#define E_BASE_HOST ( E_HAVE_HOSTIP | E_HAVE_HOSTNAME )
#define E_BASE_APP ( E_HAVE_APPNAME | E_HAVE_PID )
#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 "%c"
+#define E_TIMESTAMP_FORMAT "%F"
#define TIME_ARRAY_SIZE 100
@@ -145,12 +147,6 @@ int elapi_copy_event(struct collection_item **new_event,
struct collection_item *source_event);
/* Function to destroy event. */
-/* Keep in mind that as soon as event is logged
- * it is automatically destroyed so the
- * function should be used only in cases
- * when you have an event
- * that you use as a template for other events.
- */
void elapi_destroy_event(struct collection_item *event);
/***************************************************************************/
@@ -159,6 +155,10 @@ void elapi_destroy_event(struct collection_item *event);
/* Initializes default internal template */
int elapi_set_default_template(unsigned base, ...);
+/* Retrieve default template */
+int elapi_get_default_template(struct collection_item **template);
+
+
/* This function will use internal default template.
* Hides all complexity from the caller.
*/
diff --git a/common/elapi/elapi_internal.c b/common/elapi/elapi_internal.c
new file mode 100644
index 00000000..2e93a355
--- /dev/null
+++ b/common/elapi/elapi_internal.c
@@ -0,0 +1,231 @@
+/*
+ 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 "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 sinks */
+int elapi_internal_sink_handler(const char *sink,
+ int sink_len,
+ int type,
+ void *data,
+ int length,
+ 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);
+
+ if (type == COL_TYPE_COLLECTION) {
+ printf("\n\n\nPROCESSING EVENT:\n");
+ col_debug_collection(sink_env->event, COL_TRAVERSE_DEFAULT);
+ }
+ else printf("Sink: %s\n", sink);
+
+ TRACE_FLOW_STRING("elapi_internal_sink_handler", "Exit.");
+ return EOK;
+}
+
+/* Internal sink cleanup function */
+int elapi_internal_sink_cleanup_handler(const char *sink,
+ int sink_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop)
+{
+ TRACE_FLOW_STRING("elapi_internal_sink_cleanup_handler", "Entry.");
+
+ /* FIXME THIS IS A PLACEHOLDER FUNCTION FOR NOW */
+
+ if (type != COL_TYPE_COLLECTION) 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)
+{
+ 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);
+ 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;
+ }
+
+ /* 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);
+
+ /* Try to load the sink library */
+
+ /* 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);
+ return error;
+ }
+ */
+
+
+ /* 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));
+ if (error != 0) {
+ TRACE_ERROR_NUMBER("Failed to add sink data as property", error);
+ return error;
+ }
+
+ TRACE_FLOW_NUMBER("elapi_internal_add_sink_to_collection returning", error);
+ return error;
+}
+
+/* Function to create a list of sinks */
+int elapi_internal_construct_sink_list(struct elapi_dispatcher *handle)
+{
+ int error = EOK;
+ char **current_sink;
+
+ TRACE_FLOW_STRING("elapi_internal_construct_sink_list", "Entry");
+
+ /* 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_sink = handle->sinks;
+ handle->sink_counter = 0;
+
+ /* Add sinks as properties to the sink collection */
+ while (*current_sink != NULL) {
+
+ TRACE_INFO_STRING("Current sink", *current_sink);
+ TRACE_INFO_STRING("Will use appname:", handle->appname);
+
+ /* 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. */
+ return error;
+ }
+
+ handle->sink_counter++;
+ current_sink++;
+ }
+
+ /* 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;
+ }
+
+ TRACE_FLOW_STRING("elapi_internal_construct_sink_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)
+{
+ FILE *efile;
+ char timestr[MAX_TIMESTR];
+ time_t time_in_sec;
+ struct tm *time_as_struct;
+ struct tm time_data;
+
+ TRACE_FLOW_STRING("elapi_internal_dump_errors_to_file", "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_internal_dump_errors_to_file", "Exit");
+}
diff --git a/common/elapi/elapi_log.c b/common/elapi/elapi_log.c
new file mode 100644
index 00000000..7c0d72ab
--- /dev/null
+++ b/common/elapi/elapi_log.c
@@ -0,0 +1,631 @@
+/*
+ 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;
+
+/* Deafult sink names */
+char remote_sink[] = "remote";
+char altremote_sink[] = "altremote";
+char syslog_sink[] = "syslog";
+char db_sink[] = "db";
+char file_sink[] = "file";
+char failover_sink[] = "failover";
+char stderr_sink[] = "stderr";
+
+/* Deafult sink list */
+char *default_sinks[] = { remote_sink,
+ altremote_sink,
+ syslog_sink,
+ db_sink,
+ file_sink,
+ failover_sink,
+ stderr_sink,
+ 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(struct elapi_dispatcher *dispatcher,
+ struct collection_item *template,
+ 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,
+ template,
+ NULL,
+ 0,
+ args);
+
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create event", error);
+ return error;
+ }
+
+ /* Now log event */
+ error = elapi_dsp_log(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 create a dispatcher */
+int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
+ const char *appname,
+ const char *config_path,
+ elapi_add_fd add_fd_add_fn,
+ elapi_rem_fd add_fd_rem_fn,
+ elapi_add_timer add_timer_fn,
+ void *callers_data)
+{
+ 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;
+ int prm_cnt = 0;
+
+ 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 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 ((prm_cnt > 0) && (prm_cnt < 4)) {
+ /* We got a mixture of NULLs and not NULLs.
+ * This is bad since all should be either provided
+ * or all should be NULL.
+ */
+ TRACE_ERROR_STRING("Invalid sync parameters.", "At least one is NULL while others are not.");
+ return EINVAL;
+ }
+
+ /* 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 *) malloc(sizeof(struct elapi_dispatcher));
+ if (handle == NULL) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Memory allocation failed. Error", error);
+ return error;
+ }
+
+ /* Clean memory - we need it to be able to destroy the dispatcher at any moment */
+ /* FIXME - eventually remove the memset from here when the structure finalizes */
+ /* Valgrind requires explicit initialization of the structure member, otherwise
+ * it complains about jump or move based on the uninitialized variable.
+ */
+ memset(handle, 0, sizeof(struct elapi_dispatcher *));
+ handle->ini_config = NULL;
+ handle->sink_list = NULL;
+ handle->sinks = NULL;
+ handle->default_template = NULL;
+ handle->need_to_free = 0;
+
+ /* 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) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Memory allocation failed. Error", error);
+ elapi_destroy_dispatcher(handle);
+ return error;
+ }
+
+ /* 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_internal_dump_errors_to_file(error_set);
+ free_ini_config_errors(error_set);
+ }
+ return error;
+ }
+ /* Have to clean error set anyways */
+ free_ini_config_errors(error_set);
+
+ /* Get sink list from configuration */
+ error = get_config_item(ELAPI_DISPATCHER,
+ ELAPI_SINKS,
+ handle->ini_config,
+ &item);
+ if (error) {
+ TRACE_ERROR_NUMBER("Attempt to read configuration returned error", error);
+ elapi_destroy_dispatcher(handle);
+ return error;
+ }
+
+ if (!item) {
+ /* There is no list of sinks - use default list */
+ handle->sinks = default_sinks;
+ }
+ 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;
+ }
+
+ /* Populate async processing data if any */
+ if (prm_cnt) {
+ TRACE_INFO_STRING("Async data is present", "");
+ handle->add_fd_add_fn = add_fd_add_fn;
+ handle->add_fd_rem_fn = add_fd_rem_fn;
+ handle->add_timer_fn = add_timer_fn;
+ handle->callers_data = callers_data;
+ 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.");
+ 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,
+ NULL,
+ NULL,
+ 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_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);
+ 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("Freeing dispatcher.", "");
+ free(dispatcher);
+ }
+
+ TRACE_FLOW_STRING("elapi_destroy_dispatcher", "Exit.");
+}
+
+/* Function to log an event */
+int elapi_dsp_log(struct elapi_dispatcher *dispatcher, struct collection_item *event)
+{
+ int error = EOK;
+ struct elapi_sink_context sink_env;
+
+ TRACE_FLOW_STRING("elapi_dsp_log", "Entry");
+
+ if ((dispatcher == NULL) ||
+ (event == NULL)) {
+ TRACE_ERROR_STRING("elapi_dsp_log", "ERROR Invalid argument");
+ return EINVAL;
+ }
+
+ sink_env.handle = dispatcher;
+ sink_env.event = event;
+
+ /* Logging an event is just iterating through the sinks and calling the sink_handler */
+ error = col_traverse_collection(dispatcher->sink_list,
+ COL_TRAVERSE_ONELEVEL,
+ elapi_internal_sink_handler,
+ (void *)(&sink_env));
+
+ TRACE_FLOW_NUMBER("elapi_dsp_log Exit. Returning", error);
+ return error;
+}
+
+/* Initializes default internal template */
+int elapi_set_default_template(unsigned base, ...)
+{
+ int error = EOK;
+ struct collection_item *tpl = NULL;
+ va_list args;
+
+ TRACE_FLOW_STRING("elapi_set_default_template", "Entry");
+
+ if (global_dispatcher == NULL) elapi_init(NULL, NULL);
+
+ /* Clean previous instance of the default template */
+ elapi_destroy_event_template(global_dispatcher->default_template);
+ global_dispatcher->default_template = NULL;
+
+ /* Process varible arguments */
+ va_start(args, base);
+
+ /* Create template out of base and args */
+ error = elapi_create_event_template_with_vargs(&tpl,
+ base,
+ args);
+ va_end(args);
+
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create template. Error", error);
+ return error;
+ }
+
+ global_dispatcher->default_template = tpl;
+
+ TRACE_FLOW_STRING("elapi_set_default_template", "Exit");
+ return error;
+}
+
+/* There is one default template associated with the dispatcher */
+int elapi_get_default_template(struct collection_item **template)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("elapi_get_default_template", "Entry");
+
+ if ((global_dispatcher == NULL) ||
+ (global_dispatcher->default_template == NULL)) {
+ TRACE_INFO_STRING("Default template does not exit", "");
+
+ error = elapi_set_default_template(E_BASE_DEFV1);
+ if (error) {
+ TRACE_ERROR_NUMBER("Set default template returned error", error);
+ return error;
+ }
+ }
+
+ *template = global_dispatcher->default_template;
+ TRACE_FLOW_NUMBER("elapi_get_default_template. Exit returning", error);
+ return error;
+}
+
+
+
+/* Function to log raw key value pairs without creating an event */
+int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
+ struct collection_item *template,
+ ...)
+{
+ int error = EOK;
+ va_list args;
+
+ TRACE_FLOW_STRING("elapi_dsp_msg", "Entry");
+
+ va_start(args, template);
+
+ error = elapi_dsp_msg_with_vargs(dispatcher, template, 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 *sink,
+ int action)
+{
+
+ /* FIXME: FUNCTION IS NOT IMPLEMENTED YET */
+ return EOK;
+}
+
+/* Get sink list */
+char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher)
+{
+
+ /* 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 */
+
+}
+
+
+/******************** 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 *template = 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_template(&template);
+ 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,
+ template,
+ 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(struct collection_item *template, ...)
+{
+ int error = EOK;
+ va_list args;
+ struct collection_item *use_template;
+
+ TRACE_FLOW_STRING("elapi_msg", "Entry");
+
+ if (!template) {
+ /* Get default template */
+ error = elapi_get_default_template(&use_template);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to get default template. Error", error);
+ return error;
+ }
+ }
+ else use_template = template;
+
+ va_start(args, template);
+
+ error = elapi_dsp_msg_with_vargs(global_dispatcher, use_template, args);
+
+ va_end(args);
+
+ TRACE_FLOW_NUMBER("elapi_msg Exit:", error);
+ return error;
+}
+
+/* Log event */
+int elapi_log(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);
+
+ 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;
+}
diff --git a/common/elapi/elapi_log.h b/common/elapi/elapi_log.h
new file mode 100644
index 00000000..6fff82b6
--- /dev/null
+++ b/common/elapi/elapi_log.h
@@ -0,0 +1,117 @@
+/*
+ ELAPI
+
+ Header file for 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/>.
+*/
+
+#ifndef ELAPI_LOG_H
+#define ELAPI_LOG_H
+
+#include "elapi_async.h"
+
+/* Opaque dispatcher structure */
+struct elapi_dispatcher;
+
+
+/******************** Low level thread safe interface ************************************/
+/* This interface should be used if application plans to control the dispatcher,
+ * implement its own sinks that can be added dynamically or implements it own routing function.
+ */
+
+/********** Main functions of the interface **********/
+
+/* Function to create a dispatcher */
+int elapi_create_dispatcher(struct elapi_dispatcher **dispatcher, /* Handle of the dispatcher will be stored in this variable */
+ const char *appname, /* Application name. Passed to the sinks to do initialization */
+ const char *config_path); /* See notes below in the elapi_init() function. */
+
+/* A more advanced function to create a dispatcher */
+int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher, /* Handle of the dispatcher will be stored in this variable */
+ const char *appname, /* Application name. Passed to the sinks to do initialization */
+ const char *config_path, /* See notes below in the elapi_init() function. */
+ elapi_add_fd add_fd_add_fn, /* Caller's function to add file descriptor */
+ elapi_rem_fd add_fd_rem_fn, /* Caller's function to remove file descriptor */
+ elapi_add_timer add_timer_fn, /* Caller's function to add timer */
+ void *callers_data); /* Data that needs to be passed when caller's callback is called. */
+
+/* Function to clean memory associated with the dispatcher */
+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);
+
+/* Function to log raw key value pairs without creating an event */
+int elapi_dsp_msg(struct elapi_dispatcher *dispatcher,
+ struct collection_item *template,
+ ...);
+
+/********** Advanced dispatcher management functions **********/
+
+/* Managing the sink collection */
+int elapi_alter_dispatcher(struct elapi_dispatcher *dispatcher, /* Dispatcher */
+ const char *sink, /* Sink to change */
+ int action); /* Action to perform for sink */
+
+/* Get sink list */
+char **elapi_get_sink_list(struct elapi_dispatcher *dispatcher);
+
+/* Free sink list */
+void elapi_free_sink_list(char **sink_list);
+
+
+/******************** High level interface ************************************/
+/* This interface is not thread safe but convenient. It hides the dispatcher. */
+
+/* Function to initialize ELAPI library in the single threaded applications */
+/* If config_path = NULL the configuration will be read from the standard locations:
+ * - First from the global configuration file "elapi.conf" located in the directory
+ * defined at the compile time by the ELAPI_DEFAULT_CONFIG_DIR constant.
+ * This file is assumed to contain common ELAPI configuration for this host;
+ * - Second from the file with name constructed from appname by appending to it
+ * suffix ".conf". The file will be looked in the directory pointed by
+ * ELAPI_DEFAULT_CONFIG_APP_DIR constant that is defined at compile time.
+ * The data from second file overwrites and complements the data from the first
+ * one.
+ * It is expected that applications will take advantage of the common
+ * central convention so config_path should be NULL in most cases.
+ *
+ * If config_path points to a file the function will try to read the file
+ * as if it is a configuration file. The appname is ignored in this case.
+ * If config_path points to a directory, the function will try to read
+ * configuration from the file with name constructed by appending suffix ".conf"
+ * to appname. The file will be looked up in that directory.
+ * If the config_path is neither file or directory the default values will be used
+ * to initialize dispatcher.
+ *
+ * In case appname is NULL a default value defined by build time constant
+ * ELAPI_DEFAULT_APP_NAME will be used.
+ */
+int elapi_init(const char *appname, const char *config_path);
+
+/* Log key value pairs */
+int elapi_msg(struct collection_item *template, ...);
+
+
+/* Log event */
+int elapi_log(struct collection_item *event);
+
+/* Get dispatcher if you want to add sink to a default dispatcher or do some advanced operations */
+struct elapi_dispatcher *elapi_get_dispatcher(void);
+
+/* Close audit */
+void elapi_close(void);
+
+#endif
diff --git a/common/elapi/elapi_priv.h b/common/elapi/elapi_priv.h
index feb9a7f6..c536f4ec 100644
--- a/common/elapi/elapi_priv.h
+++ b/common/elapi/elapi_priv.h
@@ -20,13 +20,95 @@
#ifndef ELAPI_PRIV_H
#define ELAPI_PRIV_H
+#include "collection.h"
+#include "elapi_async.h"
/* Classes of the collections used by ELAPI internally */
#define COL_CLASS_ELAPI_BASE 21000
#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
/* Names for the collections */
#define E_TEMPLATE_NAME "template"
#define E_EVENT_NAME "event"
+
+#define ELAPI_DISPATCHER "dispatcher"
+#define ELAPI_SINKS "sinks"
+
+struct elapi_dispatcher {
+ char **sinks;
+ int need_to_free;
+ char *appname;
+ /*event_router_fn router; - FIXME - not defined yet */
+ struct collection_item *sink_list;
+ int sink_counter;
+ struct collection_item *ini_config;
+ /* Default event template */
+ struct collection_item *default_template;
+ /* Async processing related data */
+ elapi_add_fd add_fd_add_fn;
+ elapi_rem_fd add_fd_rem_fn;
+ elapi_add_timer add_timer_fn;
+ void *callers_data;
+ int async_mode;
+};
+
+/* Structure to pass data from logging function to sinks */
+struct elapi_sink_context {
+ struct collection_item *event;
+ struct elapi_dispatcher *handle;
+ char *format;
+ char *previous;
+ int previous_status;
+};
+
+/* The structure to hold a command and a result of the command execution */
+struct elapi_get_sink {
+ int action;
+ int found;
+};
+
+/* Function to create event using arg list */
+int elapi_create_event_with_vargs(struct collection_item **event,
+ struct collection_item *template,
+ struct collection_item *collection,
+ int mode, va_list args);
+
+/* Function to create event template using arg list */
+int elapi_create_event_template_with_vargs(struct collection_item **template,
+ unsigned base,
+ va_list args);
+
+/* Sink handler function */
+int elapi_internal_sink_handler(const char *sink,
+ int sink_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop);
+
+/* Internal sink cleanup function */
+int elapi_internal_sink_cleanup_handler(const char *sink,
+ int sink_len,
+ int type,
+ void *data,
+ int length,
+ void *passed_data,
+ int *stop);
+
+
+/* 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);
+
+/* Send ELAPI config errors into a file */
+void elapi_internal_dump_errors_to_file(struct collection_item *error_list);
+
+
#endif
diff --git a/common/elapi/elapi_sink.h b/common/elapi/elapi_sink.h
new file mode 100644
index 00000000..40b12a26
--- /dev/null
+++ b/common/elapi/elapi_sink.h
@@ -0,0 +1,78 @@
+/*
+ ELAPI
+
+ Common sink interface header.
+
+ 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/>.
+*/
+
+#ifndef ELAPI_SINK_H
+#define ELAPI_SINK_H
+
+#include <time.h>
+#include "collection.h"
+
+#define ELAPI_SINK_OK 0 /* Sink can be used for logging */
+#define ELAPI_SINK_SUSPENDED 1 /* Sink is temporary disabled due to recoverable error */
+#define ELAPI_SINK_DISABLED 2 /* Sink is explicitely disabled by the application */
+#define ELAPI_SINK_PULSE 3 /* Sink is disabled for this one event */
+
+#define SINK_LIB_NAME_SIZE 100
+#define SINK_ENTRY_POINT "get_sink_info"
+#define SINK_NAME_TEMPLATE "libelapi_sink_%s.so"
+#define SINK_NEVER_RETRY -1
+
+/* Flags related to loading sinks */
+#define SINK_FLAG_NO_LIMIT 0x00000000 /* NO limits to loading and manipulating this sink - default */
+#define SINK_FLAG_LOAD_SINGLE 0x00000001 /* Only allow one instance of the sink per process */
+
+struct data_descriptor {
+ char *appname;
+ void *config;
+ void *internal_data;
+};
+
+/* Log facility callbacks */
+typedef int (*init_fn)(struct data_descriptor *dblock);
+typedef void (*cleanup_fn)(struct data_descriptor *dblock);
+typedef int (*format_fn)(struct data_descriptor *dblock, const char *format_str, struct collection_item *event);
+typedef int (*submit_fn)(struct data_descriptor *dblock);
+typedef void (*close_fn)(struct data_descriptor *dblock);
+
+struct sink_capability {
+ int retry_interval;
+ int flags;
+ int instance;
+ init_fn init_cb;
+ cleanup_fn cleanup_cb;
+ format_fn format_cb;
+ submit_fn submit_cb;
+ close_fn close_cb;
+};
+
+/* The only open function the link can expose */
+typedef void (*capability_fn)(struct sink_capability *sink_cpb_block);
+
+struct sink_descriptor {
+ struct sink_capability sink_cpb_block;
+ struct data_descriptor dblock;
+ int suspended;
+ time_t lasttry;
+ void *lib_handle;
+};
+
+/*Standard capability function */
+void get_sink_info(struct sink_capability *sink_cpb_block);
+
+#endif
diff --git a/common/elapi/elapi_ut.c b/common/elapi/elapi_ut.c
index b9493da1..2866411f 100644
--- a/common/elapi/elapi_ut.c
+++ b/common/elapi/elapi_ut.c
@@ -68,11 +68,21 @@ int simple_event_test(void)
return error;
}
- col_debug_collection(event, COL_TRAVERSE_DEFAULT);
- col_debug_collection(event, COL_TRAVERSE_FLAT);
+ error = elapi_log(event);
elapi_destroy_event(event);
+ if (error) {
+ printf("Failed to log event! %d\n", error);
+ return error;
+ }
+
+ error = elapi_msg(NULL, "a", "b", "c", "d", E_EOARG);
+ if (error) {
+ printf("Failed to log event! %d\n", error);
+ return error;
+ }
+
printf("Simple test success!\n");
return error;
@@ -81,10 +91,11 @@ int simple_event_test(void)
int complex_event_test(void)
{
int error = 0;
- struct collection_item *template;
- struct collection_item *event, *event_copy;
+ struct collection_item *template = NULL;
+ struct collection_item *event = NULL, *event_copy = NULL;
char bin[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
- struct collection_item *col;
+ struct collection_item *col = NULL;
+ struct elapi_dispatcher *dispatcher = NULL;
printf("Complex test START:\n");
@@ -126,10 +137,18 @@ int complex_event_test(void)
col_debug_collection(template, COL_TRAVERSE_FLAT);
col_debug_collection(event, COL_TRAVERSE_FLAT);
+ error = elapi_log(event);
- elapi_destroy_event_template(template);
elapi_destroy_event(event);
+ if (error) {
+ printf("Failed to log event! %d\n", error);
+ return error;
+ }
+
+
+ elapi_destroy_event_template(template);
+
error = elapi_create_event_template(
&template,
E_BASE_DEFV1 | E_BASE_HOSTEXT,
@@ -150,7 +169,7 @@ int complex_event_test(void)
}
if ((error = col_create_collection(&col, "test", 0)) ||
- /* We are forsing overwrite with different type */
+ /* We are forcing overwrite with different type */
(error = col_add_int_property(col, NULL, "unsigned_number", 1)) ||
(error = col_add_long_property(col, NULL, "bin", 100000000L))) {
elapi_destroy_event_template(template);
@@ -181,8 +200,6 @@ int complex_event_test(void)
col_debug_collection(event, COL_TRAVERSE_FLAT);
- elapi_destroy_event_template(template);
-
if ((error = col_create_collection(&col, "test", 0)) ||
/* We are forsing overwrite with different type */
(error = col_add_int_property(col, NULL, "zzz", 1)) ||
@@ -204,6 +221,7 @@ int complex_event_test(void)
if (error) {
printf("Failed to set create template %d\n", error);
elapi_destroy_event(event);
+ elapi_destroy_event_template(template);
col_destroy_collection(col);
return error;
}
@@ -211,17 +229,60 @@ int complex_event_test(void)
col_destroy_collection(col);
error = elapi_copy_event(&event_copy, event);
-
if (error) {
printf("Failed to set create template %d\n", error);
elapi_destroy_event(event);
+ elapi_destroy_event_template(template);
+ return error;
+ }
+
+ error = elapi_create_dispatcher(&dispatcher, "elapi_ut", "./sdfdsdf");
+ if (error) {
+ elapi_destroy_event(event);
+ elapi_destroy_event(event_copy);
+ elapi_destroy_event_template(template);
+ printf("Failed to create dispatcher %d\n", error);
return error;
}
+ error = elapi_dsp_log(dispatcher, event);
+
elapi_destroy_event(event);
- col_debug_collection(event_copy, COL_TRAVERSE_FLAT);
+
+ if (error) {
+ elapi_destroy_event(event_copy);
+ elapi_destroy_event_template(template);
+ printf("Failed to log event! %d\n", error);
+ return error;
+ }
+
+ error = elapi_dsp_log(dispatcher, event_copy);
+
elapi_destroy_event(event_copy);
+ if (error) {
+ elapi_destroy_event_template(template);
+ printf("Failed to log event! %d\n", error);
+ return error;
+ }
+
+ error = elapi_dsp_msg(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);
+ if (error) {
+ elapi_destroy_event_template(template);
+ printf("Failed to log event! %d\n", error);
+ return error;
+ }
+
+ elapi_destroy_event_template(template);
+ elapi_destroy_dispatcher(dispatcher);
+
return error;
}
diff --git a/common/elapi/elapi_ut.conf b/common/elapi/elapi_ut.conf
new file mode 100644
index 00000000..19cbeb71
--- /dev/null
+++ b/common/elapi/elapi_ut.conf
@@ -0,0 +1,6 @@
+[dispatcher]
+sinks = foo, bar, baz
+
+
+
+; test