From: Timo Sirainen Date: Thu, 23 Jan 2025 21:30:01 +0000 (+0200) Subject: lib-settings: Change service filtering optimization to use settings_filter_name X-Git-Tag: 2.4.1~258 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ccbcf5d43e7e737111be42e7cbfc253e6a74269;p=thirdparty%2Fdovecot%2Fcore.git lib-settings: Change service filtering optimization to use settings_filter_name --- diff --git a/src/lib-settings/settings.c b/src/lib-settings/settings.c index 22077463fa..bf0d6ca805 100644 --- a/src/lib-settings/settings.c +++ b/src/lib-settings/settings.c @@ -251,6 +251,56 @@ settings_block_read_str(struct settings_mmap *mmap, return 0; } +static bool +settings_filter_node_match_service(struct event_filter_node *node, + const char *service_name, bool op_not) +{ + const char *node_service; + + /* Not perfect logic, but enough for the settings filters */ + switch (node->op) { + case EVENT_FILTER_OP_CMP_EQ: + if (node->type == EVENT_FILTER_NODE_TYPE_EVENT_FIELD_EXACT && + strcmp(node->field.key, SETTINGS_EVENT_FILTER_NAME) == 0 && + node->field.value_type == EVENT_FIELD_VALUE_TYPE_STR && + str_begins(node->field.value.str, "service/", &node_service)) { + bool match = strcmp(node_service, service_name) == 0; + return match != op_not; + } + break; + case EVENT_FILTER_OP_AND: + if (!settings_filter_node_match_service(node->children[0], + service_name, op_not) || + !settings_filter_node_match_service(node->children[1], + service_name, op_not)) + return FALSE; + break; + case EVENT_FILTER_OP_OR: + if (!settings_filter_node_match_service(node->children[0], + service_name, op_not) && + !settings_filter_node_match_service(node->children[1], + service_name, op_not)) + return FALSE; + break; + case EVENT_FILTER_OP_NOT: + return settings_filter_node_match_service(node->children[0], + service_name, !op_not); + default: + break; + } + return TRUE; +} + +static bool +settings_filter_match_service(struct event_filter *filter, + const char *service_name) +{ + struct event_filter_node *node = event_filter_get_root_node(filter, 0); + i_assert(node != NULL); + i_assert(event_filter_get_root_node(filter, 1) == NULL); + return settings_filter_node_match_service(node, service_name, FALSE); +} + static int settings_read_filters(struct settings_mmap *mmap, const char *service_name, enum settings_read_flags flags, size_t *offset, @@ -313,9 +363,8 @@ settings_read_filters(struct settings_mmap *mmap, const char *service_name, continue; } } - value = event_filter_find_field_exact(tmp_filter, "service", &op_not); - if (value != NULL && service_name != NULL && - (strcmp(value, service_name) == 0) == op_not) { + if (service_name != NULL && + !settings_filter_match_service(tmp_filter, service_name)) { /* service name doesn't match */ *filter_dest = EVENT_FILTER_MATCH_NEVER; event_filter_unref(&tmp_filter);