]> arthur.barton.de Git - netdata.git/blob - src/registry_person.c
removed over-optimization at the registry to simplify its logic and remove race condi...
[netdata.git] / src / registry_person.c
1 #include "registry_internals.h"
2
3 // ----------------------------------------------------------------------------
4 // PERSON
5
6 REGISTRY_PERSON *registry_person_find(const char *person_guid) {
7     debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid);
8     return dictionary_get(registry.persons, person_guid);
9 }
10
11 REGISTRY_PERSON_URL *registry_person_url_allocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when) {
12     // protection from too big names
13     if(namelen > registry.max_name_length)
14         namelen = registry.max_name_length;
15
16     debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url,
17             sizeof(REGISTRY_PERSON_URL) + namelen);
18
19     REGISTRY_PERSON_URL *pu = mallocz(sizeof(REGISTRY_PERSON_URL) + namelen);
20
21     // a simple strcpy() should do the job
22     // but I prefer to be safe, since the caller specified urllen
23     strncpyz(pu->machine_name, name, namelen);
24
25     pu->machine = m;
26     pu->first_t = pu->last_t = (uint32_t)when;
27     pu->usages = 1;
28     pu->url = u;
29     pu->flags = REGISTRY_URL_FLAGS_DEFAULT;
30     m->links++;
31
32     registry.persons_urls_memory += sizeof(REGISTRY_PERSON_URL) + namelen;
33
34     debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, u->url);
35     dictionary_set(p->person_urls, u->url, pu, sizeof(REGISTRY_PERSON_URL));
36     registry_url_link(u);
37
38     return pu;
39 }
40
41 REGISTRY_PERSON_URL *registry_person_url_reallocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when, REGISTRY_PERSON_URL *pu) {
42     // this function is needed to change the name of a PERSON_URL
43
44     debug(D_REGISTRY, "registry_person_url_reallocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url,
45             sizeof(REGISTRY_PERSON_URL) + namelen);
46
47     REGISTRY_PERSON_URL *tpu = registry_person_url_allocate(p, m, u, name, namelen, when);
48     tpu->first_t = pu->first_t;
49     tpu->last_t = pu->last_t;
50     tpu->usages = pu->usages;
51
52     // ok, these are a hack - since the registry_person_url_allocate() is
53     // adding these, we have to subtract them
54     tpu->machine->links--;
55     registry.persons_urls_memory -= sizeof(REGISTRY_PERSON_URL) + strlen(pu->machine_name);
56     registry_url_unlink(u);
57
58     freez(pu);
59
60     return tpu;
61 }
62
63 REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when) {
64     REGISTRY_PERSON *p = NULL;
65
66     debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(REGISTRY_PERSON));
67
68     p = mallocz(sizeof(REGISTRY_PERSON));
69
70     if(!person_guid) {
71         for (; ;) {
72             uuid_t uuid;
73             uuid_generate(uuid);
74             uuid_unparse_lower(uuid, p->guid);
75
76             debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid);
77             if (!dictionary_get(registry.persons, p->guid)) {
78                 debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid);
79                 break;
80             }
81             else
82                 info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid);
83         }
84     }
85     else
86         strncpyz(p->guid, person_guid, GUID_LEN);
87
88     debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): creating dictionary of urls", p->guid);
89     p->person_urls = dictionary_create(DICTIONARY_FLAGS);
90
91     p->first_t = p->last_t = (uint32_t)when;
92     p->usages = 0;
93
94     registry.persons_memory += sizeof(REGISTRY_PERSON);
95
96     registry.persons_count++;
97     dictionary_set(registry.persons, p->guid, p, sizeof(REGISTRY_PERSON));
98
99     return p;
100 }
101
102
103 // 1. validate person GUID
104 // 2. if it is valid, find it
105 // 3. if it is not valid, create a new one
106 // 4. return it
107 REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when) {
108     REGISTRY_PERSON *p = NULL;
109
110     if(person_guid && *person_guid) {
111         char buf[GUID_LEN + 1];
112         // validate it is a GUID
113         if(unlikely(registry_regenerate_guid(person_guid, buf) == -1))
114             info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid);
115         else {
116             person_guid = buf;
117             p = registry_person_find(person_guid);
118         }
119     }
120
121     if(!p) p = registry_person_allocate(NULL, when);
122
123     return p;
124 }
125
126 // ----------------------------------------------------------------------------
127 // LINKING OF OBJECTS
128
129 REGISTRY_PERSON_URL *registry_person_link_to_url(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when) {
130     debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, u->url);
131
132     REGISTRY_PERSON_URL *pu = dictionary_get(p->person_urls, u->url);
133     if(!pu) {
134         debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url);
135         pu = registry_person_url_allocate(p, m, u, name, namelen, when);
136         registry.persons_urls_count++;
137     }
138     else {
139         debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url);
140         pu->usages++;
141         if(likely(pu->last_t < (uint32_t)when)) pu->last_t = (uint32_t)when;
142
143         if(pu->machine != m) {
144             REGISTRY_MACHINE_URL *mu = dictionary_get(pu->machine->machine_urls, u->url);
145             if(mu) {
146                 info("registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.",
147                      p->guid, m->guid, u->url, pu->machine->guid);
148                 mu->flags |= REGISTRY_URL_FLAGS_EXPIRED;
149             }
150             else {
151                 info("registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - but the URL is not linked to the old machine.",
152                      p->guid, m->guid, u->url, pu->machine->guid);
153             }
154
155             pu->machine->links--;
156             pu->machine = m;
157         }
158
159         if(strcmp(pu->machine_name, name)) {
160             // the name of the PERSON_URL has changed !
161             pu = registry_person_url_reallocate(p, m, u, name, namelen, when, pu);
162         }
163     }
164
165     p->usages++;
166     if(likely(p->last_t < (uint32_t)when)) p->last_t = (uint32_t)when;
167
168     if(pu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
169         info("registry_person_link_to_url('%s', '%s', '%s'): accessing an expired URL. Re-enabling URL.", p->guid, m->guid, u->url);
170         pu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
171     }
172
173     return pu;
174 }
175