diff options
Diffstat (limited to 'src/dict/main.c')
-rw-r--r-- | src/dict/main.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/dict/main.c b/src/dict/main.c new file mode 100644 index 0000000..14b1cea --- /dev/null +++ b/src/dict/main.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "restrict-access.h" +#include "ioloop.h" +#include "randgen.h" +#include "str.h" +#include "stats-dist.h" +#include "process-title.h" +#include "env-util.h" +#include "module-dir.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "sql-api.h" +#include "dict.h" +#include "dict-client.h" +#include "dict-commands.h" +#include "dict-connection.h" +#include "dict-settings.h" +#include "dict-init-cache.h" +#include "main.h" + +#include <math.h> + +static struct module *modules; +static struct timeout *to_proctitle; +static bool proctitle_updated; +static struct ioloop *main_ioloop; + +static void +add_stats_string(string_t *str, struct stats_dist *stats, const char *name) +{ + uint64_t min, max, p95; + double avg; + + min = stats_dist_get_min(stats); + avg = stats_dist_get_avg(stats); + p95 = stats_dist_get_95th(stats); + max = stats_dist_get_max(stats); + + str_printfa(str, ", %u %s:%llu/%lld/%llu/%llu", + stats_dist_get_count(stats), name, + (unsigned long long)min/1000, llrint(avg/1000), + (unsigned long long)p95/1000, + (unsigned long long)max/1000); + stats_dist_reset(stats); +} + +static void dict_proctitle_update(void *context ATTR_UNUSED) +{ + string_t *str = t_str_new(128); + + if (!proctitle_updated) + timeout_remove(&to_proctitle); + + str_printfa(str, "[%u clients", dict_connections_current_count()); + + add_stats_string(str, cmd_stats.lookups, "lookups"); + add_stats_string(str, cmd_stats.iterations, "iters"); + add_stats_string(str, cmd_stats.commits, "commits"); + str_append_c(str, ']'); + + process_title_set(str_c(str)); + proctitle_updated = FALSE; +} + +void dict_proctitle_update_later(void) +{ + if (!dict_settings->verbose_proctitle) + return; + + if (to_proctitle == NULL) + to_proctitle = timeout_add_to(main_ioloop, 1000, dict_proctitle_update, NULL); + proctitle_updated = TRUE; +} + +static void dict_die(void) +{ + /* hope that other processes relying on us will die first. */ +} + +static void client_connected(struct master_service_connection *conn) +{ + master_service_client_connection_accept(conn); + (void)dict_connection_create(conn); +} + +static void main_preinit(void) +{ + /* Load built-in SQL drivers (if any) */ + sql_drivers_init(); + sql_drivers_register_all(); +#ifdef HAVE_CDB + dict_driver_register(&dict_driver_cdb); +#endif + + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); + restrict_access_allow_coredumps(TRUE); +} + +static void main_init(void) +{ + struct module_dir_load_settings mod_set; + void **sets; + + sets = master_service_settings_get_others(master_service); + dict_settings = sets[0]; + + if (*dict_settings->dict_db_config != '\0') { + /* for berkeley db library */ + env_put("DB_CONFIG", dict_settings->dict_db_config); + } + + i_zero(&mod_set); + mod_set.abi_version = DOVECOT_ABI_VERSION; + mod_set.require_init_funcs = TRUE; + + modules = module_dir_load(DICT_MODULE_DIR, NULL, &mod_set); + module_dir_init(modules); + + /* Register only after loading modules. They may contain SQL drivers, + which we'll need to register. */ + dict_drivers_register_all(); + dict_commands_init(); + dict_connections_init(); + + if (dict_settings->verbose_proctitle) + dict_proctitle_update(NULL); +} + +static void main_deinit(void) +{ + /* wait for all dict operations to finish */ + dict_init_cache_wait_all(); + /* connections should no longer have any extra refcounts */ + dict_connections_destroy_all(); + dict_init_cache_destroy_all(); + + dict_drivers_unregister_all(); + dict_commands_deinit(); + + module_dir_unload(&modules); + + sql_drivers_deinit(); + timeout_remove(&to_proctitle); +} + +int main(int argc, char *argv[]) +{ + const enum master_service_flags service_flags = 0; + const struct setting_parser_info *set_roots[] = { + &dict_setting_parser_info, + NULL + }; + const char *error; + + master_service = master_service_init("dict", service_flags, + &argc, &argv, ""); + if (master_getopt(master_service) > 0) + return FATAL_DEFAULT; + + if (master_service_settings_read_simple(master_service, set_roots, + &error) < 0) + i_fatal("Error reading configuration: %s", error); + + master_service_init_log_with_pid(master_service); + main_preinit(); + master_service_set_die_callback(master_service, dict_die); + + main_ioloop = current_ioloop; + main_init(); + master_service_init_finish(master_service); + master_service_run(master_service, client_connected); + + /* clean up cached dicts */ + main_deinit(); + master_service_deinit(&master_service); + return 0; +} |