From: Timo Sirainen Date: Tue, 4 Mar 2025 14:10:14 +0000 (+0200) Subject: lib: Add event_filter_register_cmp() X-Git-Tag: 2.4.1~106 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4529add38896e6e51dea9948aaedaaa3a003d70c;p=thirdparty%2Fdovecot%2Fcore.git lib: Add event_filter_register_cmp() --- diff --git a/src/lib/event-filter-private.h b/src/lib/event-filter-private.h index 3242228209..3c0edbce03 100644 --- a/src/lib/event-filter-private.h +++ b/src/lib/event-filter-private.h @@ -24,6 +24,9 @@ struct event_filter { int refcount; ARRAY(struct event_filter_query_internal) queries; + const char *cmp_key; + event_filter_cmp *cmp_key_func; + bool fragment; bool named_queries_only; }; @@ -122,7 +125,8 @@ event_filter_get_root_node(struct event_filter *filter, unsigned int idx); /* the following are exposed to allow for unit testing */ bool -event_filter_query_match_eval(struct event_filter_node *node, +event_filter_query_match_eval(struct event_filter *filter, + struct event_filter_node *node, struct event *event, const char *source_filename, unsigned int source_linenum, enum event_filter_log_type log_type); diff --git a/src/lib/event-filter.c b/src/lib/event-filter.c index 5b397b1d85..fd4f730d80 100644 --- a/src/lib/event-filter.c +++ b/src/lib/event-filter.c @@ -784,9 +784,9 @@ event_filter_handle_numeric_operation(enum event_filter_node_op op, } static bool -event_match_field(struct event *event, struct event_filter_node *node, - bool use_strcmp, const char *source_filename, - unsigned int source_linenum) +event_match_field(struct event_filter *filter, struct event *event, + struct event_filter_node *node, bool use_strcmp, + const char *source_filename, unsigned int source_linenum) { const struct event_field *field; struct event_field duration; @@ -841,7 +841,13 @@ event_match_field(struct event *event, struct event_filter_node *node, wanted_field->value.str[0] == '\0'; } T_BEGIN { - ret = cmp_value(field->value.str, wanted_field, cmp_flags); + if (filter->cmp_key != NULL && + strcmp(wanted_field->key, filter->cmp_key) == 0) { + ret = filter->cmp_key_func(field->value.str, + wanted_field_value_str(wanted_field)); + } else { + ret = cmp_value(field->value.str, wanted_field, cmp_flags); + } } T_END; return ret; case EVENT_FIELD_VALUE_TYPE_INTMAX: @@ -995,7 +1001,8 @@ event_match_field(struct event *event, struct event_filter_node *node, } static bool -event_filter_query_match_cmp(struct event_filter_node *node, +event_filter_query_match_cmp(struct event_filter *filter, + struct event_filter_node *node, struct event *event, const char *source_filename, unsigned int source_linenum, enum event_filter_log_type log_type) @@ -1030,17 +1037,20 @@ event_filter_query_match_cmp(struct event_filter_node *node, case EVENT_FILTER_NODE_TYPE_EVENT_CATEGORY: return event_has_category(event, node, log_type); case EVENT_FILTER_NODE_TYPE_EVENT_FIELD_EXACT: - return event_match_field(event, node, TRUE, source_filename, source_linenum); + return event_match_field(filter, event, node, TRUE, + source_filename, source_linenum); case EVENT_FILTER_NODE_TYPE_EVENT_FIELD_WILDCARD: case EVENT_FILTER_NODE_TYPE_EVENT_FIELD_NUMERIC_WILDCARD: - return event_match_field(event, node, FALSE, source_filename, source_linenum); + return event_match_field(filter, event, node, FALSE, + source_filename, source_linenum); } i_unreached(); } bool -event_filter_query_match_eval(struct event_filter_node *node, +event_filter_query_match_eval(struct event_filter *filter, + struct event_filter_node *node, struct event *event, const char *source_filename, unsigned int source_linenum, enum event_filter_log_type log_type) @@ -1051,33 +1061,29 @@ event_filter_query_match_eval(struct event_filter_node *node, case EVENT_FILTER_OP_CMP_LT: case EVENT_FILTER_OP_CMP_GE: case EVENT_FILTER_OP_CMP_LE: - return event_filter_query_match_cmp(node, event, source_filename, - source_linenum, log_type); + return event_filter_query_match_cmp(filter, node, event, + source_filename, source_linenum, log_type); case EVENT_FILTER_OP_AND: - return event_filter_query_match_eval(node->children[0], event, - source_filename, source_linenum, - log_type) && - event_filter_query_match_eval(node->children[1], event, - source_filename, source_linenum, - log_type); + return event_filter_query_match_eval(filter, node->children[0], + event, source_filename, source_linenum, log_type) && + event_filter_query_match_eval(filter, node->children[1], + event, source_filename, source_linenum, log_type); case EVENT_FILTER_OP_OR: - return event_filter_query_match_eval(node->children[0], event, - source_filename, source_linenum, - log_type) || - event_filter_query_match_eval(node->children[1], event, - source_filename, source_linenum, - log_type); + return event_filter_query_match_eval(filter, node->children[0], + event, source_filename, source_linenum, log_type) || + event_filter_query_match_eval(filter, node->children[1], + event, source_filename, source_linenum, log_type); case EVENT_FILTER_OP_NOT: - return !event_filter_query_match_eval(node->children[0], event, - source_filename, source_linenum, - log_type); + return !event_filter_query_match_eval(filter, node->children[0], + event, source_filename, source_linenum, log_type); } i_unreached(); } static bool -event_filter_query_match(const struct event_filter_query_internal *query, +event_filter_query_match(struct event_filter *filter, + const struct event_filter_query_internal *query, struct event *event, const char *source_filename, unsigned int source_linenum, const struct failure_context *ctx) @@ -1087,8 +1093,9 @@ event_filter_query_match(const struct event_filter_query_internal *query, i_assert(ctx->type < N_ELEMENTS(event_filter_log_type_map)); log_type = event_filter_log_type_map[ctx->type].log_type; - return event_filter_query_match_eval(query->expr, event, source_filename, - source_linenum, log_type); + return event_filter_query_match_eval(filter, query->expr, event, + source_filename, source_linenum, + log_type); } static bool @@ -1125,8 +1132,9 @@ bool event_filter_match_source(struct event_filter *filter, struct event *event, return FALSE; array_foreach(&filter->queries, query) { - if (event_filter_query_match(query, event, source_filename, - source_linenum, ctx)) + if (event_filter_query_match(filter, query, event, + source_filename, source_linenum, + ctx)) return TRUE; } return FALSE; @@ -1179,7 +1187,7 @@ void *event_filter_match_iter_next(struct event_filter_match_iter *iter) iter->idx++; if (query->context != NULL && - event_filter_query_match(query, iter->event, + event_filter_query_match(iter->filter, query, iter->event, iter->event->source_filename, iter->event->source_linenum, iter->failure_ctx)) @@ -1196,6 +1204,16 @@ void event_filter_match_iter_deinit(struct event_filter_match_iter **_iter) i_free(iter); } +void event_filter_register_cmp(struct event_filter *filter, const char *key, + event_filter_cmp *cmp) +{ + /* for now we need to support just one */ + i_assert(filter->cmp_key == NULL); + + filter->cmp_key = p_strdup(filter->pool, key); + filter->cmp_key_func = cmp; +} + static void event_filter_query_update_category(struct event_filter_query_internal *query, struct event_filter_node *node, diff --git a/src/lib/event-filter.h b/src/lib/event-filter.h index b00c4a5ca3..9c8529f63b 100644 --- a/src/lib/event-filter.h +++ b/src/lib/event-filter.h @@ -13,6 +13,8 @@ struct event_filter_field { const char *value; }; +typedef bool event_filter_cmp(const char *value, const char *wanted_field); + struct event_filter *event_filter_create(void); struct event_filter *event_filter_create_with_pool(pool_t pool); struct event_filter *event_filter_create_fragment(pool_t pool); @@ -77,6 +79,11 @@ event_filter_match_iter_init(struct event_filter *filter, struct event *event, void *event_filter_match_iter_next(struct event_filter_match_iter *iter); void event_filter_match_iter_deinit(struct event_filter_match_iter **iter); +/* Register a comparator function for the key. event_filter_match() will use + this function when matching the values for the key. */ +void event_filter_register_cmp(struct event_filter *filter, const char *key, + event_filter_cmp *cmp); + void event_filter_init(void); void event_filter_deinit(void); diff --git a/src/lib/test-event-filter-expr.c b/src/lib/test-event-filter-expr.c index 7e9b85b963..1a14451fdd 100644 --- a/src/lib/test-event-filter-expr.c +++ b/src/lib/test-event-filter-expr.c @@ -28,7 +28,7 @@ static void check_expr(const char *test_name, test_out_quiet(t_strdup_printf("%s:num_queries==1", test_name), num_queries == 1); /* should have only one query */ - got = event_filter_query_match_eval(expr, event, + got = event_filter_query_match_eval(filter, expr, event, SOURCE_FILENAME, SOURCE_LINE, log_type); test_out_quiet(t_strdup_printf("%s:got=expected", test_name),