registry_person.c 9.0 KB

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