master
c 232 lines 8.97 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "database/rrd.h"
4 #include "registry_internals.h"
5
6 // ----------------------------------------------------------------------------
7 // PERSON_URL INDEX
8
9 inline REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, STRING *url) {
10 netdata_log_debug(D_REGISTRY, "Registry: registry_person_url_index_find('%s', '%s')", p->guid, string2str(url));
11
12 REGISTRY_PERSON_URL *pu;
13 for(pu = p->person_urls ; pu ;pu = pu->next)
14 if(pu->url == url)
15 break;
16
17 return pu;
18 }
19
20 inline REGISTRY_PERSON_URL *registry_person_url_index_add(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
21 DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(p->person_urls, pu, prev, next);
22 return pu;
23 }
24
25 inline REGISTRY_PERSON_URL *registry_person_url_index_del(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
26 DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(p->person_urls, pu, prev, next);
27 return pu;
28 }
29
30 // ----------------------------------------------------------------------------
31 // PERSON_URL
32
33 REGISTRY_PERSON_URL *registry_person_url_allocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, STRING *url, char *machine_name, size_t machine_name_len, time_t when) {
34 netdata_log_debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, string2str(url), sizeof(REGISTRY_PERSON_URL) + machine_name_len);
35
36 // protection from too big names
37 if(machine_name_len > registry.max_name_length)
38 machine_name_len = registry.max_name_length;
39
40 REGISTRY_PERSON_URL *pu = aral_mallocz(registry.person_urls_aral);
41
42 // a simple strcpy() should do the job,
43 // but I prefer to be safe, since the caller specified name_len
44 pu->machine_name = string_strdupz(machine_name);
45
46 pu->machine = m;
47 pu->first_t = pu->last_t = (uint32_t)when;
48 pu->usages = 1;
49 pu->url = string_dup(url);
50 pu->flags = REGISTRY_URL_FLAGS_DEFAULT;
51 m->links++;
52
53 netdata_log_debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, string2str(url));
54 REGISTRY_PERSON_URL *tpu = registry_person_url_index_add(p, pu);
55 if(tpu != pu) {
56 netdata_log_error("Registry: Attempted to add duplicate person url '%s' with name '%s' to person '%s'", string2str(url), machine_name, p->guid);
57 string_freez(pu->machine_name);
58 string_freez(pu->url);
59 aral_freez(registry.person_urls_aral, pu);
60 pu = tpu;
61 }
62
63 return pu;
64 }
65
66 void registry_person_url_deindex_and_free(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
67 netdata_log_debug(D_REGISTRY, "registry_person_url_deindex_and_free('%s', '%s')", p->guid, string2str(pu->url));
68
69 REGISTRY_PERSON_URL *tpu = registry_person_url_index_del(p, pu);
70 if(tpu) {
71 string_freez(tpu->machine_name);
72 string_freez(tpu->url);
73 tpu->machine->links--;
74 aral_freez(registry.person_urls_aral, tpu);
75 }
76 }
77
78 // this function is needed to change the name of a PERSON_URL
79 REGISTRY_PERSON_URL *registry_person_url_reallocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, STRING *url, char *machine_name, size_t machine_name_len, time_t when, REGISTRY_PERSON_URL *pu) {
80 netdata_log_debug(D_REGISTRY, "registry_person_url_reallocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, string2str(url), sizeof(REGISTRY_PERSON_URL) + machine_name_len);
81
82 // keep a backup
83 REGISTRY_PERSON_URL pu2 = {
84 .first_t = pu->first_t,
85 .last_t = pu->last_t,
86 .usages = pu->usages,
87 .flags = pu->flags,
88 .machine = pu->machine,
89 .machine_name = NULL
90 };
91
92 // remove the existing one from the index
93 registry_person_url_deindex_and_free(p, pu);
94 pu = &pu2;
95
96 // allocate a new one
97 REGISTRY_PERSON_URL *tpu = registry_person_url_allocate(p, m, url, machine_name, machine_name_len, when);
98 tpu->first_t = pu->first_t;
99 tpu->last_t = pu->last_t;
100 tpu->usages = pu->usages;
101 tpu->flags = pu->flags;
102
103 return tpu;
104 }
105
106
107 // ----------------------------------------------------------------------------
108 // PERSON
109
110 REGISTRY_PERSON *registry_person_find(const char *person_guid) {
111 netdata_log_debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid);
112 return dictionary_get(registry.persons, person_guid);
113 }
114
115 REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when) {
116 netdata_log_debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(REGISTRY_PERSON));
117
118 REGISTRY_PERSON *p = aral_mallocz(registry.persons_aral);
119 if(!person_guid) {
120 for(;;) {
121 nd_uuid_t uuid;
122 uuid_generate(uuid);
123 uuid_unparse_lower(uuid, p->guid);
124
125 netdata_log_debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid);
126 if (!dictionary_get(registry.persons, p->guid)) {
127 netdata_log_debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid);
128 break;
129 }
130 else
131 netdata_log_info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid);
132 }
133 }
134 else
135 strncpyz(p->guid, person_guid, GUID_LEN);
136
137 p->person_urls = NULL;
138
139 p->first_t = p->last_t = (uint32_t)when;
140 p->usages = 0;
141
142 registry.persons_count++;
143 dictionary_set(registry.persons, p->guid, p, sizeof(REGISTRY_PERSON));
144
145 return p;
146 }
147
148
149 // 1. validate person GUID
150 // 2. if it is valid, find it
151 // 3. if it is not valid, create a new one
152 // 4. return it
153 REGISTRY_PERSON *registry_person_find_or_create(const char *person_guid, time_t when, bool is_dummy) {
154 netdata_log_debug(D_REGISTRY, "Registry: registry_person_find_or_create('%s'): creating dictionary of urls", person_guid);
155
156 char buf[GUID_LEN + 1];
157 REGISTRY_PERSON *p = NULL;
158
159 if(person_guid && *person_guid) {
160 // validate it is a GUID
161 if(unlikely(regenerate_guid(person_guid, buf) == -1)) {
162 netdata_log_info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid);
163 person_guid = NULL;
164 }
165 else {
166 person_guid = buf;
167 p = registry_person_find(person_guid);
168 if(!p && !is_dummy)
169 person_guid = NULL;
170 }
171 }
172 else
173 person_guid = NULL;
174
175 if(!p) p = registry_person_allocate(person_guid, when);
176
177 return p;
178 }
179
180 // ----------------------------------------------------------------------------
181 // LINKING OF OBJECTS
182
183 REGISTRY_PERSON_URL *registry_person_link_to_url(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, STRING *url, char *machine_name, size_t machine_name_len, time_t when) {
184 netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, string2str(url));
185
186 REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, url);
187 if(!pu) {
188 netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, string2str(url));
189 pu = registry_person_url_allocate(p, m, url, machine_name, machine_name_len, when);
190 registry.persons_urls_count++;
191 }
192 else {
193 netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, string2str(url));
194 pu->usages++;
195 if(likely(pu->last_t < (uint32_t)when)) pu->last_t = (uint32_t)when;
196
197 if(pu->machine != m) {
198 REGISTRY_MACHINE_URL *mu = registry_machine_url_find(pu->machine, url);
199 if(mu) {
200 netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.",
201 p->guid, m->guid, string2str(url), pu->machine->guid);
202 mu->flags |= REGISTRY_URL_FLAGS_EXPIRED;
203 }
204 else {
205 netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - but the URL is not linked to the old machine.",
206 p->guid, m->guid, string2str(url), pu->machine->guid);
207 }
208
209 pu->machine->links--;
210 pu->machine = m;
211 }
212
213 if(strcmp(string2str(pu->machine_name), machine_name) != 0) {
214 // the name of the PERSON_URL has changed !
215 pu = registry_person_url_reallocate(p, m, url, machine_name, machine_name_len, when, pu);
216 }
217 }
218
219 p->usages++;
220 if(likely(p->last_t < (uint32_t)when)) p->last_t = (uint32_t)when;
221
222 if(pu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
223 netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): accessing an expired URL. Re-enabling URL.", p->guid, m->guid, string2str(url));
224 pu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
225 }
226
227 return pu;
228 }
229
230 void registry_person_unlink_from_url(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
231 registry_person_url_deindex_and_free(p, pu);
232 }