#include "ostream.h"
#include "llist.h"
#include "strescape.h"
+#include "settings.h"
#include "master-service.h"
#include "dict-client.h"
#include "dict-settings.h"
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)
{
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);
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;
}
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,
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];
}
}
+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) */
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;
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);
}
sql_drivers_deinit();
timeout_remove(&to_expire);
settings_free(server_settings);
+ settings_free(dict_settings);
}
int main(int argc, char *argv[])
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)
#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);
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",
};
const struct dict_server_settings *server_settings;
+const struct dict_settings *dict_settings;
+
+struct event_category dict_server_event_category = {
+ .name = "dict-server",
+};
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
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;
sql_drivers_deinit();
timeout_remove(&to_proctitle);
+ settings_free(dict_settings);
settings_free(server_settings);
}