From: Timo Sirainen Date: Thu, 21 Mar 2024 22:25:36 +0000 (+0200) Subject: dict: Support accessing non-legacy dicts X-Git-Tag: 2.4.1~805 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86a5072d58b268caa29fcc5a5225eb41fa1908e2;p=thirdparty%2Fdovecot%2Fcore.git dict: Support accessing non-legacy dicts The dicts can be configured inside dict_server { .. } filter, e.g.: dict_server { dict cassandra { .. } dict cassandra2 { driver = cassandra .. } } --- diff --git a/src/dict/dict-connection.c b/src/dict/dict-connection.c index 95208a09cc..37b2ff69c3 100644 --- a/src/dict/dict-connection.c +++ b/src/dict/dict-connection.c @@ -7,6 +7,7 @@ #include "ostream.h" #include "llist.h" #include "strescape.h" +#include "settings.h" #include "master-service.h" #include "dict-client.h" #include "dict-settings.h" @@ -22,10 +23,6 @@ static int dict_connection_dict_init(struct dict_connection *conn); static void dict_connection_destroy(struct connection *_conn); struct connection_list *dict_connections = NULL; -static struct event_category dict_server_event_category = { - .name = "dict-server", -}; - static int dict_connection_handshake_args(struct connection *_conn, const char *const *args) { @@ -66,28 +63,23 @@ static int dict_connection_handshake_line(struct connection *conn, return dict_connection_handshake_args(conn, args); } -static int dict_connection_dict_init(struct dict_connection *conn) +static int dict_connection_dict_init_legacy(struct dict_connection *conn) { struct dict_legacy_settings dict_set; const char *const *strlist; unsigned int i, count; const char *uri, *error; - if (!array_is_created(&server_settings->legacy_dicts)) { - e_error(conn->conn.event, "No dictionaries configured"); - return -1; - } + if (!array_is_created(&server_settings->legacy_dicts)) + return 0; strlist = array_get(&server_settings->legacy_dicts, &count); for (i = 0; i < count; i += 2) { if (strcmp(strlist[i], conn->name) == 0) break; } - if (i == count) { - e_error(conn->conn.event, "Unconfigured dictionary name '%s'", - conn->name); - return -1; - } + if (i == count) + return 0; event_set_append_log_prefix(conn->conn.event, t_strdup_printf("%s: ", conn->name)); event_add_str(conn->conn.event, "dict_name", conn->name); @@ -103,6 +95,57 @@ static int dict_connection_dict_init(struct dict_connection *conn) conn->name, error); return -1; } + return 1; +} + +static int dict_connection_dict_init_name(struct dict_connection *conn) +{ + struct event *event; + const char *error; + + event_set_append_log_prefix(conn->conn.event, + t_strdup_printf("%s: ", conn->name)); + + /* The dict is persistently cached, so don't use connection's event. */ + event = event_create(master_service_get_event(master_service)); + event_set_append_log_prefix(event, t_strdup_printf("%s: ", conn->name)); + event_add_str(event, "dict_name", conn->name); + + if (dict_init_cache_get(event, conn->name, &conn->dict, &error) < 0) { + e_error(conn->conn.event, "Failed to initialize dictionary '%s': %s", + conn->name, error); + event_unref(&event); + return -1; + } + event_unref(&event); + return 0; +} + +static int dict_connection_dict_init(struct dict_connection *conn) +{ + int ret = 0; + + if (array_is_created(&dict_settings->dicts)) { + const char *dict_name; + array_foreach_elem(&dict_settings->dicts, dict_name) { + if (strcmp(conn->name, dict_name) == 0) { + if (dict_connection_dict_init_name(conn) < 0) + return -1; + ret = 1; + break; + } + } + } + + if (ret == 0) { + if ((ret = dict_connection_dict_init_legacy(conn)) < 0) + return -1; + } + if (ret == 0) { + e_error(conn->conn.event, "Unconfigured dictionary name '%s'", + conn->name); + return -1; + } return 0; } diff --git a/src/dict/dict-expire.c b/src/dict/dict-expire.c index 931718484a..aaa313854f 100644 --- a/src/dict/dict-expire.c +++ b/src/dict/dict-expire.c @@ -63,7 +63,7 @@ static void client_connected(struct master_service_connection *conn ATTR_UNUSED) dict_expire_run(); } -static void dict_expire_init(void) +static void dict_expire_init_legacy(void) { struct dict_legacy_settings dict_set = { .base_dir = server_settings->base_dir, @@ -72,7 +72,8 @@ static void dict_expire_init(void) const char *const *strlist, *error; unsigned int i, count; - i_array_init(&expire_dicts, 16); + if (!array_is_created(&server_settings->legacy_dicts)) + return; strlist = array_get(&server_settings->legacy_dicts, &count); for (i = 0; i < count; i += 2) { const char *name = strlist[i]; @@ -90,6 +91,30 @@ static void dict_expire_init(void) } } +static void dict_expire_init(struct event *event) +{ + i_array_init(&expire_dicts, 16); + dict_expire_init_legacy(); + + if (!array_is_created(&dict_settings->dicts)) + return; + + struct dict *dict; + const char *dict_name, *error; + array_foreach_elem(&dict_settings->dicts, dict_name) { + if (dict_init_filter_auto(event, dict_name, &dict, &error) < 0) { + i_error("Failed to initialize dictionary '%s': %s - skipping", + dict_name, error); + } else { + struct expire_dict *expire_dict = + array_append_space(&expire_dicts); + expire_dict->name = dict_name; + expire_dict->dict = dict; + } + } + +} + static void main_preinit(void) { /* Load built-in SQL drivers (if any) */ @@ -105,10 +130,14 @@ static void main_preinit(void) static void main_init(void) { struct module_dir_load_settings mod_set; + struct event *event = master_service_get_event(master_service); + event_add_category(event, &dict_server_event_category); + event_set_ptr(event, SETTINGS_EVENT_FILTER_NAME, "dict_server"); server_settings = - settings_get_or_fatal(master_service_get_event(master_service), - &dict_server_setting_parser_info); + settings_get_or_fatal(event, &dict_server_setting_parser_info); + dict_settings = + settings_get_or_fatal(event, &dict_setting_parser_info); i_zero(&mod_set); mod_set.abi_version = DOVECOT_ABI_VERSION; @@ -121,7 +150,7 @@ static void main_init(void) which we'll need to register. */ dict_drivers_register_all(); - dict_expire_init(); + dict_expire_init(event); to_expire = timeout_add(DICT_EXPIRE_RUN_INTERVAL_MSECS, dict_expire_timeout, NULL); } @@ -140,6 +169,7 @@ static void main_deinit(void) sql_drivers_deinit(); timeout_remove(&to_expire); settings_free(server_settings); + settings_free(dict_settings); } int main(int argc, char *argv[]) diff --git a/src/dict/dict-init-cache.c b/src/dict/dict-init-cache.c index 779b6b3a5a..146ec26e8a 100644 --- a/src/dict/dict-init-cache.c +++ b/src/dict/dict-init-cache.c @@ -75,6 +75,25 @@ static struct dict_init_cache_list *dict_init_cache_find(const char *dict_name) return match; } +int dict_init_cache_get(struct event *event, const char *dict_name, + struct dict **dict_r, const char **error_r) +{ + struct dict_init_cache_list *match; + int ret = 0; + + match = dict_init_cache_find(dict_name); + if (match == NULL) { + if (dict_init_filter_auto(event, dict_name, dict_r, error_r) <= 0) + return -1; + match = dict_init_cache_add(dict_name, *dict_r); + } else { + match->refcount++; + *dict_r = match->dict; + } + i_assert(match->dict != NULL); + return ret; +} + int dict_init_cache_get_legacy(const char *dict_name, const char *uri, const struct dict_legacy_settings *set, struct dict **dict_r, const char **error_r) diff --git a/src/dict/dict-init-cache.h b/src/dict/dict-init-cache.h index e66f5d331d..afd4385084 100644 --- a/src/dict/dict-init-cache.h +++ b/src/dict/dict-init-cache.h @@ -1,6 +1,8 @@ #ifndef DICT_INIT_CACHE_H #define DICT_INIT_CACHE_H +int dict_init_cache_get(struct event *event, const char *dict_name, + struct dict **dict_r, const char **error_r); int dict_init_cache_get_legacy(const char *dict_name, const char *uri, const struct dict_legacy_settings *set, struct dict **dict_r, const char **error_r); diff --git a/src/dict/dict-settings.c b/src/dict/dict-settings.c index f551cb11ac..0224fc083d 100644 --- a/src/dict/dict-settings.c +++ b/src/dict/dict-settings.c @@ -90,6 +90,8 @@ struct service_settings dict_expire_service_settings = { SETTING_DEFINE_STRUCT_##type(#name, name, struct dict_server_settings) static const struct setting_define dict_setting_defines[] = { + { .type = SET_FILTER_NAME, .key = "dict_server" }, + DEF(STR_HIDDEN, base_dir), DEF(BOOL, verbose_proctitle), { .type = SET_STRLIST, .key = "dict_legacy", @@ -115,3 +117,8 @@ const struct setting_parser_info dict_server_setting_parser_info = { }; const struct dict_server_settings *server_settings; +const struct dict_settings *dict_settings; + +struct event_category dict_server_event_category = { + .name = "dict-server", +}; diff --git a/src/dict/dict-settings.h b/src/dict/dict-settings.h index 8518f0c94e..9930cbe275 100644 --- a/src/dict/dict-settings.h +++ b/src/dict/dict-settings.h @@ -10,5 +10,8 @@ struct dict_server_settings { extern const struct setting_parser_info dict_server_setting_parser_info; extern const struct dict_server_settings *server_settings; +extern const struct dict_settings *dict_settings; + +extern struct event_category dict_server_event_category; #endif diff --git a/src/dict/main.c b/src/dict/main.c index 9d8d992092..9b3637c961 100644 --- a/src/dict/main.c +++ b/src/dict/main.c @@ -100,11 +100,15 @@ static void main_preinit(void) static void main_init(void) { + struct event *event = master_service_get_event(master_service); struct module_dir_load_settings mod_set; + event_add_category(event, &dict_server_event_category); + event_set_ptr(event, SETTINGS_EVENT_FILTER_NAME, "dict_server"); server_settings = - settings_get_or_fatal(master_service_get_event(master_service), - &dict_server_setting_parser_info); + settings_get_or_fatal(event, &dict_server_setting_parser_info); + dict_settings = + settings_get_or_fatal(event, &dict_setting_parser_info); i_zero(&mod_set); mod_set.abi_version = DOVECOT_ABI_VERSION; @@ -138,6 +142,7 @@ static void main_deinit(void) sql_drivers_deinit(); timeout_remove(&to_proctitle); + settings_free(dict_settings); settings_free(server_settings); }