summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/elapi/elapi_async.h130
-rw-r--r--common/elapi/elapi_log.c45
-rw-r--r--common/elapi/elapi_log.h5
-rw-r--r--common/elapi/elapi_priv.h64
-rw-r--r--common/elapi/elapi_sink.h5
-rw-r--r--common/elapi/elapi_test/elapi_ut.conf16
6 files changed, 175 insertions, 90 deletions
diff --git a/common/elapi/elapi_async.h b/common/elapi/elapi_async.h
index 24cb7f8b..f9fbd9e3 100644
--- a/common/elapi/elapi_async.h
+++ b/common/elapi/elapi_async.h
@@ -22,51 +22,113 @@
#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.
+#define ELAPI_FD_READ 0x00000001 /* request to read */
+#define ELAPI_FD_WRITE 0x00000002 /* request to write */
+
+/* Structure that holds ELAPI file descriptor's watch data */
+struct elapi_fd_data;
+
+/* Structure that holds ELAPI timer data */
+struct elapi_tm_data;
+
+/* Functions to set and get data from file descriptor data. */
+/* Functions return EINVAL if passed in argument is invalid. */
+int elapi_set_fd_priv(struct elapi_fd_data *fd_data,
+ void *priv_data_to_set);
+int elapi_get_fd_priv(struct elapi_fd_data *fd_data,
+ void **priv_data_to_get);
+/* Cleanup function */
+int elapi_destroy_fd_data(struct elapi_fd_data *fd_data);
+
+/* Functions to set and get custom data from timer data. */
+/* Functions return EINVAL if passed in argument is invalid. */
+int elapi_set_tm_priv(struct elapi_tm_data *tm_data,
+ void *priv_data_to_set);
+int elapi_get_tm_priv(struct elapi_tm_data *tm_data,
+ void **priv_data_to_get);
+/* Cleanup function */
+int elapi_destroy_tm_data(struct elapi_tm_data *tm_data);
+
+/* Public interfaces ELAPI exposes to handle fd or timer
+ * events (do not confuse with log events).
+ */
+int elapi_process_fd(struct elapi_fd_data *fd_data);
+int elapi_process_tm(struct elapi_tm_data *tm_data);
+
+/* Signature of the function to add
+ * file descriptor into the event loop.
+ * Provided by caller of the ELAPI interface.
*/
-typedef int (*elapi_fd_callback)(int fd, /* File descriptor */
- void *elapi_data); /* ELAPI supplied data */
+typedef int (*elapi_add_fd)(int fd,
+ unsigned flags,
+ struct elapi_fd_data *fd_data,
+ void *ext_fd_data);
-/* Signature ELAPI callback function that
- * should be called when the event loop got a timer driven event.
+/* Signature of the function to remove
+ * file descriptor from the event loop.
+ * Provided by caller of the ELAPI interface.
*/
-typedef int (*elapi_timer_callback)(void *elapi_data); /* ELAPI supplied data */
+typedef int (*elapi_rem_fd)(int fd,
+ struct elapi_fd_data *fd_data,
+ void *ext_fd_data);
-/* Signature of the supplied by caller function that ELAPI
- * will call to add the fd into the application event processing loop.
+/* Signature of the function to set
+ * file descriptor for read/write operation.
+ * Provided by caller of the ELAPI interface.
*/
-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_set_fd)(int fd,
+ unsigned flags,
+ struct elapi_fd_data *fd_data,
+ void *ext_fd_data);
+
+
+/* Signature of the function to add timer.
+ * Provided by caller of the ELAPI interface.
+ * Caller must be aware that the timeval strcuture
+ * is allocated on stack.
*/
-typedef int (*elapi_rem_fd)(int fd, /* File descriptor to add */
- void *callers_data); /* Data that the function
- * would need to do its work */
+typedef int (*elapi_add_tm)(struct timeval *tv,
+ struct elapi_tm_data *tm_data,
+ void *ext_tm_data);
-/* Signature of the supplied by caller function that ELAPI
- * will call to add a new timer event to the application event processing loop.
+/* Signature of the function to add timer.
+ * Provided by caller of the ELAPI interface.
+ * Caller must be aware that the timeval strcuture
+ * is allocated on stack.
*/
-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 */
+typedef int (*elapi_rem_tm)(struct elapi_tm_data *tm_data,
+ void *ext_tm_data);
+/* Structure that contains the pointer to functions
+ * that needed to be provided to enable async processing.
+ */
+struct elapi_async_ctx {
+ elapi_add_fd add_fd_cb;
+ elapi_rem_fd rem_fd_cb;
+ elapi_set_fd set_fd_cb;
+ void *ext_fd_data;
+ elapi_add_tm add_tm_cb;
+ elapi_rem_tm rem_tm_cb;
+ void *ext_tm_data;
+};
+
+/* Interface to create the async context */
+int elapi_create_asctx(struct elapi_async_ctx **ctx,
+ elapi_add_fd add_fd_cb,
+ elapi_rem_fd rem_fd_cb,
+ elapi_set_fd set_fd_cb,
+ void *ext_fd_data,
+ elapi_add_tm add_tm_cb,
+ elapi_rem_tm rem_tm_cb,
+ void *ext_tm_data);
+
+/* Function to free the async context */
+void elapi_destroy_asctx(struct elapi_async_ctx *ctx);
+/* Function to validate the consistency of the
+ * async context */
+int elapi_check_asctx(struct elapi_async_ctx *ctx);
#endif
diff --git a/common/elapi/elapi_log.c b/common/elapi/elapi_log.c
index 67f6e386..291527bf 100644
--- a/common/elapi/elapi_log.c
+++ b/common/elapi/elapi_log.c
@@ -102,10 +102,7 @@ static int elapi_dsp_msg_with_vargs(uint32_t target,
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_async_ctx *async_ctx)
{
struct elapi_dispatcher *handle = NULL;
struct collection_item *error_set = NULL;
@@ -114,7 +111,6 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
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");
@@ -132,20 +128,7 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
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;
- }
+ /* FIXME: Check if context is valid */
/* Check what is passed in the config_path */
if (config_path) {
@@ -264,13 +247,20 @@ int elapi_create_dispatcher_adv(struct elapi_dispatcher **dispatcher,
}
/* Populate async processing data if any */
- if (prm_cnt) {
+ if (async_ctx) {
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;
+ handle->async_ctx = malloc(sizeof(struct elapi_async_ctx));
+ if (handle->async_ctx != NULL) {
+ TRACE_ERROR_NUMBER("Failed to allocate async context", ENOMEM);
+ elapi_destroy_dispatcher(handle);
+ return ENOMEM;
+ }
+ /* Copy async data */
+ memcpy(handle->async_ctx, async_ctx, sizeof(struct elapi_async_ctx));
+ }
+ else {
+ TRACE_INFO_STRING("No async data present", "");
+ handle->async_ctx = NULL;
}
*dispatcher = handle;
@@ -293,9 +283,6 @@ int elapi_create_dispatcher(struct elapi_dispatcher **dispatcher,
error = elapi_create_dispatcher_adv(dispatcher,
appname,
config_path,
- NULL,
- NULL,
- NULL,
NULL);
TRACE_FLOW_STRING("elapi_create_dispatcher", "Exit.");
@@ -335,6 +322,8 @@ void elapi_destroy_dispatcher(struct elapi_dispatcher *dispatcher)
TRACE_INFO_STRING("Freeing application name.", "");
free(dispatcher->appname);
+ TRACE_INFO_STRING("Freeing async context.", "");
+ free(dispatcher->async_ctx);
TRACE_INFO_STRING("Freeing config.", "");
free_ini_config(dispatcher->ini_config);
TRACE_INFO_STRING("Deleting targets name array.", "");
diff --git a/common/elapi/elapi_log.h b/common/elapi/elapi_log.h
index 7d8a3b7d..7d783553 100644
--- a/common/elapi/elapi_log.h
+++ b/common/elapi/elapi_log.h
@@ -52,10 +52,7 @@ int elapi_create_dispatcher(struct elapi_dispatcher **dispatcher, /* Handle of
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. */
+ struct elapi_async_ctx *async_ctx); /* Async context. */
/* Function to clean memory associated with the dispatcher */
void elapi_destroy_dispatcher(struct elapi_dispatcher *dispatcher);
diff --git a/common/elapi/elapi_priv.h b/common/elapi/elapi_priv.h
index 081fae8d..fb8cd3e8 100644
--- a/common/elapi/elapi_priv.h
+++ b/common/elapi/elapi_priv.h
@@ -61,17 +61,19 @@
/* Names of embedded providers */
#define ELAPI_EMB_PRVDR_FILE "file"
-#define ELAPI_EMB_PRVDR_STDERR "stderr"
#define ELAPI_EMB_PRVDR_SYSLOG "syslog"
/* Numbers for embedded providers */
#define ELAPI_EMB_PRVDR_FILENUM 0
-#define ELAPI_EMB_PRVDR_STDERRNUM 1
-#define ELAPI_EMB_PRVDR_SYSLOGNUM 2
-
+#define ELAPI_EMB_PRVDR_SYSLOGNUM 1
#define ELAPI_TARGET_ALL 0xFFFF /* 65k targets should be enough */
+/* Possible values for onerror config parameter */
+#define ELAPI_ONERROR_REVIVE 0
+#define ELAPI_ONERROR_DISABLE 1
+
+
struct elapi_dispatcher {
/* Application name */
char *appname;
@@ -88,11 +90,13 @@ struct elapi_dispatcher {
/* 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;
+ struct elapi_async_ctx *async_ctx;
+ /* Indicator of our synch mode
+ * FIXME: Do we need it?
+ */
uint32_t async_mode;
+ /* Time offset */
+ int32_t offset;
};
/* Structure to pass data from logging function to targets */
@@ -120,7 +124,7 @@ struct elapi_tgt_ctx {
*/
};
-/* FIXME: Compbine with context */
+/* Structure that hols sink's error status */
struct sink_status {
int suspended;
time_t lasttry;
@@ -145,12 +149,20 @@ struct elapi_sink_ctx {
struct collection_item *in_queue;
/* Pending list */
struct collection_item *pending;
- /* FIXME: add:
- * sink's error status
- */
+ /* Sink's error status */
+ struct sink_status status;
+ /* Synch/asynch mode */
uint32_t async_mode;
/* Sink configuration data */
struct elapi_sink_cfg sink_cfg;
+ /* Back pointer to the target context.
+ * This is needed for the cases
+ * when we detect that sink
+ * is failed and we need
+ * to fail over for the next one.
+ */
+ struct elapi_tgt_ctx *tgt_ctx;
+
};
/* The structure to hold the event and its context */
@@ -161,11 +173,31 @@ struct elapi_sink_ctx {
* instead of the actual event.
*/
struct elapi_event_ctx {
- struct collection_item *event;
- /* FIXME: other things:
- * time stamp
- * resolved message
+ /* This is a copy of the event */
+ /* We have to copy it for two reasons:
+ * a) It needs to be flattened so
+ * that we do not get unnecesary naming
+ * collisions if same key appears on different
+ * levels
+ * b) In case of async logging we need
+ * the original event until we are sure
+ * it is actually logged. If we do not
+ * keep it around the application can modify
+ * it or delete it before we figured out
+ * that sink is broken and we need to fail over.
+ * If in this case we go to another sink
+ * and if we do not have the original event
+ * we are screwed.
*/
+ struct collection_item *event;
+ /* Reference count */
+ int refcount;
+ /* Event time */
+ time_t tm;
+ /* Resolved message */
+ char *message;
+ /* Time offset */
+ int32_t offset;
};
/* Lookup structure for searching for providers */
diff --git a/common/elapi/elapi_sink.h b/common/elapi/elapi_sink.h
index b7287213..03e681a5 100644
--- a/common/elapi/elapi_sink.h
+++ b/common/elapi/elapi_sink.h
@@ -32,11 +32,6 @@
#define SINK_ENTRY_POINT "get_sink_info"
#define SINK_NAME_TEMPLATE "libelapi_sink_%s.so"
-/* 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 provider per process */
-
-
/* Log facility callbacks */
/* FIXME - the signatures need to take into the account async processing */
typedef int (*init_fn)(void **priv_ctx,
diff --git a/common/elapi/elapi_test/elapi_ut.conf b/common/elapi/elapi_test/elapi_ut.conf
index 00b5912a..a42045a2 100644
--- a/common/elapi/elapi_test/elapi_ut.conf
+++ b/common/elapi/elapi_test/elapi_ut.conf
@@ -63,7 +63,6 @@ sinks = logfile, syslog
;
; Special sinks provided by ELAPI are:
; file
-; stderr
; syslog
;
; Example:
@@ -100,9 +99,9 @@ sinks = logfile, syslog
; of the sinks that act in the synch mode and guarantee
; the delivery or return failure.
-; SPECIFIC FIELDS FOR DIFFERENT SINKS
+; SPECIFIC CONFIGURATION PARAMETERS FOR DIFFERENT PROVIDERS
;
-; 1) FILE SINK
+; 1) FILE PROVIDER
;
; filename - name of the log file. If not specified <appname>.log will be used.
; Avoid using the same name of the file for different sinks,
@@ -142,6 +141,17 @@ sinks = logfile, syslog
; If this value is missing or 0 - no flushing.
; If it is positive it denotes the number of events before next flush.
; If it is negative it denotes the number of seconds before next flush.
+; Ignored if file is opened and closed each time.
+;
+; marker - (optional)
+; Default is "\n".
+; Marker specifies a line that will be inserted into the file to denote
+; the beginning of a new run. The provided string is used as is
+; as a format argument for the strftime() function. The string can
+; contain zero or one time stamp format specifier listed in a man page
+; for the strftime function(). Providing an invalid marker can
+; potentially cause your application to crash.
+;
;
; Format specific parameters:
;