| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "database/rrd.h" |
| 4 | #include "registry_internals.h" |
| 5 | |
| 6 | void registry_db_stats(void) { |
| 7 | size_t persons = 0; |
| 8 | size_t persons_urls = 0; |
| 9 | size_t max_urls_per_person = 0; |
| 10 | |
| 11 | REGISTRY_PERSON *p; |
| 12 | dfe_start_read(registry.persons, p) { |
| 13 | persons++; |
| 14 | size_t urls = 0; |
| 15 | for(REGISTRY_PERSON_URL *pu = p->person_urls ; pu ;pu = pu->next) |
| 16 | urls++; |
| 17 | |
| 18 | if(urls > max_urls_per_person) |
| 19 | max_urls_per_person = urls; |
| 20 | |
| 21 | persons_urls += urls; |
| 22 | } |
| 23 | dfe_done(p); |
| 24 | |
| 25 | size_t machines = 0; |
| 26 | size_t machines_urls = 0; |
| 27 | size_t max_urls_per_machine = 0; |
| 28 | |
| 29 | REGISTRY_MACHINE *m; |
| 30 | dfe_start_read(registry.machines, m) { |
| 31 | machines++; |
| 32 | size_t urls = 0; |
| 33 | for(REGISTRY_MACHINE_URL *mu = m->machine_urls ; mu ;mu = mu->next) |
| 34 | urls++; |
| 35 | |
| 36 | if(urls > max_urls_per_machine) |
| 37 | max_urls_per_machine = urls; |
| 38 | |
| 39 | machines_urls += urls; |
| 40 | } |
| 41 | dfe_done(m); |
| 42 | |
| 43 | netdata_log_info("REGISTRY: persons %zu, person_urls %zu, max_urls_per_person %zu, " |
| 44 | "machines %zu, machine_urls %zu, max_urls_per_machine %zu", |
| 45 | persons, persons_urls, max_urls_per_person, |
| 46 | machines, machines_urls, max_urls_per_machine); |
| 47 | } |
| 48 | |
| 49 | void registry_generate_curl_urls(void) { |
| 50 | FILE *fp = fopen("/tmp/registry.curl", "w+"); |
| 51 | if (unlikely(!fp)) |
| 52 | return; |
| 53 | |
| 54 | REGISTRY_PERSON *p; |
| 55 | dfe_start_read(registry.persons, p) { |
| 56 | for(REGISTRY_PERSON_URL *pu = p->person_urls ; pu ;pu = pu->next) { |
| 57 | fprintf(fp, "do_curl '%s' '%s' '%s'\n", p->guid, pu->machine->guid, string2str(pu->url)); |
| 58 | } |
| 59 | } |
| 60 | dfe_done(p); |
| 61 | |
| 62 | fclose(fp); |
| 63 | } |
| 64 | |
| 65 | void netdata_conf_section_registry(void) { |
| 66 | FUNCTION_RUN_ONCE(); |
| 67 | |
| 68 | netdata_conf_section_directories(); |
| 69 | netdata_conf_section_global_hostname(); |
| 70 | |
| 71 | char filename[FILENAME_MAX + 1]; |
| 72 | |
| 73 | // registry enabled? |
| 74 | if(web_server_mode != WEB_SERVER_MODE_NONE) { |
| 75 | registry.enabled = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_REGISTRY, "enabled", 0); |
| 76 | } |
| 77 | else { |
| 78 | netdata_log_info("Registry is disabled"); |
| 79 | inicfg_set_boolean(&netdata_config, CONFIG_SECTION_REGISTRY, "enabled", 0); |
| 80 | registry.enabled = 0; |
| 81 | } |
| 82 | |
| 83 | // path names |
| 84 | snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir); |
| 85 | registry.pathname = inicfg_get_path(&netdata_config, CONFIG_SECTION_DIRECTORIES, "registry", filename); |
| 86 | |
| 87 | // filenames |
| 88 | snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname); |
| 89 | registry.db_filename = inicfg_get_filename(&netdata_config, CONFIG_SECTION_REGISTRY, "registry db file", filename); |
| 90 | |
| 91 | snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname); |
| 92 | registry.log_filename = inicfg_get_filename(&netdata_config, CONFIG_SECTION_REGISTRY, "registry log file", filename); |
| 93 | |
| 94 | // configuration options |
| 95 | registry.save_registry_every_entries = (unsigned long long)inicfg_get_number(&netdata_config, CONFIG_SECTION_REGISTRY, "registry save db every new entries", 1000000); |
| 96 | registry.persons_expiration = inicfg_get_duration_days_to_seconds(&netdata_config, CONFIG_SECTION_REGISTRY, "registry expire idle persons", 365 * 86400); |
| 97 | registry.registry_domain = inicfg_get(&netdata_config, CONFIG_SECTION_REGISTRY, "registry domain", ""); |
| 98 | registry.registry_to_announce = inicfg_get(&netdata_config, CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io"); |
| 99 | registry.hostname = inicfg_get(&netdata_config, CONFIG_SECTION_REGISTRY, "registry hostname", netdata_configured_hostname); |
| 100 | registry.verify_cookies_redirects = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_REGISTRY, "verify browser cookies support", 1); |
| 101 | registry.enable_cookies_samesite_secure = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_REGISTRY, "enable cookies SameSite and Secure", 1); |
| 102 | |
| 103 | registry_update_cloud_base_url(); |
| 104 | nd_setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1); |
| 105 | nd_setenv("NETDATA_REGISTRY_URL", registry.registry_to_announce, 1); |
| 106 | |
| 107 | registry.max_url_length = (size_t)inicfg_get_number(&netdata_config, CONFIG_SECTION_REGISTRY, "max URL length", 1024); |
| 108 | if(registry.max_url_length < 10) { |
| 109 | registry.max_url_length = 10; |
| 110 | inicfg_set_number(&netdata_config, CONFIG_SECTION_REGISTRY, "max URL length", (long long)registry.max_url_length); |
| 111 | } |
| 112 | |
| 113 | registry.max_name_length = (size_t)inicfg_get_number(&netdata_config, CONFIG_SECTION_REGISTRY, "max URL name length", 50); |
| 114 | if(registry.max_name_length < 10) { |
| 115 | registry.max_name_length = 10; |
| 116 | inicfg_set_number(&netdata_config, CONFIG_SECTION_REGISTRY, "max URL name length", (long long)registry.max_name_length); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | void registry_init(void) { |
| 121 | FUNCTION_RUN_ONCE(); |
| 122 | |
| 123 | netdata_conf_section_registry(); |
| 124 | |
| 125 | verify_required_directory(NULL, registry.pathname, true, 0770); |
| 126 | |
| 127 | // initialize entries counters |
| 128 | registry.persons_count = 0; |
| 129 | registry.machines_count = 0; |
| 130 | registry.usages_count = 0; |
| 131 | registry.persons_urls_count = 0; |
| 132 | registry.machines_urls_count = 0; |
| 133 | |
| 134 | // initialize locks |
| 135 | netdata_mutex_init(®istry.lock); |
| 136 | } |
| 137 | |
| 138 | bool registry_load(void) { |
| 139 | if(registry.enabled) { |
| 140 | bool use_mmap = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_REGISTRY, "use mmap", false); |
| 141 | |
| 142 | // create dictionaries |
| 143 | registry.persons = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); |
| 144 | registry.machines = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); |
| 145 | |
| 146 | // initialize the allocators |
| 147 | |
| 148 | size_t min_page_size = 4 * 1024; |
| 149 | size_t max_page_size = 1024 * 1024; |
| 150 | |
| 151 | if(use_mmap) { |
| 152 | min_page_size = 100 * 1024 * 1024; |
| 153 | max_page_size = 512 * 1024 * 1024; |
| 154 | } |
| 155 | |
| 156 | registry.persons_aral = aral_create("registry_persons", sizeof(REGISTRY_PERSON), |
| 157 | min_page_size / sizeof(REGISTRY_PERSON), max_page_size, |
| 158 | ®istry.aral_stats, |
| 159 | "registry_persons", |
| 160 | &netdata_configured_cache_dir, |
| 161 | use_mmap, true, true); |
| 162 | |
| 163 | registry.machines_aral = aral_create("registry_machines", sizeof(REGISTRY_MACHINE), |
| 164 | min_page_size / sizeof(REGISTRY_MACHINE), max_page_size, |
| 165 | ®istry.aral_stats, |
| 166 | "registry_machines", |
| 167 | &netdata_configured_cache_dir, |
| 168 | use_mmap, true, true); |
| 169 | |
| 170 | registry.person_urls_aral = aral_create("registry_person_urls", sizeof(REGISTRY_PERSON_URL), |
| 171 | min_page_size / sizeof(REGISTRY_PERSON_URL), max_page_size, |
| 172 | ®istry.aral_stats, |
| 173 | "registry_person_urls", |
| 174 | &netdata_configured_cache_dir, |
| 175 | use_mmap, true, true); |
| 176 | |
| 177 | registry.machine_urls_aral = aral_create("registry_machine_urls", sizeof(REGISTRY_MACHINE_URL), |
| 178 | min_page_size / sizeof(REGISTRY_MACHINE_URL), max_page_size, |
| 179 | ®istry.aral_stats, |
| 180 | "registry_machine_urls", |
| 181 | &netdata_configured_cache_dir, |
| 182 | use_mmap, true, true); |
| 183 | |
| 184 | registry_log_open(); |
| 185 | registry_db_load(); |
| 186 | registry_log_load(); |
| 187 | |
| 188 | if(unlikely(registry_db_should_be_saved())) |
| 189 | registry_db_save(); |
| 190 | |
| 191 | // registry_db_stats(); |
| 192 | // registry_generate_curl_urls(); |
| 193 | // exit(0); |
| 194 | |
| 195 | return true; |
| 196 | } |
| 197 | |
| 198 | return false; |
| 199 | } |
| 200 | |
| 201 | static int machine_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data __maybe_unused) { |
| 202 | REGISTRY_MACHINE *m = (REGISTRY_MACHINE *)entry; |
| 203 | |
| 204 | int count = 0; |
| 205 | |
| 206 | while(m->machine_urls) { |
| 207 | registry_machine_url_unlink_from_machine_and_free(m, m->machine_urls); |
| 208 | count++; |
| 209 | } |
| 210 | |
| 211 | aral_freez(registry.machines_aral, m); |
| 212 | |
| 213 | return count + 1; |
| 214 | } |
| 215 | |
| 216 | static int registry_person_del_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *d __maybe_unused) { |
| 217 | REGISTRY_PERSON *p = (REGISTRY_PERSON *)entry; |
| 218 | |
| 219 | netdata_log_debug(D_REGISTRY, "Registry: registry_person_del('%s'): deleting person", p->guid); |
| 220 | |
| 221 | while(p->person_urls) |
| 222 | registry_person_unlink_from_url(p, (REGISTRY_PERSON_URL *)p->person_urls); |
| 223 | |
| 224 | //debug(D_REGISTRY, "Registry: deleting person '%s' from persons registry", p->guid); |
| 225 | //dictionary_del(registry.persons, p->guid); |
| 226 | |
| 227 | netdata_log_debug(D_REGISTRY, "Registry: freeing person '%s'", p->guid); |
| 228 | aral_freez(registry.persons_aral, p); |
| 229 | |
| 230 | return 1; |
| 231 | } |
| 232 | |
| 233 | void registry_free(void) { |
| 234 | if(!registry.enabled) return; |
| 235 | registry.enabled = false; |
| 236 | |
| 237 | netdata_log_debug(D_REGISTRY, "Registry: destroying persons dictionary"); |
| 238 | dictionary_walkthrough_read(registry.persons, registry_person_del_callback, NULL); |
| 239 | dictionary_destroy(registry.persons); |
| 240 | registry.persons = NULL; |
| 241 | |
| 242 | netdata_log_debug(D_REGISTRY, "Registry: destroying machines dictionary"); |
| 243 | dictionary_walkthrough_read(registry.machines, machine_delete_callback, NULL); |
| 244 | dictionary_destroy(registry.machines); |
| 245 | registry.machines = NULL; |
| 246 | |
| 247 | aral_destroy(registry.persons_aral); |
| 248 | aral_destroy(registry.machines_aral); |
| 249 | aral_destroy(registry.person_urls_aral); |
| 250 | aral_destroy(registry.machine_urls_aral); |
| 251 | registry.persons_aral = NULL; |
| 252 | registry.machines_aral = NULL; |
| 253 | registry.person_urls_aral = NULL; |
| 254 | registry.machine_urls_aral = NULL; |
| 255 | } |