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