dovecot-2.0: config: Send client a services names that have more...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Mar 19 17:24:25 EET 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/30e2d65eb67a
changeset: 10952:30e2d65eb67a
user: Timo Sirainen <tss at iki.fi>
date: Fri Mar 19 17:23:56 2010 +0200
description:
config: Send client a services names that have more specific settings.
diffstat:
src/config/config-connection.c | 8 ++++
src/config/config-filter.c | 50 +++++++++++++++++++++++-
src/config/config-filter.h | 1 +
src/config/config-parser.c | 48 +++++++++++++++++++++++-
src/config/config-parser.h | 3 +
src/config/config-request.c | 54 ++------------------------
src/lib-master/master-service-settings.c | 20 ++++++++--
src/lib-master/master-service-settings.h | 9 +++-
8 files changed, 134 insertions(+), 59 deletions(-)
diffs (truncated from 365 to 300 lines):
diff -r edd11ffa467c -r 30e2d65eb67a src/config/config-connection.c
--- a/src/config/config-connection.c Fri Mar 19 16:44:38 2010 +0200
+++ b/src/config/config-connection.c Fri Mar 19 17:23:56 2010 +0200
@@ -115,6 +115,14 @@
config_export_by_filter(ctx, &filter);
config_export_get_output(ctx, &output);
+ if (output.specific_services != NULL) {
+ const char *const *s;
+
+ for (s = output.specific_services; *s != NULL; s++) {
+ o_stream_send_str(conn->output,
+ t_strdup_printf("service=%s\t", *s));
+ }
+ }
if (output.service_uses_local)
o_stream_send_str(conn->output, "service-uses-local\t");
if (output.service_uses_remote)
diff -r edd11ffa467c -r 30e2d65eb67a src/config/config-filter.c
--- a/src/config/config-filter.c Fri Mar 19 16:44:38 2010 +0200
+++ b/src/config/config-filter.c Fri Mar 19 17:23:56 2010 +0200
@@ -155,22 +155,60 @@
return -config_filter_parser_cmp(p1, p2);
}
+static bool str_array_contains(ARRAY_TYPE(const_string) *arr, const char *str)
+{
+ const char *const *p;
+
+ array_foreach(arr, p) {
+ if (strcmp(*p, str) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool have_changed_settings(const struct config_filter_parser *parser,
+ const char *module)
+{
+ const unsigned char *changes;
+ unsigned int i, j, size;
+
+ for (i = 0; parser->parsers[i].root != NULL; i++) {
+ if (*module != '\0' &&
+ !config_module_want_parser(module, parser->parsers[i].root))
+ continue;
+
+ changes = settings_parser_get_changes(parser->parsers[i].parser);
+ size = parser->parsers[i].root->struct_size;
+ for (j = 0; j < size; j++) {
+ if (changes[j] != 0)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static struct config_filter_parser *const *
-config_filter_find_all(struct config_filter_context *ctx,
+config_filter_find_all(struct config_filter_context *ctx, const char *module,
const struct config_filter *filter,
struct master_service_settings_output *output_r)
{
ARRAY_TYPE(config_filter_parsers) matches;
+ ARRAY_TYPE(const_string) service_names;
unsigned int i;
memset(output_r, 0, sizeof(*output_r));
t_array_init(&matches, 8);
+ t_array_init(&service_names, 8);
for (i = 0; ctx->parsers[i] != NULL; i++) {
const struct config_filter *mask = &ctx->parsers[i]->filter;
- if (!config_filter_match_service(mask, filter))
+ if (!config_filter_match_service(mask, filter)) {
+ if (!str_array_contains(&service_names, mask->service) &&
+ have_changed_settings(ctx->parsers[i], module))
+ array_append(&service_names, &mask->service, 1);
continue;
+ }
if (mask->local_bits > 0)
output_r->service_uses_local = TRUE;
@@ -184,6 +222,11 @@
array_append(&matches, &ctx->parsers[i], 1);
}
}
+ if (filter->service == NULL) {
+ (void)array_append_space(&service_names);
+ output_r->specific_services = array_idx(&service_names, 0);
+ }
+
array_sort(&matches, config_filter_parser_cmp);
(void)array_append_space(&matches);
return array_idx(&matches, 0);
@@ -260,6 +303,7 @@
}
int config_filter_parsers_get(struct config_filter_context *ctx, pool_t pool,
+ const char *module,
const struct config_filter *filter,
struct config_module_parser **parsers_r,
struct master_service_settings_output *output_r,
@@ -270,7 +314,7 @@
const char *error, **error_p;
unsigned int i, count;
- src = config_filter_find_all(ctx, filter, output_r);
+ src = config_filter_find_all(ctx, module, filter, output_r);
/* all of them should have the same number of parsers.
duplicate our initial parsers from the first match */
diff -r edd11ffa467c -r 30e2d65eb67a src/config/config-filter.h
--- a/src/config/config-filter.h Fri Mar 19 16:44:38 2010 +0200
+++ b/src/config/config-filter.h Fri Mar 19 17:23:56 2010 +0200
@@ -29,6 +29,7 @@
/* Build new parsers from all existing ones matching the given filter. */
int config_filter_parsers_get(struct config_filter_context *ctx, pool_t pool,
+ const char *module,
const struct config_filter *filter,
struct config_module_parser **parsers_r,
struct master_service_settings_output *output_r,
diff -r edd11ffa467c -r 30e2d65eb67a src/config/config-parser.c
--- a/src/config/config-parser.c Fri Mar 19 16:44:38 2010 +0200
+++ b/src/config/config-parser.c Fri Mar 19 17:23:56 2010 +0200
@@ -300,7 +300,7 @@
i_assert(count > 0 && parsers[count-1] == NULL);
count--;
for (i = 0; i < count && ret == 0; i++) {
- if (config_filter_parsers_get(new_filter, tmp_pool,
+ if (config_filter_parsers_get(new_filter, tmp_pool, "",
&parsers[i]->filter,
&tmp_parsers, &output,
error_r) < 0) {
@@ -850,3 +850,49 @@
*default_services = new_services;
}
}
+
+static bool parsers_are_connected(const struct setting_parser_info *root,
+ const struct setting_parser_info *info)
+{
+ const struct setting_parser_info *p;
+ const struct setting_parser_info *const *dep;
+
+ /* we're trying to find info or its parents from root's dependencies. */
+
+ for (p = info; p != NULL; p = p->parent) {
+ if (p == root)
+ return TRUE;
+ }
+
+ if (root->dependencies != NULL) {
+ for (dep = root->dependencies; *dep != NULL; dep++) {
+ if (parsers_are_connected(*dep, info))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool config_module_want_parser(const char *module,
+ const struct setting_parser_info *root)
+{
+ struct config_module_parser *l;
+
+ if (strcmp(root->module_name, module) == 0)
+ return TRUE;
+ if (root == &master_service_setting_parser_info) {
+ /* everyone wants master service settings */
+ return TRUE;
+ }
+
+ for (l = config_module_parsers; l->root != NULL; l++) {
+ if (strcmp(l->root->module_name, module) != 0)
+ continue;
+
+ /* see if we can find a way to get from the original parser
+ to this parser */
+ if (parsers_are_connected(l->root, root))
+ return TRUE;
+ }
+ return FALSE;
+}
diff -r edd11ffa467c -r 30e2d65eb67a src/config/config-parser.h
--- a/src/config/config-parser.h Fri Mar 19 16:44:38 2010 +0200
+++ b/src/config/config-parser.h Fri Mar 19 17:23:56 2010 +0200
@@ -18,4 +18,7 @@
void config_parse_load_modules(void);
+bool config_module_want_parser(const char *module,
+ const struct setting_parser_info *root);
+
#endif
diff -r edd11ffa467c -r 30e2d65eb67a src/config/config-request.c
--- a/src/config/config-request.c Fri Mar 19 16:44:38 2010 +0200
+++ b/src/config/config-request.c Fri Mar 19 17:23:56 2010 +0200
@@ -30,53 +30,6 @@
bool failed;
};
-static bool parsers_are_connected(const struct setting_parser_info *root,
- const struct setting_parser_info *info)
-{
- const struct setting_parser_info *p;
- const struct setting_parser_info *const *dep;
-
- /* we're trying to find info or its parents from root's dependencies. */
-
- for (p = info; p != NULL; p = p->parent) {
- if (p == root)
- return TRUE;
- }
-
- if (root->dependencies != NULL) {
- for (dep = root->dependencies; *dep != NULL; dep++) {
- if (parsers_are_connected(*dep, info))
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static bool
-config_module_parser_is_in_service(const struct config_module_parser *list,
- const char *module)
-{
- struct config_module_parser *l;
-
- if (strcmp(list->root->module_name, module) == 0)
- return TRUE;
- if (list->root == &master_service_setting_parser_info) {
- /* everyone wants master service settings */
- return TRUE;
- }
-
- for (l = config_module_parsers; l->root != NULL; l++) {
- if (strcmp(l->root->module_name, module) != 0)
- continue;
-
- /* see if we can find a way to get from the original parser
- to this parser */
- if (parsers_are_connected(l->root, list->root))
- return TRUE;
- }
- return FALSE;
-}
-
bool config_export_type(string_t *str, const void *value,
const void *default_value,
enum setting_type type, bool dump_default,
@@ -343,6 +296,8 @@
struct config_export_context *ctx;
pool_t pool;
+ i_assert(module != NULL);
+
pool = pool_alloconly_create("config export", 1024*64);
ctx = p_new(pool, struct config_export_context, 1);
ctx->pool = pool;
@@ -364,7 +319,8 @@
{
const char *error;
- if (config_filter_parsers_get(config_filter, ctx->pool, filter,
+ if (config_filter_parsers_get(config_filter, ctx->pool,
+ ctx->module, filter,
&ctx->dup_parsers, &ctx->output,
&error) < 0) {
i_error("%s", error);
@@ -411,7 +367,7 @@
for (i = 0; ctx->parsers[i].root != NULL; i++) {
parser = &ctx->parsers[i];
if (*ctx->module != '\0' &&
- !config_module_parser_is_in_service(parser, ctx->module))
+ !config_module_want_parser(ctx->module, parser->root))
continue;
settings_export(ctx, parser->root, FALSE,
diff -r edd11ffa467c -r 30e2d65eb67a src/lib-master/master-service-settings.c
--- a/src/lib-master/master-service-settings.c Fri Mar 19 16:44:38 2010 +0200
+++ b/src/lib-master/master-service-settings.c Fri Mar 19 17:23:56 2010 +0200
@@ -230,22 +230,23 @@
}
static int
-config_read_reply_header(struct istream *input, const char *path,
+config_read_reply_header(struct istream *istream, const char *path, pool_t pool,
+ const struct master_service_settings_input *input,
struct master_service_settings_output *output_r,
const char **error_r)
{
const char *line;
ssize_t ret;
- while ((ret = i_stream_read(input)) > 0) {
- line = i_stream_next_line(input);
More information about the dovecot-cvs
mailing list