dovecot-2.0: Added settings_parser_apply_changes() for copying c...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Sep 3 23:36:51 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/2e502c0e23e7
changeset: 9858:2e502c0e23e7
user: Timo Sirainen <tss at iki.fi>
date: Thu Sep 03 16:35:19 2009 -0400
description:
Added settings_parser_apply_changes() for copying changed settings.
diffstat:
2 files changed, 176 insertions(+), 43 deletions(-)
src/lib-settings/settings-parser.c | 212 ++++++++++++++++++++++++++++--------
src/lib-settings/settings-parser.h | 7 +
diffs (260 lines):
diff -r 0830fbbdfecd -r 2e502c0e23e7 src/lib-settings/settings-parser.c
--- a/src/lib-settings/settings-parser.c Wed Sep 02 17:45:35 2009 -0400
+++ b/src/lib-settings/settings-parser.c Thu Sep 03 16:35:19 2009 -0400
@@ -895,6 +895,56 @@ static void settings_set_parent(const st
*ptr = parent;
}
+static bool
+setting_copy(enum setting_type type, const void *src, void *dest, pool_t pool)
+{
+ switch (type) {
+ case SET_BOOL: {
+ const bool *src_bool = src;
+ bool *dest_bool = dest;
+
+ *dest_bool = *src_bool;
+ }
+ case SET_UINT: {
+ const unsigned int *src_uint = src;
+ unsigned int *dest_uint = dest;
+
+ *dest_uint = *src_uint;
+ break;
+ }
+ case SET_STR_VARS:
+ case SET_STR:
+ case SET_ENUM: {
+ const char *const *src_str = src;
+ const char **dest_str = dest;
+
+ *dest_str = p_strdup(pool, *src_str);
+ break;
+ }
+ case SET_DEFLIST:
+ return FALSE;
+ case SET_STRLIST: {
+ const ARRAY_TYPE(const_string) *src_arr = src;
+ ARRAY_TYPE(const_string) *dest_arr = dest;
+ const char *const *strings, *dup;
+ unsigned int i, count;
+
+ if (!array_is_created(src_arr))
+ break;
+
+ strings = array_get(src_arr, &count);
+ if (!array_is_created(dest_arr))
+ p_array_init(dest_arr, pool, count);
+ for (i = 0; i < count; i++) {
+ dup = p_strdup(pool, strings[i]);
+ array_append(dest_arr, &dup, 1);
+ }
+ break;
+ }
+ }
+ return TRUE;
+}
+
void *settings_dup(const struct setting_parser_info *info,
const void *set, pool_t pool)
{
@@ -910,36 +960,13 @@ void *settings_dup(const struct setting_
src = CONST_PTR_OFFSET(set, def->offset);
dest = PTR_OFFSET(dest_set, def->offset);
- switch (def->type) {
- case SET_BOOL: {
- const bool *src_bool = src;
- bool *dest_bool = dest;
-
- *dest_bool = *src_bool;
- }
- case SET_UINT: {
- const unsigned int *src_uint = src;
- unsigned int *dest_uint = dest;
-
- *dest_uint = *src_uint;
- break;
- }
- case SET_STR_VARS:
- case SET_STR:
- case SET_ENUM: {
- const char *const *src_str = src;
- const char **dest_str = dest;
-
- *dest_str = p_strdup(pool, *src_str);
- break;
- }
- case SET_DEFLIST: {
+ if (!setting_copy(def->type, src, dest, pool)) {
const ARRAY_TYPE(void_array) *src_arr = src;
ARRAY_TYPE(void_array) *dest_arr = dest;
void *child_set;
if (!array_is_created(src_arr))
- break;
+ continue;
children = array_get(src_arr, &count);
p_array_init(dest_arr, pool, count);
@@ -950,24 +977,6 @@ void *settings_dup(const struct setting_
settings_set_parent(def->list_info, child_set,
dest_set);
}
- break;
- }
- case SET_STRLIST: {
- const ARRAY_TYPE(const_string) *src_arr = src;
- ARRAY_TYPE(const_string) *dest_arr = dest;
- const char *const *strings, *dup;
-
- if (!array_is_created(src_arr))
- break;
-
- strings = array_get(src_arr, &count);
- p_array_init(dest_arr, pool, count);
- for (i = 0; i < count; i++) {
- dup = p_strdup(pool, strings[i]);
- array_append(dest_arr, &dup, 1);
- }
- break;
- }
}
}
return dest_set;
@@ -1224,3 +1233,120 @@ settings_parser_dup(struct setting_parse
hash_table_destroy(&links);
return new_ctx;
}
+
+static void *
+settings_changes_init(const struct setting_parser_info *info,
+ const void *change_set, pool_t pool)
+{
+ const struct setting_define *def;
+ const ARRAY_TYPE(void_array) *src_arr;
+ ARRAY_TYPE(void_array) *dest_arr;
+ void *dest_set, *set, *const *children;
+ unsigned int i, count;
+
+ dest_set = p_malloc(pool, info->struct_size);
+ for (def = info->defines; def->key != NULL; def++) {
+ if (def->type != SET_DEFLIST)
+ continue;
+
+ src_arr = CONST_PTR_OFFSET(change_set, def->offset);
+ dest_arr = PTR_OFFSET(dest_set, def->offset);
+
+ if (array_is_created(src_arr)) {
+ children = array_get(src_arr, &count);
+ i_assert(!array_is_created(dest_arr));
+ p_array_init(dest_arr, pool, count);
+ for (i = 0; i < count; i++) {
+ set = settings_changes_init(def->list_info,
+ children[i], pool);
+ array_append(dest_arr, &set, 1);
+ }
+ }
+ }
+ return dest_set;
+}
+
+static int
+settings_apply(struct setting_link *dest_link,
+ const struct setting_link *src_link,
+ pool_t pool, const char **conflict_key_r)
+{
+ const struct setting_define *def;
+ const void *src, *csrc;
+ void *dest, *cdest, *const *children;
+ unsigned int i, count;
+
+ for (def = dest_link->info->defines; def->key != NULL; def++) {
+ csrc = CONST_PTR_OFFSET(src_link->change_struct, def->offset);
+ cdest = PTR_OFFSET(dest_link->change_struct, def->offset);
+
+ if (def->type == SET_DEFLIST || def->type == SET_STRLIST) {
+ /* just add the new values */
+ } else if (*((const char *)csrc) == 0) {
+ /* unchanged */
+ continue;
+ } else if (*((const char *)cdest) != 0) {
+ /* conflict */
+ if (conflict_key_r != NULL) {
+ *conflict_key_r = def->key;
+ return -1;
+ }
+ continue;
+ } else {
+ *((char *)cdest) = 1;
+ }
+
+ /* found a changed setting */
+ src = CONST_PTR_OFFSET(src_link->set_struct, def->offset);
+ dest = PTR_OFFSET(dest_link->set_struct, def->offset);
+
+ if (!setting_copy(def->type, src, dest, pool)) {
+ const ARRAY_TYPE(void_array) *src_arr = src;
+ ARRAY_TYPE(void_array) *dest_arr = dest;
+ void *child_set;
+
+ if (!array_is_created(src_arr))
+ continue;
+
+ children = array_get(src_arr, &count);
+ if (!array_is_created(dest_arr))
+ p_array_init(dest_arr, pool, count);
+ for (i = 0; i < count; i++) {
+ child_set = settings_dup(def->list_info,
+ children[i], pool);
+ array_append(dest_arr, &child_set, 1);
+ settings_set_parent(def->list_info, child_set,
+ dest_link->set_struct);
+ }
+
+ /* copy changes */
+ dest_arr = cdest;
+ if (!array_is_created(dest_arr))
+ p_array_init(dest_arr, pool, count);
+ for (i = 0; i < count; i++) {
+ child_set =
+ settings_changes_init(def->list_info,
+ children[i],
+ pool);
+ array_append(dest_arr, &child_set, 1);
+ }
+ }
+ }
+ return 0;
+}
+
+int settings_parser_apply_changes(struct setting_parser_context *dest,
+ const struct setting_parser_context *src,
+ pool_t pool, const char **conflict_key_r)
+{
+ unsigned int i;
+
+ i_assert(src->root_count == dest->root_count);
+ for (i = 0; i < dest->root_count; i++) {
+ i_assert(src->roots[i].info == dest->roots[i].info);
+ if (settings_apply(&dest->roots[i], &src->roots[i], pool,
+ conflict_key_r) < 0)
+ return -1;
+ }
+ return 0;
+}
diff -r 0830fbbdfecd -r 2e502c0e23e7 src/lib-settings/settings-parser.h
--- a/src/lib-settings/settings-parser.h Wed Sep 02 17:45:35 2009 -0400
+++ b/src/lib-settings/settings-parser.h Thu Sep 03 16:35:19 2009 -0400
@@ -163,4 +163,11 @@ const void *settings_find_dynamic(struct
const void *settings_find_dynamic(struct setting_parser_info *info,
const void *base_set, const char *name);
+/* Copy changed settings from src to dest. If conflict_key_r is not NULL and
+ both src and dest have changed the same setting, return -1 and set the
+ key name. */
+int settings_parser_apply_changes(struct setting_parser_context *dest,
+ const struct setting_parser_context *src,
+ pool_t pool, const char **conflict_key_r);
+
#endif
More information about the dovecot-cvs
mailing list