master
c 95 lines 3.51 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "inicfg_internals.h"
4
5 int inicfg_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new) {
6 struct config_option *opt_old, *opt_new;
7 int ret = -1;
8
9 netdata_log_debug(D_CONFIG, "request to rename config in section '%s', old name '%s', to section '%s', new name '%s'", section_old, name_old, section_new, name_new);
10
11 struct config_section *sect_old = inicfg_section_find(root, section_old);
12 if(!sect_old) return ret;
13
14 struct config_section *sect_new = inicfg_section_find(root, section_new);
15 if(!sect_new) sect_new = inicfg_section_create(root, section_new);
16
17 SECTION_LOCK(sect_old);
18 if(sect_old != sect_new)
19 SECTION_LOCK(sect_new);
20
21 opt_old = inicfg_option_find(sect_old, name_old);
22 if(!opt_old) goto cleanup;
23
24 opt_new = inicfg_option_find(sect_new, name_new);
25 if(opt_new) goto cleanup;
26
27 if(unlikely(inicfg_option_del(sect_old, opt_old) != opt_old))
28 netdata_log_error("INTERNAL ERROR: deletion of config '%s' from section '%s', deleted the wrong config entry.",
29 string2str(opt_old->name), string2str(sect_old->name));
30
31 // remember the old position of the item
32 struct config_option *opt_old_next = (sect_old == sect_new) ? opt_old->next : NULL;
33
34 DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(sect_old->values, opt_old, prev, next);
35
36 // nd_log(NDLS_DAEMON, NDLP_WARNING,
37 // "CONFIG: option '[%s].%s' has been migrated to '[%s].%s'.",
38 // section_old, name_old,
39 // section_new, name_new);
40
41 if(!opt_old->migrated.name) {
42 string_freez(opt_old->migrated.section);
43 opt_old->migrated.section = string_dup(sect_old->name);
44 opt_old->migrated.name = opt_old->name;
45 }
46 else
47 string_freez(opt_old->name);
48
49 opt_old->name = string_strdupz(name_new);
50 opt_old->flags |= CONFIG_VALUE_MIGRATED;
51
52 opt_new = opt_old;
53
54 // put in the list, but try to keep the order
55 if(opt_old_next && sect_old == sect_new)
56 DOUBLE_LINKED_LIST_INSERT_ITEM_BEFORE_UNSAFE(sect_new->values, opt_old_next, opt_new, prev, next);
57 else {
58 // we don't have the old next item (probably a different section?)
59 // find the last MIGRATED one
60 struct config_option *t = sect_new->values ? sect_new->values->prev : NULL;
61 for (; t && t != sect_new->values ; t = t->prev) {
62 if (t->flags & CONFIG_VALUE_MIGRATED)
63 break;
64 }
65 if (t == sect_new->values)
66 DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(sect_new->values, opt_new, prev, next);
67 else
68 DOUBLE_LINKED_LIST_INSERT_ITEM_AFTER_UNSAFE(sect_new->values, t, opt_new, prev, next);
69 }
70
71 if(unlikely(inicfg_option_add(sect_new, opt_old) != opt_old))
72 netdata_log_error("INTERNAL ERROR: re-indexing of config '%s' in section '%s', already exists.",
73 string2str(opt_old->name), string2str(sect_new->name));
74
75 ret = 0;
76
77 cleanup:
78 if(sect_old != sect_new)
79 SECTION_UNLOCK(sect_new);
80 SECTION_UNLOCK(sect_old);
81 return ret;
82 }
83
84 int inicfg_move_everywhere(struct config *root, const char *name_old, const char *name_new) {
85 int ret = -1;
86 APPCONFIG_LOCK(root);
87 struct config_section *sect;
88 for(sect = root->sections; sect; sect = sect->next) {
89 if(inicfg_move(root, string2str(sect->name), name_old, string2str(sect->name), name_new) == 0)
90 ret = 0;
91 }
92 APPCONFIG_UNLOCK(root);
93 return ret;
94 }
95