From: Stephan Bosch Date: Sat, 19 Aug 2023 17:46:27 +0000 (+0200) Subject: lib: lib-event - Add support for iterating the full ancestral tree of an event's... X-Git-Tag: 2.4.0~2400 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40333adb8015536c3898a4c4f1a10c898dd03cae;p=thirdparty%2Fdovecot%2Fcore.git lib: lib-event - Add support for iterating the full ancestral tree of an event's categories --- diff --git a/src/lib/lib-event.c b/src/lib/lib-event.c index 8c40848ba9..33a3e64cae 100644 --- a/src/lib/lib-event.c +++ b/src/lib/lib-event.c @@ -4,6 +4,7 @@ #include "lib-event-private.h" #include "event-filter.h" #include "array.h" +#include "hash.h" #include "llist.h" #include "time-util.h" #include "str.h" @@ -12,6 +13,8 @@ #include +HASH_TABLE_DEFINE_TYPE(category_set, void *, const struct event_category *); + enum event_code { EVENT_CODE_ALWAYS_LOG_SOURCE = 'a', EVENT_CODE_CATEGORY = 'c', @@ -62,6 +65,11 @@ struct event_reason { struct event *event; }; +struct event_category_iterator { + HASH_TABLE_TYPE(category_set) hash; + struct hash_iterate_context *iter; +}; + extern struct event_passthrough event_passthrough_vfuncs; static struct event *events = NULL; @@ -1257,6 +1265,67 @@ event_get_categories(const struct event *event, unsigned int *count_r) return array_get(&event->categories, count_r); } +static void +insert_category(HASH_TABLE_TYPE(category_set) hash, + const struct event_category *const cat) +{ + /* insert this category (key == the unique internal pointer) */ + hash_table_update(hash, cat->internal, cat); + + /* insert parent's categories */ + if (cat->parent != NULL) + insert_category(hash, cat->parent); +} + +struct event_category_iterator * +event_categories_iterate_init(const struct event *event) +{ + struct event_category_iterator *iter; + struct event_category *const *cats; + unsigned int count, i; + + cats = event_get_categories(event, &count); + if (count == 0) + return NULL; + + iter = i_new(struct event_category_iterator, 1); + + hash_table_create_direct(&iter->hash, default_pool, + 3 * count /* estimate */); + + /* Insert all the categories into the hash table */ + for (i = 0; i < count; i++) + insert_category(iter->hash, cats[i]); + + iter->iter = hash_table_iterate_init(iter->hash); + + return iter; +} + +bool event_categories_iterate(struct event_category_iterator *iter, + const struct event_category **cat_r) +{ + void *key ATTR_UNUSED; + + if (iter == NULL) { + *cat_r = NULL; + return FALSE; + } + return hash_table_iterate(iter->iter, iter->hash, &key, cat_r); +} + +void event_categories_iterate_deinit(struct event_category_iterator **_iter) +{ + struct event_category_iterator *iter = *_iter; + + if (iter == NULL) + return; + *_iter = NULL; + + hash_table_iterate_deinit(&iter->iter); + hash_table_destroy(&iter->hash); +} + void event_send(struct event *event, struct failure_context *ctx, const char *fmt, ...) { diff --git a/src/lib/lib-event.h b/src/lib/lib-event.h index b3bdf05302..ebf15341cd 100644 --- a/src/lib/lib-event.h +++ b/src/lib/lib-event.h @@ -10,6 +10,7 @@ struct event; struct event_log_params; +struct event_category_iterator; /* Hierarchical category of events. Each event can belong to multiple categories. For example [ lib-storage/maildir, syscall/io ]. The categories @@ -421,6 +422,20 @@ event_get_fields(const struct event *event, unsigned int *count_r); struct event_category *const * event_get_categories(const struct event *event, unsigned int *count_r); +/* Iterator for scanning through all categories of the event, including the + parents and higher ancestry of the categories directly associated with this + event. Note that this does not include the categories of any parent event. To + avoid useless allocation of an iterator, the event_categories_iterate_init() + function returns NULL if no categories are associated with this event. The + event_categories_iterate() and event_categories_iterate_deinit() functions + safely handle this NULL iterator. + */ +struct event_category_iterator * +event_categories_iterate_init(const struct event *event); +bool event_categories_iterate(struct event_category_iterator *iter, + const struct event_category **cat_r); +void event_categories_iterate_deinit(struct event_category_iterator **_iter); + /* Export the event into a tabescaped string, so its fields are separated with TABs and there are no NUL, CR or LF characters. */ void event_export(const struct event *event, string_t *dest);