Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4393:9928ebb54719 HEAD
Instead of passing URIs directly to dictionary server, it now accepts only
named dictionaries which are configured in config file. SIGHUPing master now
restarts dict server.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 17 Jun 2006 15:24:59 +0300 |
parents | ed8e49b0a4ae |
children | 0462137fa4ce |
files | dovecot-example.conf src/dict/dict-server.c src/lib-dict/dict-client.h src/master/dict-process.c src/master/dict-process.h src/master/log.c src/master/log.h src/master/main.c src/master/master-settings.c src/master/master-settings.h |
diffstat | 10 files changed, 128 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/dovecot-example.conf Sat Jun 17 15:21:21 2006 +0300 +++ b/dovecot-example.conf Sat Jun 17 15:24:59 2006 +0300 @@ -939,6 +939,20 @@ #} ## +## Dictionary server settings +## + +# Dictionary can be used by some plugins to store key=value lists. +# Currently this is only used by dict quota backend. The dictionary can be +# used either directly or though a dictionary server. The following dict block +# maps dictionary names to URIs when the server is used. These can then be +# referenced using URIs in format "proxy:<name>". + +dict { + #quota = mysql:/etc/dovecot-dict-quota.conf +} + +## ## Plugin settings ##
--- a/src/dict/dict-server.c Sat Jun 17 15:21:21 2006 +0300 +++ b/src/dict/dict-server.c Sat Jun 17 15:24:59 2006 +0300 @@ -23,7 +23,7 @@ struct dict_server *server; char *username; - char *uri; + char *name, *uri; struct dict *dict; int fd; @@ -271,7 +271,7 @@ static int dict_client_parse_handshake(struct dict_client_connection *conn, const char *line) { - const char *username; + const char *username, *name; if (*line++ != DICT_PROTOCOL_CMD_HELLO) return -1; @@ -296,13 +296,37 @@ conn->username = i_strdup_until(username, line - 1); - /* the rest is dict URI */ - conn->uri = i_strdup(line); + /* the rest is dict name. since we're looking it with getenv(), + disallow all funny characters that might confuse it, just in case. */ + name = line; + while (*line > ' ' && *line != '=') line++; + + if (*line != '\0') + return -1; + + conn->name = i_strdup(name); + return 0; +} + +static int dict_client_dict_init(struct dict_client_connection *conn) +{ + const char *uri; + + uri = getenv(t_strconcat("DICT_", conn->name, NULL)); + if (uri == NULL) { + i_error("dict client: Unconfigured dictionary name '%s'", + conn->name); + return -1; + } + + conn->uri = i_strdup(uri); conn->dict = dict_cache_get(conn->server->cache, conn->uri, conn->username); - if (conn->dict == NULL) + if (conn->dict == NULL) { + /* dictionary initialization failed */ + i_error("Failed to initialize dictionary '%s'", conn->name); return -1; - + } return 0; } @@ -322,7 +346,7 @@ return; case -2: /* buffer full */ - i_error("BUG: Dict client sent us more than %d bytes", + i_error("dict client: Sent us more than %d bytes", (int)DICT_CLIENT_MAX_LINE_LENGTH); dict_client_connection_deinit(conn); return; @@ -334,6 +358,11 @@ return; if (dict_client_parse_handshake(conn, line) < 0) { + i_error("dict client: Broken handshake"); + dict_client_connection_deinit(conn); + return; + } + if (dict_client_dict_init(conn)) { dict_client_connection_deinit(conn); return; } @@ -376,6 +405,7 @@ if (conn->dict != NULL) dict_cache_unref(conn->server->cache, conn->uri); + i_free(conn->name); i_free(conn->uri); i_free(conn->username); i_free(conn);
--- a/src/lib-dict/dict-client.h Sat Jun 17 15:21:21 2006 +0300 +++ b/src/lib-dict/dict-client.h Sat Jun 17 15:24:59 2006 +0300 @@ -9,7 +9,7 @@ #define DICT_CLIENT_MAX_LINE_LENGTH (64*1024) enum { - /* <major-version> <minor-version> <user> <dict uri> */ + /* <major-version> <minor-version> <user> <dict name> */ DICT_PROTOCOL_CMD_HELLO = 'H', DICT_PROTOCOL_CMD_LOOKUP = 'L', /* <key> */
--- a/src/master/dict-process.c Sat Jun 17 15:21:21 2006 +0300 +++ b/src/master/dict-process.c Sat Jun 17 15:24:59 2006 +0300 @@ -1,6 +1,7 @@ /* Copyright (C) 2006 Timo Sirainen */ #include "common.h" +#include "array.h" #include "ioloop.h" #include "network.h" #include "fd-close-on-exec.h" @@ -17,6 +18,8 @@ struct dict_process { char *path; int fd; + + struct log_io *log; struct io *io; }; @@ -27,8 +30,9 @@ static int dict_process_start(struct dict_process *process) { struct log_io *log; - const char *executable; - int i, log_fd; + const char *executable, *const *dicts; + unsigned int i, count; + int log_fd; pid_t pid; log_fd = log_create_pipe(&log, 0); @@ -51,6 +55,8 @@ log_set_prefix(log, "dict: "); (void)close(log_fd); + process->log = log; + log_ref(process->log); dict_process_unlisten(process); return 0; } @@ -75,6 +81,11 @@ child_process_init_env(); env_put(t_strconcat("DICT_LISTEN_FROM_FD=", process->path, NULL)); + dicts = array_get(&settings_root->dicts, &count); + i_assert((count % 2) == 0); + for (i = 0; i < count; i += 2) + env_put(t_strdup_printf("DICT_%s=%s", dicts[i], dicts[i+1])); + /* make sure we don't leak syslog fd, but do it last so that any errors above will be logged */ closelog(); @@ -89,6 +100,7 @@ { struct dict_process *process = context; + i_assert(process->log == NULL); dict_process_start(process); } @@ -157,6 +169,8 @@ void dict_process_deinit(void) { dict_process_unlisten(process); + if (process->log != NULL) + log_unref(process->log); i_free(process->path); i_free(process); } @@ -166,3 +180,11 @@ dict_process_deinit(); dict_process_init(); } + +void dict_process_kill(void) +{ + if (process->log != NULL) { + log_unref(process->log); + process->log = NULL; + } +}
--- a/src/master/dict-process.h Sat Jun 17 15:21:21 2006 +0300 +++ b/src/master/dict-process.h Sat Jun 17 15:24:59 2006 +0300 @@ -4,5 +4,6 @@ void dict_process_init(void); void dict_process_deinit(void); void dict_process_restart(void); +void dict_process_kill(void); #endif
--- a/src/master/log.c Sat Jun 17 15:21:21 2006 +0300 +++ b/src/master/log.c Sat Jun 17 15:24:59 2006 +0300 @@ -10,6 +10,8 @@ struct log_io { struct log_io *prev, *next; + int refcount; + struct io *io; struct istream *stream; @@ -29,7 +31,6 @@ static int log_it(struct log_io *log_io, const char *line, bool continues); static void log_read(void *context); -static void log_io_free(struct log_io *log_io); static void log_throttle_timeout(void *context); static bool log_write_pending(struct log_io *log_io) @@ -132,7 +133,7 @@ if (ret < 0) { if (ret == -1) { /* closed */ - log_io_free(log_io); + log_unref(log_io); return; } @@ -166,6 +167,7 @@ fd_close_on_exec(fd[1], TRUE); log_io = i_new(struct log_io, 1); + log_io->refcount = 1; log_io->stream = i_stream_create_file(fd[0], default_pool, 1024, TRUE); log_io->max_lines_per_sec = max_lines_per_sec != 0 ? max_lines_per_sec : (unsigned int)-1; @@ -189,11 +191,19 @@ log->prefix = i_strdup(prefix); } -static void log_io_free(struct log_io *log_io) +void log_ref(struct log_io *log_io) +{ + log_io->refcount++; +} + +static void log_close(struct log_io *log_io) { const unsigned char *data; size_t size; + if (log_io->destroying) + return; + /* if there was something in buffer, write it */ log_io->destroying = TRUE; (void)log_write_pending(log_io); @@ -218,6 +228,17 @@ else throttle_count--; i_stream_destroy(&log_io->stream); +} + +void log_unref(struct log_io *log_io) +{ + i_assert(log_io->refcount > 0); + + log_close(log_io); + + if (--log_io->refcount > 0) + return; + i_free(log_io->prefix); i_free(log_io); } @@ -255,7 +276,7 @@ while (log_ios != NULL) { next = log_ios->next; - log_io_free(log_ios); + log_unref(log_ios); log_ios = next; }
--- a/src/master/log.h Sat Jun 17 15:21:21 2006 +0300 +++ b/src/master/log.h Sat Jun 17 15:24:59 2006 +0300 @@ -6,6 +6,9 @@ int log_create_pipe(struct log_io **log_r, unsigned int max_lines_per_sec); void log_set_prefix(struct log_io *log, const char *prefix); +void log_ref(struct log_io *log_io); +void log_unref(struct log_io *log_io); + void log_init(void); void log_deinit(void);
--- a/src/master/main.c Sat Jun 17 15:21:21 2006 +0300 +++ b/src/master/main.c Sat Jun 17 15:24:59 2006 +0300 @@ -136,6 +136,7 @@ /* restart auth and login processes */ login_processes_destroy_all(); auth_processes_destroy_all(); + dict_process_kill(); if (!master_settings_read(configfile, FALSE)) i_warning("Invalid configuration, keeping old one");
--- a/src/master/master-settings.c Sat Jun 17 15:21:21 2006 +0300 +++ b/src/master/master-settings.c Sat Jun 17 15:24:59 2006 +0300 @@ -30,6 +30,7 @@ SETTINGS_TYPE_AUTH_USERDB, SETTINGS_TYPE_NAMESPACE, SETTINGS_TYPE_SOCKET, + SETTINGS_TYPE_DICT, SETTINGS_TYPE_PLUGIN }; @@ -1071,6 +1072,13 @@ return parse_setting_from_defs(settings_pool, socket_setting_defs, ctx->socket, key, value); + case SETTINGS_TYPE_DICT: + key = p_strdup(settings_pool, key); + value = p_strdup(settings_pool, value); + + array_append(&ctx->server->dicts, &key, 1); + array_append(&ctx->server->dicts, &value, 1); + return NULL; case SETTINGS_TYPE_PLUGIN: key = p_strdup(settings_pool, key); value = p_strdup(settings_pool, value); @@ -1109,6 +1117,7 @@ *server->imap = *imap_defaults; *server->pop3 = *pop3_defaults; + ARRAY_CREATE(&server->dicts, settings_pool, const char *, 4); ARRAY_CREATE(&server->imap->plugin_envs, settings_pool, const char *, 8); ARRAY_CREATE(&server->pop3->plugin_envs, settings_pool, @@ -1257,6 +1266,17 @@ return ctx->namespace != NULL; } + if (strcmp(type, "dict") == 0) { + if (ctx->type != SETTINGS_TYPE_ROOT && + ctx->type != SETTINGS_TYPE_SERVER) { + *errormsg = "Plugin section not allowed here"; + return FALSE; + } + + ctx->type = SETTINGS_TYPE_DICT; + return TRUE; + } + if (strcmp(type, "plugin") == 0) { if (ctx->type != SETTINGS_TYPE_ROOT && ctx->type != SETTINGS_TYPE_SERVER) {