lib-event.c revision b8a1347a9ea2cecf0d16f24748c2600fea8c7158
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib-event-private.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "array.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "llist.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "str.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "strescape.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ioloop.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenextern const struct event_passthrough event_passthrough_vfuncs;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic struct event *events = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic struct event *current_global_event = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic struct event_passthrough *event_last_passthrough = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic ARRAY(event_callback_t *) event_handlers;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic ARRAY(event_category_callback_t *) event_category_callbacks;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic ARRAY(struct event_category *) event_registered_categories;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic ARRAY(struct event *) global_event_stack;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic uint64_t event_id_counter = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic struct event *last_passthrough_event(void)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return container_of(event_last_passthrough,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event, event_passthrough);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic void event_copy_parent_defaults(struct event *event,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const struct event *parent)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->always_log_source = parent->always_log_source;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->passthrough = parent->passthrough;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->forced_debug = parent->forced_debug;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#undef event_create
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct event *event_create(struct event *parent, const char *source_filename,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen unsigned int source_linenum)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event *event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen pool_t pool = pool_alloconly_create(MEMPOOL_GROWING"event", 64);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event = p_new(pool, struct event, 1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->event_passthrough = event_passthrough_vfuncs;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->refcount = 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->id = ++event_id_counter;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->pool = pool;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->tv_created = ioloop_timeval;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->source_filename = source_filename;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->source_linenum = source_linenum;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (parent != NULL) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->parent = parent;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event_ref(event->parent);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event_copy_parent_defaults(event, parent);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DLLIST_PREPEND(&events, event);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return event;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#undef event_create_passthrough
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct event_passthrough *
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenevent_create_passthrough(struct event *parent, const char *source_filename,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int source_linenum)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!parent->passthrough) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (event_last_passthrough != NULL) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* API is being used in a wrong or dangerous way */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_panic("Can't create multiple passthrough events - finish the earlier with ->event()");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct event *event =
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event_create(parent, source_filename, source_linenum);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->passthrough = TRUE;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* This event only intends to extend the parent event.
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen Use the parent's creation timestamp. */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->tv_created = parent->tv_created;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event_last_passthrough = &event->event_passthrough;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen } else {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event_last_passthrough = &parent->event_passthrough;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return event_last_passthrough;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic bool
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_send_callbacks(struct event *event, enum event_callback_type type,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct failure_context *ctx, const char *fmt, va_list args)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_callback_t *const *callbackp;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen array_foreach(&event_handlers, callbackp) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen bool ret;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen T_BEGIN {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = (*callbackp)(event, type, ctx, fmt, args);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen } T_END;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (!ret) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* event sending was stopped */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return FALSE;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return TRUE;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct event *event_ref(struct event *event)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_assert(event->refcount > 0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen event->refcount++;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return event;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenvoid event_unref(struct event **_event)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct event *event = *_event;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (event == NULL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen *_event = NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_assert(event->refcount > 0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (--event->refcount > 0)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_assert(event != current_global_event);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (event->call_free) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen va_list empty;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen (void)event_send_callbacks(event, EVENT_CALLBACK_TYPE_FREE,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen NULL, NULL, empty);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (last_passthrough_event() == event)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_last_passthrough = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (event->log_prefix_from_system_pool)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_free(event->log_prefix);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_free(event->sending_name);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_unref(&event->parent);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen DLLIST_REMOVE(&events, event);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pool_unref(&event->pool);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct event *events_get_head(void)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return events;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *event_push_global(struct event *event)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (current_global_event != NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!array_is_created(&global_event_stack))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_array_init(&global_event_stack, 4);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen array_append(&global_event_stack, &current_global_event, 1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen current_global_event = event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *event_pop_global(struct event *event)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_assert(event != NULL);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_assert(event == current_global_event);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!array_is_created(&global_event_stack) ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen array_count(&global_event_stack) == 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen current_global_event = NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen unsigned int event_count;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event *const *events =
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen array_get(&global_event_stack, &event_count);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_assert(event_count > 0);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen current_global_event = events[event_count-1];
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen array_delete(&global_event_stack, event_count-1, 1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return current_global_event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *event_get_global(void)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return current_global_event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic struct event *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_set_log_prefix(struct event *event, const char *prefix, bool append)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (event->log_prefix == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* allocate the first log prefix from the pool */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->log_prefix = p_strdup(event->pool, prefix);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* log prefix is being updated multiple times -
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen switch to system pool so we don't keep leaking memory */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (event->log_prefix_from_system_pool)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_free(event->log_prefix);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->log_prefix_from_system_pool = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->log_prefix = i_strdup(prefix);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->log_prefix_replace = !append;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_set_append_log_prefix(struct event *event, const char *prefix)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event_set_log_prefix(event, prefix, TRUE);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *event_replace_log_prefix(struct event *event, const char *prefix)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event_set_log_prefix(event, prefix, FALSE);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_set_name(struct event *event, const char *name)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_free(event->sending_name);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->sending_name = i_strdup(name);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_set_source(struct event *event, const char *filename,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen unsigned int linenum, bool literal_fname)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->source_filename = literal_fname ? filename :
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen p_strdup(event->pool, filename);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->source_linenum = linenum;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *event_set_always_log_source(struct event *event)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event->always_log_source = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct event_category *event_category_find_registered(const char *name)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct event_category *const *catp;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen array_foreach(&event_registered_categories, catp) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (strcmp((*catp)->name, name) == 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return *catp;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event_category *const *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_get_registered_categories(unsigned int *count_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return array_get(&event_registered_categories, count_r);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic void event_category_register(struct event_category *category)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_category_callback_t *const *callbackp;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (category->registered)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* register parent categories first */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (category->parent != NULL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_category_register(category->parent);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen category->registered = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen array_append(&event_registered_categories, &category, 1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen array_foreach(&event_category_callbacks, callbackp) T_BEGIN {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen (*callbackp)(category);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } T_END;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic bool
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_find_category(struct event *event, const struct event_category *category)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct event_category *const *categoryp;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen array_foreach(&event->categories, categoryp) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (*categoryp == category)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return FALSE;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct event *
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenevent_add_categories(struct event *event,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct event_category *const *categories)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!array_is_created(&event->categories))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen p_array_init(&event->categories, event->pool, 4);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen for (unsigned int i = 0; categories[i] != NULL; i++) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event_category_register(categories[i]);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!event_find_category(event, categories[i]))
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen array_append(&event->categories, &categories[i], 1);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return event;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct event *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_add_category(struct event *event, struct event_category *category)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event_category *const categories[] = { category, NULL };
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return event_add_categories(event, categories);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic struct event_field *
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenevent_find_field_int(struct event *event, const char *key)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct event_field *field;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (!array_is_created(&event->fields))
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen array_foreach_modifiable(&event->fields, field) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (strcmp(field->key, key) == 0)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return field;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenconst struct event_field *
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenevent_find_field(struct event *event, const char *key)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const struct event_field *field = event_find_field_int(event, key);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (field != NULL || event->parent == NULL)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return field;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return event_find_field(event->parent, key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenconst char *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_find_field_str(struct event *event, const char *key)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const struct event_field *field;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field = event_find_field(event, key);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (field == NULL)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen switch (field->value_type) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen case EVENT_FIELD_VALUE_TYPE_STR:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return field->value.str;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen case EVENT_FIELD_VALUE_TYPE_INTMAX:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return dec2str(field->value.intmax);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen case EVENT_FIELD_VALUE_TYPE_TIMEVAL:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return t_strdup_printf("%"PRIdTIME_T".%u",
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field->value.timeval.tv_sec,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen (unsigned int)field->value.timeval.tv_usec);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_unreached();
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic struct event_field *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_get_field(struct event *event, const char *key)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct event_field *field;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field = event_find_field_int(event, key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (field == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (!array_is_created(&event->fields))
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_array_init(&event->fields, event->pool, 8);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field = array_append_space(&event->fields);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field->key = p_strdup(event->pool, key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return field;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct event *
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenevent_add_str(struct event *event, const char *key, const char *value)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event_field *field;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field = event_get_field(event, key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field->value_type = EVENT_FIELD_VALUE_TYPE_STR;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_zero(&field->value);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field->value.str = p_strdup(event->pool, value);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_add_int(struct event *event, const char *key, intmax_t num)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event_field *field;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field = event_get_field(event, key);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field->value_type = EVENT_FIELD_VALUE_TYPE_INTMAX;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_zero(&field->value);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen field->value.intmax = num;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return event;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct event *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_add_timeval(struct event *event, const char *key,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const struct timeval *tv)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct event_field *field;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field = event_get_field(event, key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field->value_type = EVENT_FIELD_VALUE_TYPE_TIMEVAL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_zero(&field->value);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen field->value.timeval = *tv;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return event;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct event *
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainenevent_add_fields(struct event *event,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const struct event_add_field *fields)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen for (unsigned int i = 0; fields[i].key != NULL; i++) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fields[i].value != NULL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_add_str(event, fields[i].key, fields[i].value);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else if (fields[i].value_timeval.tv_sec != 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_add_timeval(event, fields[i].key, &fields[i].value_timeval);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event_add_int(event, fields[i].key, fields[i].value_intmax);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return event;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct event *event_get_parent(struct event *event)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return event->parent;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenvoid event_get_create_time(struct event *event, struct timeval *tv_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *tv_r = event->tv_created;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenbool event_get_last_send_time(struct event *event, struct timeval *tv_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen *tv_r = event->tv_last_sent;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return tv_r->tv_sec != 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenconst struct event_field *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenevent_get_fields(struct event *event, unsigned int *count_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (!array_is_created(&event->fields)) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *count_r = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return array_get(&event->fields, count_r);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct event_category *const *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenevent_get_categories(struct event *event, unsigned int *count_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (!array_is_created(&event->categories)) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *count_r = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return array_get(&event->categories, count_r);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainenvoid event_send(struct event *event, struct failure_context *ctx,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *fmt, va_list args)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen event->tv_last_sent = ioloop_timeval;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (event_send_callbacks(event, EVENT_CALLBACK_TYPE_EVENT,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx, fmt, args))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_log_typev(ctx, fmt, args);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen event_send_abort(event);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenvoid event_send_abort(struct event *event)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* if the event is sent again, it needs a new name */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_free(event->sending_name);
if (event->passthrough)
event_unref(&event);
}
void event_register_callback(event_callback_t *callback)
{
array_append(&event_handlers, &callback, 1);
}
void event_unregister_callback(event_callback_t *callback)
{
event_callback_t *const *callbackp;
array_foreach(&event_handlers, callbackp) {
if (*callbackp == callback) {
array_delete(&event_handlers,
array_foreach_idx(&event_handlers, callbackp), 1);
}
}
i_unreached();
}
void event_category_register_callback(event_category_callback_t *callback)
{
array_append(&event_category_callbacks, &callback, 1);
}
void event_category_unregister_callback(event_category_callback_t *callback)
{
event_category_callback_t *const *callbackp;
array_foreach(&event_category_callbacks, callbackp) {
if (*callbackp == callback) {
array_delete(&event_category_callbacks,
array_foreach_idx(&event_category_callbacks, callbackp), 1);
return;
}
}
i_unreached();
}
static void event_category_remove_from_array(struct event_category *category)
{
struct event_category *const *catp;
array_foreach(&event_registered_categories, catp) {
if (*catp == category) {
array_delete(&event_registered_categories,
array_foreach_idx(&event_registered_categories, catp), 1);
return;
}
}
i_unreached();
}
void event_category_unregister(struct event_category *category)
{
event_category_callback_t *const *callbackp;
if (!category->registered) {
/* it was never registered in the first place - ignore */
return;
}
category->registered = FALSE;
event_category_remove_from_array(category);
array_foreach(&event_category_callbacks, callbackp) T_BEGIN {
(*callbackp)(category);
} T_END;
}
static struct event_passthrough *
event_passthrough_set_append_log_prefix(const char *prefix)
{
event_set_append_log_prefix(last_passthrough_event(), prefix);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_replace_log_prefix(const char *prefix)
{
event_replace_log_prefix(last_passthrough_event(), prefix);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_set_name(const char *name)
{
event_set_name(last_passthrough_event(), name);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_set_source(const char *filename,
unsigned int linenum, bool literal_fname)
{
event_set_source(last_passthrough_event(), filename,
linenum, literal_fname);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_set_always_log_source(void)
{
event_set_always_log_source(last_passthrough_event());
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_add_categories(struct event_category *const *categories)
{
event_add_categories(last_passthrough_event(), categories);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_add_category(struct event_category *category)
{
event_add_category(last_passthrough_event(), category);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_add_fields(const struct event_add_field *fields)
{
event_add_fields(last_passthrough_event(), fields);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_add_str(const char *key, const char *value)
{
event_add_str(last_passthrough_event(), key, value);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_add_int(const char *key, intmax_t num)
{
event_add_int(last_passthrough_event(), key, num);
return event_last_passthrough;
}
static struct event_passthrough *
event_passthrough_add_timeval(const char *key, const struct timeval *tv)
{
event_add_timeval(last_passthrough_event(), key, tv);
return event_last_passthrough;
}
static struct event *event_passthrough_event(void)
{
struct event *event = last_passthrough_event();
event_last_passthrough = NULL;
return event;
}
const struct event_passthrough event_passthrough_vfuncs = {
event_passthrough_set_append_log_prefix,
event_passthrough_replace_log_prefix,
event_passthrough_set_name,
event_passthrough_set_source,
event_passthrough_set_always_log_source,
event_passthrough_add_categories,
event_passthrough_add_category,
event_passthrough_add_fields,
event_passthrough_add_str,
event_passthrough_add_int,
event_passthrough_add_timeval,
event_passthrough_event,
};
void lib_event_init(void)
{
i_array_init(&event_handlers, 4);
i_array_init(&event_category_callbacks, 4);
i_array_init(&event_registered_categories, 16);
}
void lib_event_deinit(void)
{
for (struct event *event = events; event != NULL; event = event->next) {
i_warning("Event %p leaked (parent=%p): %s:%u",
event, event->parent,
event->source_filename, event->source_linenum);
}
array_free(&event_handlers);
array_free(&event_category_callbacks);
array_free(&event_registered_categories);
}