]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add event_filter_register_cmp()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 4 Mar 2025 14:10:14 +0000 (16:10 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 6 Mar 2025 06:12:52 +0000 (06:12 +0000)
src/lib/event-filter-private.h
src/lib/event-filter.c
src/lib/event-filter.h
src/lib/test-event-filter-expr.c

index 324222820982616f6695951498a75f02624a630d..3c0edbce032eaa2058ceef2238996e7d6e6727f0 100644 (file)
@@ -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);
index 5b397b1d85537d2e1d4b4cc69041080d4a393784..fd4f730d80e738aae637a71f1a0095eabaaeadf9 100644 (file)
@@ -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,
index b00c4a5ca3433b885e512f546fb9a18dbfe7f74a..9c8529f63bf74526f7a995c30934af005383b9f2 100644 (file)
@@ -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);
 
index 7e9b85b963285eaac4a3bc5f2c259733d73cc0d1..1a14451fddc26d76e815df8875611bb6e8d79171 100644 (file)
@@ -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),