diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-07-20 04:49:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-07-20 04:49:55 +0000 |
commit | ab1bb5b7f1c3c3a7b240ab7fc8661459ecd7decb (patch) | |
tree | 7a900833aad3ccc685712c6c2a7d87576d54f427 /registry | |
parent | Adding upstream version 1.40.1. (diff) | |
download | netdata-upstream/1.41.0.tar.xz netdata-upstream/1.41.0.zip |
Adding upstream version 1.41.0.upstream/1.41.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | registry/registry.c | 179 | ||||
-rw-r--r-- | registry/registry.h | 2 | ||||
-rw-r--r-- | registry/registry_db.c | 245 | ||||
-rw-r--r-- | registry/registry_init.c | 182 | ||||
-rw-r--r-- | registry/registry_internals.c | 135 | ||||
-rw-r--r-- | registry/registry_internals.h | 29 | ||||
-rw-r--r-- | registry/registry_log.c | 25 | ||||
-rw-r--r-- | registry/registry_machine.c | 65 | ||||
-rw-r--r-- | registry/registry_machine.h | 15 | ||||
-rw-r--r-- | registry/registry_person.c | 158 | ||||
-rw-r--r-- | registry/registry_person.h | 30 | ||||
-rw-r--r-- | registry/registry_url.c | 88 | ||||
-rw-r--r-- | registry/registry_url.h | 35 |
13 files changed, 633 insertions, 555 deletions
diff --git a/registry/registry.c b/registry/registry.c index f8de470eb..b63c6db0f 100644 --- a/registry/registry.c +++ b/registry/registry.c @@ -8,6 +8,10 @@ #define REGISTRY_STATUS_FAILED "failed" #define REGISTRY_STATUS_DISABLED "disabled" +bool registry_is_valid_url(const char *url) { + return url && (*url == 'h' || *url == '*'); +} + // ---------------------------------------------------------------------------- // REGISTRY concurrency locking @@ -23,19 +27,21 @@ static inline void registry_unlock(void) { // COOKIES static void registry_set_cookie(struct web_client *w, const char *guid) { - char edate[100]; + char e_date[100]; time_t et = now_realtime_sec() + registry.persons_expiration; - struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf); - strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm); + struct tm e_tm_buf, *etm = gmtime_r(&et, &e_tm_buf); + strftime(e_date, sizeof(e_date), "%a, %d %b %Y %H:%M:%S %Z", etm); - buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s\r\n", guid, edate); + buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s\r\n", guid, e_date); + buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; SameSite=Strict; Expires=%s\r\n", guid, e_date); if(registry.enable_cookies_samesite_secure) - buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; SameSite=None; Secure\r\n", guid, edate); + buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; SameSite=None; Secure\r\n", guid, e_date); if(registry.registry_domain && *registry.registry_domain) { - buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s\r\n", guid, edate, registry.registry_domain); + buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s\r\n", guid, e_date, registry.registry_domain); + buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s; SameSite=Strict\r\n", guid, e_date, registry.registry_domain); if(registry.enable_cookies_samesite_secure) - buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s; SameSite=None; Secure\r\n", guid, edate, registry.registry_domain); + buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s; SameSite=None; Secure\r\n", guid, e_date, registry.registry_domain); } w->response.has_cookies = true; @@ -52,7 +58,7 @@ static inline void registry_set_person_cookie(struct web_client *w, REGISTRY_PER static inline void registry_json_header(RRDHOST *host, struct web_client *w, const char *action, const char *status) { buffer_flush(w->response.data); w->response.data->content_type = CT_APPLICATION_JSON; - buffer_json_initialize(w->response.data, "\"", "\"", 0, true, false); + buffer_json_initialize(w->response.data, "\"", "\"", 0, true, true); buffer_json_member_add_string(w->response.data, "action", action); buffer_json_member_add_string(w->response.data, "status", status); buffer_json_member_add_string(w->response.data, "hostname", rrdhost_registry_hostname(host)); @@ -84,39 +90,44 @@ struct registry_json_walk_person_urls_callback { int count; }; +static STRING *asterisks = NULL; + // callback for rendering PERSON_URLs -static int registry_json_person_url_callback(void *entry, void *data) { - REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)entry; - struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data; +static int registry_json_person_url_callback(REGISTRY_PERSON_URL *pu, struct registry_json_walk_person_urls_callback *c) { + if(unlikely(!asterisks)) + asterisks = string_strdupz("***"); + struct web_client *w = c->w; - if (!strcmp(pu->url->url,"***")) return 0; + if (pu->url == asterisks) return 0; buffer_json_add_array_item_array(w->response.data); buffer_json_add_array_item_string(w->response.data, pu->machine->guid); - buffer_json_add_array_item_string(w->response.data, pu->url->url); + buffer_json_add_array_item_string(w->response.data, string2str(pu->url)); buffer_json_add_array_item_uint64(w->response.data, pu->last_t * (uint64_t) 1000); buffer_json_add_array_item_uint64(w->response.data, pu->usages); - buffer_json_add_array_item_string(w->response.data, pu->machine_name); + buffer_json_add_array_item_string(w->response.data, string2str(pu->machine_name)); buffer_json_array_close(w->response.data); return 1; } // callback for rendering MACHINE_URLs -static int registry_json_machine_url_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data) { - REGISTRY_MACHINE_URL *mu = (REGISTRY_MACHINE_URL *)entry; - struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data; +static int registry_json_machine_url_callback(REGISTRY_MACHINE_URL *mu, struct registry_json_walk_person_urls_callback *c, STRING *hostname) { + if(unlikely(!asterisks)) + asterisks = string_strdupz("***"); + struct web_client *w = c->w; REGISTRY_MACHINE *m = c->m; - if (!strcmp(mu->url->url,"***")) return 0; + if (mu->url == asterisks) return 0; buffer_json_add_array_item_array(w->response.data); buffer_json_add_array_item_string(w->response.data, m->guid); - buffer_json_add_array_item_string(w->response.data, mu->url->url); + buffer_json_add_array_item_string(w->response.data, string2str(mu->url)); buffer_json_add_array_item_uint64(w->response.data, mu->last_t * (uint64_t) 1000); buffer_json_add_array_item_uint64(w->response.data, mu->usages); + buffer_json_add_array_item_string(w->response.data, string2str(hostname)); buffer_json_array_close(w->response.data); return 1; @@ -130,9 +141,7 @@ struct registry_person_url_callback_verify_machine_exists_data { int count; }; -static inline int registry_person_url_callback_verify_machine_exists(void *entry, void *data) { - struct registry_person_url_callback_verify_machine_exists_data *d = (struct registry_person_url_callback_verify_machine_exists_data *)data; - REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)entry; +static inline int registry_person_url_callback_verify_machine_exists(REGISTRY_PERSON_URL *pu, struct registry_person_url_callback_verify_machine_exists_data *d) { REGISTRY_MACHINE *m = d->m; if(pu->machine == m) @@ -157,38 +166,84 @@ void registry_update_cloud_base_url() { int registry_request_hello_json(RRDHOST *host, struct web_client *w) { registry_json_header(host, w, "hello", REGISTRY_STATUS_OK); + if(host->node_id) + buffer_json_member_add_uuid(w->response.data, "node_id", host->node_id); + + buffer_json_member_add_object(w->response.data, "agent"); + { + buffer_json_member_add_string(w->response.data, "machine_guid", localhost->machine_guid); + + if(localhost->node_id) + buffer_json_member_add_uuid(w->response.data, "node_id", localhost->node_id); + + char *claim_id = get_agent_claimid(); + if (claim_id) { + buffer_json_member_add_string(w->response.data, "claim_id", claim_id); + freez(claim_id); + } + + buffer_json_member_add_boolean(w->response.data, "bearer_protection", netdata_is_protected_by_bearer); + } + buffer_json_object_close(w->response.data); + buffer_json_member_add_string(w->response.data, "registry", registry.registry_to_announce); buffer_json_member_add_string(w->response.data, "cloud_base_url", registry.cloud_base_url); buffer_json_member_add_boolean(w->response.data, "anonymous_statistics", netdata_anonymous_statistics_enabled); + buffer_json_member_add_array(w->response.data, "nodes"); + RRDHOST *h; + dfe_start_read(rrdhost_root_index, h) { + buffer_json_add_array_item_object(w->response.data); + buffer_json_member_add_string(w->response.data, "machine_guid", h->machine_guid); + + if(h->node_id) + buffer_json_member_add_uuid(w->response.data, "node_id", h->node_id); + + buffer_json_member_add_string(w->response.data, "hostname", rrdhost_registry_hostname(h)); + buffer_json_object_close(w->response.data); + } + dfe_done(h); + buffer_json_array_close(w->response.data); // nodes + registry_json_footer(w); return HTTP_RESP_OK; } // ---------------------------------------------------------------------------- -//public ACCESS request - -#define REGISTRY_VERIFY_COOKIES_GUID "give-me-back-this-cookie-now--please" +// public ACCESS request // the main method for registering an access int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when) { if(unlikely(!registry.enabled)) return registry_json_disabled(host, w, "access"); + if(!registry_is_valid_url(url)) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid URL given in the request"); + return HTTP_RESP_BAD_REQUEST; + } + // ------------------------------------------------------------------------ - // verify the browser supports cookies + // verify the browser supports cookies or the bearer if(registry.verify_cookies_redirects > 0 && !person_guid[0]) { + registry_lock(); + registry_request_access(REGISTRY_VERIFY_COOKIES_GUID, machine_guid, url, name, when); + registry_unlock(); + buffer_flush(w->response.data); registry_set_cookie(w, REGISTRY_VERIFY_COOKIES_GUID); w->response.data->content_type = CT_APPLICATION_JSON; registry_json_header(host, w, "access", REGISTRY_STATUS_REDIRECT); + buffer_json_member_add_string(w->response.data, "person_guid", REGISTRY_VERIFY_COOKIES_GUID); buffer_json_member_add_string(w->response.data, "registry", registry.registry_to_announce); registry_json_footer(w); return HTTP_RESP_OK; } - if(unlikely(person_guid[0] && !strcmp(person_guid, REGISTRY_VERIFY_COOKIES_GUID))) + if(unlikely(person_guid[0] && is_dummy_person(person_guid))) + // it passed the check - they gave us a different person_guid + // empty the dummy one, so that we will generate a new person_guid person_guid[0] = '\0'; // ------------------------------------------------------------------------ @@ -212,7 +267,8 @@ int registry_request_access_json(RRDHOST *host, struct web_client *w, char *pers buffer_json_member_add_array(w->response.data, "urls"); struct registry_json_walk_person_urls_callback c = { p, NULL, w, 0 }; - avl_traverse(&p->person_urls, registry_json_person_url_callback, &c); + for(REGISTRY_PERSON_URL *pu = p->person_urls; pu ;pu = pu->next) + registry_json_person_url_callback(pu, &c); buffer_json_array_close(w->response.data); // urls registry_json_footer(w); @@ -228,6 +284,12 @@ int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *pers if(!registry.enabled) return registry_json_disabled(host, w, "delete"); + if(!registry_is_valid_url(url)) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid URL given in the request"); + return HTTP_RESP_BAD_REQUEST; + } + registry_lock(); REGISTRY_PERSON *p = registry_request_delete(person_guid, machine_guid, url, delete_url, when); @@ -249,17 +311,25 @@ int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *pers // public SEARCH request // the main method for searching the URLs of a netdata -int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) { +int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *request_machine) { if(!registry.enabled) return registry_json_disabled(host, w, "search"); + if(!person_guid || !person_guid[0]) { + registry_json_header(host, w, "search", REGISTRY_STATUS_FAILED); + registry_json_footer(w); + return HTTP_RESP_PRECOND_FAIL; + } + registry_lock(); - REGISTRY_MACHINE *m = registry_request_machine(person_guid, machine_guid, url, request_machine, when); + STRING *hostname = NULL; + REGISTRY_MACHINE *m = registry_request_machine(person_guid, request_machine, &hostname); if(!m) { registry_json_header(host, w, "search", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); + string_freez(hostname); return HTTP_RESP_NOT_FOUND; } @@ -267,11 +337,15 @@ int registry_request_search_json(RRDHOST *host, struct web_client *w, char *pers buffer_json_member_add_array(w->response.data, "urls"); struct registry_json_walk_person_urls_callback c = { NULL, m, w, 0 }; - dictionary_walkthrough_read(m->machine_urls, registry_json_machine_url_callback, &c); + + for(REGISTRY_MACHINE_URL *mu = m->machine_urls; mu ; mu = mu->next) + registry_json_machine_url_callback(mu, &c, hostname); + buffer_json_array_close(w->response.data); registry_json_footer(w); registry_unlock(); + string_freez(hostname); return HTTP_RESP_OK; } @@ -279,12 +353,21 @@ int registry_request_search_json(RRDHOST *host, struct web_client *w, char *pers // SWITCH REQUEST // the main method for switching user identity -int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when) { +int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url __maybe_unused, char *new_person_guid, time_t when __maybe_unused) { if(!registry.enabled) return registry_json_disabled(host, w, "switch"); - (void)url; - (void)when; + if(!person_guid || !person_guid[0]) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Who are you? Person GUID is missing"); + return HTTP_RESP_PRECOND_FAIL; + } + + if(!registry_is_valid_url(url)) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid URL given in the request"); + return HTTP_RESP_BAD_REQUEST; + } registry_lock(); @@ -315,7 +398,9 @@ int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *pers struct registry_person_url_callback_verify_machine_exists_data data = { m, 0 }; // verify the old person has access to this machine - avl_traverse(&op->person_urls, registry_person_url_callback_verify_machine_exists, &data); + for(REGISTRY_PERSON_URL *pu = op->person_urls; pu ;pu = pu->next) + registry_person_url_callback_verify_machine_exists(pu, &data); + if(!data.count) { registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); @@ -325,7 +410,9 @@ int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *pers // verify the new person has access to this machine data.count = 0; - avl_traverse(&np->person_urls, registry_person_url_callback_verify_machine_exists, &data); + for(REGISTRY_PERSON_URL *pu = np->person_urls; pu ;pu = pu->next) + registry_person_url_callback_verify_machine_exists(pu, &data); + if(!data.count) { registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); @@ -396,14 +483,12 @@ void registry_statistics(void) { rrddim_add(stc, "persons", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stc, "machines", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(stc, "urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stc, "persons_urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stc, "machines_urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } rrddim_set(stc, "persons", (collected_number)registry.persons_count); rrddim_set(stc, "machines", (collected_number)registry.machines_count); - rrddim_set(stc, "urls", (collected_number)registry.urls_count); rrddim_set(stc, "persons_urls", (collected_number)registry.persons_urls_count); rrddim_set(stc, "machines_urls", (collected_number)registry.machines_urls_count); rrdset_done(stc); @@ -428,15 +513,21 @@ void registry_statistics(void) { rrddim_add(stm, "persons", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stm, "machines", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(stm, "urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stm, "persons_urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stm, "machines_urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - rrddim_set(stm, "persons", (collected_number)registry.persons_memory + dictionary_stats_for_registry(registry.persons)); - rrddim_set(stm, "machines", (collected_number)registry.machines_memory + dictionary_stats_for_registry(registry.machines)); - rrddim_set(stm, "urls", (collected_number)registry.urls_memory); - rrddim_set(stm, "persons_urls", (collected_number)registry.persons_urls_memory); - rrddim_set(stm, "machines_urls", (collected_number)registry.machines_urls_memory); + struct aral_statistics *p_aral_stats = aral_statistics(registry.persons_aral); + rrddim_set(stm, "persons", (collected_number)p_aral_stats->structures.allocated_bytes + (collected_number)p_aral_stats->malloc.allocated_bytes + (collected_number)p_aral_stats->mmap.allocated_bytes); + + struct aral_statistics *m_aral_stats = aral_statistics(registry.machines_aral); + rrddim_set(stm, "machines", (collected_number)m_aral_stats->structures.allocated_bytes + (collected_number)m_aral_stats->malloc.allocated_bytes + (collected_number)m_aral_stats->mmap.allocated_bytes); + + struct aral_statistics *pu_aral_stats = aral_statistics(registry.person_urls_aral); + rrddim_set(stm, "persons_urls", (collected_number)pu_aral_stats->structures.allocated_bytes + (collected_number)pu_aral_stats->malloc.allocated_bytes + (collected_number)pu_aral_stats->mmap.allocated_bytes); + + struct aral_statistics *mu_aral_stats = aral_statistics(registry.machine_urls_aral); + rrddim_set(stm, "machines_urls", (collected_number)mu_aral_stats->structures.allocated_bytes + (collected_number)mu_aral_stats->malloc.allocated_bytes + (collected_number)mu_aral_stats->mmap.allocated_bytes); + rrdset_done(stm); } diff --git a/registry/registry.h b/registry/registry.h index 6aa3f0a11..a572991c7 100644 --- a/registry/registry.h +++ b/registry/registry.h @@ -64,7 +64,7 @@ void registry_free(void); // HTTP requests handled by the registry int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when); int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); -int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when); +int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *request_machine); int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when); int registry_request_hello_json(RRDHOST *host, struct web_client *w); diff --git a/registry/registry_db.c b/registry/registry_db.c index ae74aa530..a5c3956a5 100644 --- a/registry/registry_db.c +++ b/registry/registry_db.c @@ -4,25 +4,22 @@ #include "registry_internals.h" int registry_db_should_be_saved(void) { - debug(D_REGISTRY, "log entries %llu, max %llu", registry.log_count, registry.save_registry_every_entries); + netdata_log_debug(D_REGISTRY, "log entries %llu, max %llu", registry.log_count, registry.save_registry_every_entries); return registry.log_count > registry.save_registry_every_entries; } // ---------------------------------------------------------------------------- // INTERNAL FUNCTIONS FOR SAVING REGISTRY OBJECTS -static int registry_machine_save_url(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *file) { - REGISTRY_MACHINE_URL *mu = entry; - FILE *fp = file; - - debug(D_REGISTRY, "Registry: registry_machine_save_url('%s')", mu->url->url); +static int registry_machine_save_url(REGISTRY_MACHINE_URL *mu, FILE *fp) { + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_save_url('%s')", string2str(mu->url)); int ret = fprintf(fp, "V\t%08x\t%08x\t%08x\t%02x\t%s\n", mu->first_t, mu->last_t, mu->usages, mu->flags, - mu->url->url + string2str(mu->url) ); // error handling is done at registry_db_save() @@ -35,7 +32,7 @@ static int registry_machine_save(const DICTIONARY_ITEM *item __maybe_unused, voi REGISTRY_MACHINE *m = entry; FILE *fp = file; - debug(D_REGISTRY, "Registry: registry_machine_save('%s')", m->guid); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_save('%s')", m->guid); int ret = fprintf(fp, "M\t%08x\t%08x\t%08x\t%s\n", m->first_t, @@ -45,9 +42,13 @@ static int registry_machine_save(const DICTIONARY_ITEM *item __maybe_unused, voi ); if(ret >= 0) { - int ret2 = dictionary_walkthrough_read(m->machine_urls, registry_machine_save_url, fp); - if(ret2 < 0) return ret2; - ret += ret2; + for(REGISTRY_MACHINE_URL *mu = m->machine_urls; mu ; mu = mu->next) { + int rc = registry_machine_save_url(mu, fp); + if(rc < 0) + return rc; + + ret += rc; + } } // error handling is done at registry_db_save() @@ -55,11 +56,8 @@ static int registry_machine_save(const DICTIONARY_ITEM *item __maybe_unused, voi return ret; } -static inline int registry_person_save_url(void *entry, void *file) { - REGISTRY_PERSON_URL *pu = entry; - FILE *fp = file; - - debug(D_REGISTRY, "Registry: registry_person_save_url('%s')", pu->url->url); +static inline int registry_person_save_url(REGISTRY_PERSON_URL *pu, FILE *fp) { + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_person_save_url('%s')", string2str(pu->url)); int ret = fprintf(fp, "U\t%08x\t%08x\t%08x\t%02x\t%s\t%s\t%s\n", pu->first_t, @@ -67,8 +65,8 @@ static inline int registry_person_save_url(void *entry, void *file) { pu->usages, pu->flags, pu->machine->guid, - pu->machine_name, - pu->url->url + string2str(pu->machine_name), + string2str(pu->url) ); // error handling is done at registry_db_save() @@ -80,7 +78,7 @@ static inline int registry_person_save(const DICTIONARY_ITEM *item __maybe_unuse REGISTRY_PERSON *p = entry; FILE *fp = file; - debug(D_REGISTRY, "Registry: registry_person_save('%s')", p->guid); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_person_save('%s')", p->guid); int ret = fprintf(fp, "P\t%08x\t%08x\t%08x\t%s\n", p->first_t, @@ -90,10 +88,13 @@ static inline int registry_person_save(const DICTIONARY_ITEM *item __maybe_unuse ); if(ret >= 0) { - //int ret2 = dictionary_walkthrough_read(p->person_urls, registry_person_save_url, fp); - int ret2 = avl_traverse(&p->person_urls, registry_person_save_url, fp); - if (ret2 < 0) return ret2; - ret += ret2; + for(REGISTRY_PERSON_URL *pu = p->person_urls; pu ;pu = pu->next) { + int rc = registry_person_save_url(pu, fp); + if(rc < 0) + return rc; + else + ret += rc; + } } // error handling is done at registry_db_save() @@ -119,42 +120,42 @@ int registry_db_save(void) { snprintfz(old_filename, FILENAME_MAX, "%s.old", registry.db_filename); snprintfz(tmp_filename, FILENAME_MAX, "%s.tmp", registry.db_filename); - debug(D_REGISTRY, "Registry: Creating file '%s'", tmp_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: Creating file '%s'", tmp_filename); FILE *fp = fopen(tmp_filename, "w"); if(!fp) { - error("Registry: Cannot create file: %s", tmp_filename); + netdata_log_error("REGISTRY: Cannot create file: %s", tmp_filename); error_log_limit_reset(); return -1; } // dictionary_walkthrough_read() has its own locking, so this is safe to do - debug(D_REGISTRY, "Saving all machines"); + netdata_log_debug(D_REGISTRY, "REGISTRY: saving all machines"); int bytes1 = dictionary_walkthrough_read(registry.machines, registry_machine_save, fp); if(bytes1 < 0) { - error("Registry: Cannot save registry machines - return value %d", bytes1); + netdata_log_error("REGISTRY: Cannot save registry machines - return value %d", bytes1); fclose(fp); error_log_limit_reset(); return bytes1; } - debug(D_REGISTRY, "Registry: saving machines took %d bytes", bytes1); + netdata_log_debug(D_REGISTRY, "REGISTRY: saving machines took %d bytes", bytes1); - debug(D_REGISTRY, "Saving all persons"); + netdata_log_debug(D_REGISTRY, "Saving all persons"); int bytes2 = dictionary_walkthrough_read(registry.persons, registry_person_save, fp); if(bytes2 < 0) { - error("Registry: Cannot save registry persons - return value %d", bytes2); + netdata_log_error("REGISTRY: Cannot save registry persons - return value %d", bytes2); fclose(fp); error_log_limit_reset(); return bytes2; } - debug(D_REGISTRY, "Registry: saving persons took %d bytes", bytes2); + netdata_log_debug(D_REGISTRY, "REGISTRY: saving persons took %d bytes", bytes2); // save the totals fprintf(fp, "T\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\n", registry.persons_count, registry.machines_count, registry.usages_count + 1, // this is required - it is lost on db rotation - registry.urls_count, + 0LLU, //registry.urls_count, registry.persons_urls_count, registry.machines_urls_count ); @@ -164,36 +165,36 @@ int registry_db_save(void) { errno = 0; // remove the .old db - debug(D_REGISTRY, "Registry: Removing old db '%s'", old_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: Removing old db '%s'", old_filename); if(unlink(old_filename) == -1 && errno != ENOENT) - error("Registry: cannot remove old registry file '%s'", old_filename); + netdata_log_error("REGISTRY: cannot remove old registry file '%s'", old_filename); // rename the db to .old - debug(D_REGISTRY, "Registry: Link current db '%s' to .old: '%s'", registry.db_filename, old_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: Link current db '%s' to .old: '%s'", registry.db_filename, old_filename); if(link(registry.db_filename, old_filename) == -1 && errno != ENOENT) - error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", registry.db_filename, old_filename); + netdata_log_error("REGISTRY: cannot move file '%s' to '%s'. Saving registry DB failed!", registry.db_filename, old_filename); else { // remove the database (it is saved in .old) - debug(D_REGISTRY, "Registry: removing db '%s'", registry.db_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: removing db '%s'", registry.db_filename); if (unlink(registry.db_filename) == -1 && errno != ENOENT) - error("Registry: cannot remove old registry file '%s'", registry.db_filename); + netdata_log_error("REGISTRY: cannot remove old registry file '%s'", registry.db_filename); // move the .tmp to make it active - debug(D_REGISTRY, "Registry: linking tmp db '%s' to active db '%s'", tmp_filename, registry.db_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: linking tmp db '%s' to active db '%s'", tmp_filename, registry.db_filename); if (link(tmp_filename, registry.db_filename) == -1) { - error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename, + netdata_log_error("REGISTRY: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename, registry.db_filename); // move the .old back - debug(D_REGISTRY, "Registry: linking old db '%s' to active db '%s'", old_filename, registry.db_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: linking old db '%s' to active db '%s'", old_filename, registry.db_filename); if(link(old_filename, registry.db_filename) == -1) - error("Registry: cannot move file '%s' to '%s'. Recovering the old registry DB failed!", old_filename, registry.db_filename); + netdata_log_error("REGISTRY: cannot move file '%s' to '%s'. Recovering the old registry DB failed!", old_filename, registry.db_filename); } else { - debug(D_REGISTRY, "Registry: removing tmp db '%s'", tmp_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: removing tmp db '%s'", tmp_filename); if(unlink(tmp_filename) == -1) - error("Registry: cannot remove tmp registry file '%s'", tmp_filename); + netdata_log_error("REGISTRY: cannot remove tmp registry file '%s'", tmp_filename); // it has been moved successfully // discard the current registry log @@ -215,75 +216,33 @@ size_t registry_db_load(void) { char *s, buf[4096 + 1]; REGISTRY_PERSON *p = NULL; REGISTRY_MACHINE *m = NULL; - REGISTRY_URL *u = NULL; + STRING *u = NULL; size_t line = 0; - debug(D_REGISTRY, "Registry: loading active db from: '%s'", registry.db_filename); + netdata_log_debug(D_REGISTRY, "REGISTRY: loading active db from: '%s'", registry.db_filename); FILE *fp = fopen(registry.db_filename, "r"); if(!fp) { - error("Registry: cannot open registry file: '%s'", registry.db_filename); + netdata_log_error("REGISTRY: cannot open registry file: '%s'", registry.db_filename); return 0; } + REGISTRY_MACHINE_URL *mu; size_t len = 0; buf[4096] = '\0'; while((s = fgets_trim_len(buf, 4096, fp, &len))) { line++; - debug(D_REGISTRY, "Registry: read line %zu to length %zu: %s", line, len, s); + netdata_log_debug(D_REGISTRY, "REGISTRY: read line %zu to length %zu: %s", line, len, s); switch(*s) { - case 'T': // totals - if(unlikely(len != 103 || s[1] != '\t' || s[18] != '\t' || s[35] != '\t' || s[52] != '\t' || s[69] != '\t' || s[86] != '\t' || s[103] != '\0')) { - error("Registry totals line %zu is wrong (len = %zu).", line, len); - continue; - } - registry.persons_count = strtoull(&s[2], NULL, 16); - registry.machines_count = strtoull(&s[19], NULL, 16); - registry.usages_count = strtoull(&s[36], NULL, 16); - registry.urls_count = strtoull(&s[53], NULL, 16); - registry.persons_urls_count = strtoull(&s[70], NULL, 16); - registry.machines_urls_count = strtoull(&s[87], NULL, 16); - break; - - case 'P': // person - m = NULL; - // verify it is valid - if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) { - error("Registry person line %zu is wrong (len = %zu).", line, len); - continue; - } - - s[1] = s[10] = s[19] = s[28] = '\0'; - p = registry_person_allocate(&s[29], strtoul(&s[2], NULL, 16)); - p->last_t = (uint32_t)strtoul(&s[11], NULL, 16); - p->usages = (uint32_t)strtoul(&s[20], NULL, 16); - debug(D_REGISTRY, "Registry loaded person '%s', first: %u, last: %u, usages: %u", p->guid, p->first_t, p->last_t, p->usages); - break; - - case 'M': // machine - p = NULL; - // verify it is valid - if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) { - error("Registry person line %zu is wrong (len = %zu).", line, len); - continue; - } - - s[1] = s[10] = s[19] = s[28] = '\0'; - m = registry_machine_allocate(&s[29], strtoul(&s[2], NULL, 16)); - m->last_t = (uint32_t)strtoul(&s[11], NULL, 16); - m->usages = (uint32_t)strtoul(&s[20], NULL, 16); - debug(D_REGISTRY, "Registry loaded machine '%s', first: %u, last: %u, usages: %u", m->guid, m->first_t, m->last_t, m->usages); - break; - case 'U': // person URL if(unlikely(!p)) { - error("Registry: ignoring line %zu, no person loaded: %s", line, s); + netdata_log_error("REGISTRY: ignoring line %zu, no person loaded: %s", line, s); continue; } // verify it is valid if(len < 69 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t' || s[68] != '\t') { - error("Registry person URL line %zu is wrong (len = %zu).", line, len); + netdata_log_error("REGISTRY: person URL line %zu is wrong (len = %zu).", line, len); continue; } @@ -293,51 +252,125 @@ size_t registry_db_load(void) { char *url = &s[69]; while(*url && *url != '\t') url++; if(!*url) { - error("Registry person URL line %zu does not have a url.", line); + netdata_log_error("REGISTRY: person URL line %zu does not have a url.", line); continue; } *url++ = '\0'; - // u = registry_url_allocate_nolock(url, strlen(url)); - u = registry_url_get(url, strlen(url)); + if(*url != 'h' && *url != '*') { + netdata_log_error("REGISTRY: person URL line %zu does not have a valid url: %s", line, url); + continue; + } + + u = string_strdupz(url); - time_t first_t = strtoul(&s[2], NULL, 16); + time_t first_t = (time_t)strtoul(&s[2], NULL, 16); m = registry_machine_find(&s[32]); if(!m) m = registry_machine_allocate(&s[32], first_t); - REGISTRY_PERSON_URL *pu = registry_person_url_allocate(p, m, u, &s[69], strlen(&s[69]), first_t); + mu = registry_machine_url_find(m, u); + if(!mu) { + netdata_log_error("REGISTRY: person URL line %zu was not linked to the machine it refers to", line); + mu = registry_machine_url_allocate(m, u, first_t); + } + + REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, u); + if(!pu) + pu = registry_person_url_allocate(p, m, u, &s[69], strlen(&s[69]), first_t); + else + netdata_log_error("REGISTRY: person URL line %zu is duplicate, reusing the old one.", line); + pu->last_t = (uint32_t)strtoul(&s[11], NULL, 16); pu->usages = (uint32_t)strtoul(&s[20], NULL, 16); pu->flags = (uint8_t)strtoul(&s[29], NULL, 16); - debug(D_REGISTRY, "Registry loaded person URL '%s' with name '%s' of machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, pu->machine_name, m->guid, pu->first_t, pu->last_t, pu->usages, pu->flags); + netdata_log_debug(D_REGISTRY, "REGISTRY: loaded person URL '%s' with name '%s' of machine '%s', first: %u, last: %u, usages: %u, flags: %02x", + string2str(u), string2str(pu->machine_name), m->guid, pu->first_t, pu->last_t, pu->usages, pu->flags); + + string_freez(u); + break; + + case 'P': // person + m = NULL; + // verify it is valid + if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) { + netdata_log_error("REGISTRY: person line %zu is wrong (len = %zu).", line, len); + continue; + } + + s[1] = s[10] = s[19] = s[28] = '\0'; + p = registry_person_allocate(&s[29], (time_t)strtoul(&s[2], NULL, 16)); + p->last_t = (uint32_t)strtoul(&s[11], NULL, 16); + p->usages = (uint32_t)strtoul(&s[20], NULL, 16); + netdata_log_debug(D_REGISTRY, "REGISTRY: loaded person '%s', first: %u, last: %u, usages: %u", p->guid, p->first_t, p->last_t, p->usages); break; case 'V': // machine URL if(unlikely(!m)) { - error("Registry: ignoring line %zu, no machine loaded: %s", line, s); + netdata_log_error("REGISTRY: ignoring line %zu, no machine loaded: %s", line, s); continue; } // verify it is valid if(len < 32 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t') { - error("Registry person URL line %zu is wrong (len = %zu).", line, len); + netdata_log_error("REGISTRY: person URL line %zu is wrong (len = %zu).", line, len); continue; } s[1] = s[10] = s[19] = s[28] = s[31] = '\0'; - // u = registry_url_allocate_nolock(&s[32], strlen(&s[32])); - u = registry_url_get(&s[32], strlen(&s[32])); - REGISTRY_MACHINE_URL *mu = registry_machine_url_allocate(m, u, strtoul(&s[2], NULL, 16)); + url = &s[32]; + if(*url != 'h' && *url != '*') { + netdata_log_error("REGISTRY: machine URL line %zu does not have a valid url: %s", line, url); + continue; + } + + u = string_strdupz(url); + + mu = registry_machine_url_find(m, u); + if(!mu) + mu = registry_machine_url_allocate(m, u, (time_t)strtoul(&s[2], NULL, 16)); + else + netdata_log_error("REGISTRY: machine URL line %zu is duplicate, reusing the old one.", line); + mu->last_t = (uint32_t)strtoul(&s[11], NULL, 16); mu->usages = (uint32_t)strtoul(&s[20], NULL, 16); mu->flags = (uint8_t)strtoul(&s[29], NULL, 16); - debug(D_REGISTRY, "Registry loaded machine URL '%s', machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, m->guid, mu->first_t, mu->last_t, mu->usages, mu->flags); + netdata_log_debug(D_REGISTRY, "Registry loaded machine URL '%s', machine '%s', first: %u, last: %u, usages: %u, flags: %02x", + string2str(u), m->guid, mu->first_t, mu->last_t, mu->usages, mu->flags); + + string_freez(u); + break; + + case 'M': // machine + p = NULL; + // verify it is valid + if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) { + netdata_log_error("REGISTRY: person line %zu is wrong (len = %zu).", line, len); + continue; + } + + s[1] = s[10] = s[19] = s[28] = '\0'; + m = registry_machine_allocate(&s[29], (time_t)strtoul(&s[2], NULL, 16)); + m->last_t = (uint32_t)strtoul(&s[11], NULL, 16); + m->usages = (uint32_t)strtoul(&s[20], NULL, 16); + netdata_log_debug(D_REGISTRY, "REGISTRY: loaded machine '%s', first: %u, last: %u, usages: %u", m->guid, m->first_t, m->last_t, m->usages); + break; + + case 'T': // totals + if(unlikely(len != 103 || s[1] != '\t' || s[18] != '\t' || s[35] != '\t' || s[52] != '\t' || s[69] != '\t' || s[86] != '\t' || s[103] != '\0')) { + netdata_log_error("REGISTRY: totals line %zu is wrong (len = %zu).", line, len); + continue; + } + registry.persons_count = strtoull(&s[2], NULL, 16); + registry.machines_count = strtoull(&s[19], NULL, 16); + registry.usages_count = strtoull(&s[36], NULL, 16); + registry.persons_urls_count = strtoull(&s[70], NULL, 16); + registry.machines_urls_count = strtoull(&s[87], NULL, 16); break; default: - error("Registry: ignoring line %zu of filename '%s': %s.", line, registry.db_filename, s); + netdata_log_error("REGISTRY: ignoring line %zu of filename '%s': %s.", line, registry.db_filename, s); break; } } diff --git a/registry/registry_init.c b/registry/registry_init.c index ba4250ef3..79523e258 100644 --- a/registry/registry_init.c +++ b/registry/registry_init.c @@ -3,6 +3,65 @@ #include "daemon/common.h" #include "registry_internals.h" +void registry_db_stats(void) { + size_t persons = 0; + size_t persons_urls = 0; + size_t max_urls_per_person = 0; + + REGISTRY_PERSON *p; + dfe_start_read(registry.persons, p) { + persons++; + size_t urls = 0; + for(REGISTRY_PERSON_URL *pu = p->person_urls ; pu ;pu = pu->next) + urls++; + + if(urls > max_urls_per_person) + max_urls_per_person = urls; + + persons_urls += urls; + } + dfe_done(p); + + size_t machines = 0; + size_t machines_urls = 0; + size_t max_urls_per_machine = 0; + + REGISTRY_MACHINE *m; + dfe_start_read(registry.machines, m) { + machines++; + size_t urls = 0; + for(REGISTRY_MACHINE_URL *mu = m->machine_urls ; mu ;mu = mu->next) + urls++; + + if(urls > max_urls_per_machine) + max_urls_per_machine = urls; + + machines_urls += urls; + } + dfe_done(m); + + netdata_log_info("REGISTRY: persons %zu, person_urls %zu, max_urls_per_person %zu, " + "machines %zu, machine_urls %zu, max_urls_per_machine %zu", + persons, persons_urls, max_urls_per_person, + machines, machines_urls, max_urls_per_machine); +} + +void registry_generate_curl_urls(void) { + FILE *fp = fopen("/tmp/registry.curl", "w+"); + if (unlikely(!fp)) + return; + + REGISTRY_PERSON *p; + dfe_start_read(registry.persons, p) { + for(REGISTRY_PERSON_URL *pu = p->person_urls ; pu ;pu = pu->next) { + fprintf(fp, "do_curl '%s' '%s' '%s'\n", p->guid, pu->machine->guid, string2str(pu->url)); + } + } + dfe_done(p); + + fclose(fp); +} + int registry_init(void) { char filename[FILENAME_MAX + 1]; @@ -11,12 +70,12 @@ int registry_init(void) { registry.enabled = config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0); } else { - info("Registry is disabled - use the central netdata"); + netdata_log_info("Registry is disabled - use the central netdata"); config_set_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0); registry.enabled = 0; } - // pathnames + // path names snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir); registry.pathname = config_get(CONFIG_SECTION_DIRECTORIES, "registry", filename); if(mkdir(registry.pathname, 0770) == -1 && errno != EEXIST) @@ -57,91 +116,134 @@ int registry_init(void) { config_set_number(CONFIG_SECTION_REGISTRY, "max URL name length", (long long)registry.max_name_length); } + bool use_mmap = config_get_boolean(CONFIG_SECTION_REGISTRY, "use mmap", false); + // initialize entries counters registry.persons_count = 0; registry.machines_count = 0; registry.usages_count = 0; - registry.urls_count = 0; registry.persons_urls_count = 0; registry.machines_urls_count = 0; - // initialize memory counters - registry.persons_memory = 0; - registry.machines_memory = 0; - registry.urls_memory = 0; - registry.persons_urls_memory = 0; - registry.machines_urls_memory = 0; - // initialize locks netdata_mutex_init(®istry.lock); - // create dictionaries - registry.persons = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); - registry.machines = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); - avl_init(®istry.registry_urls_root_index, registry_url_compare); - // load the registry database if(registry.enabled) { + // create dictionaries + registry.persons = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); + registry.machines = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); + + // initialize the allocators + + size_t min_page_size = 4 * 1024; + size_t max_page_size = 1024 * 1024; + + if(use_mmap) { + min_page_size = 100 * 1024 * 1024; + max_page_size = 512 * 1024 * 1024; + } + + registry.persons_aral = aral_create("registry_persons", sizeof(REGISTRY_PERSON), + min_page_size / sizeof(REGISTRY_PERSON), max_page_size, + ®istry.aral_stats, + "registry_persons", + &netdata_configured_cache_dir, + use_mmap, true); + + registry.machines_aral = aral_create("registry_machines", sizeof(REGISTRY_MACHINE), + min_page_size / sizeof(REGISTRY_MACHINE), max_page_size, + ®istry.aral_stats, + "registry_machines", + &netdata_configured_cache_dir, + use_mmap, true); + + registry.person_urls_aral = aral_create("registry_person_urls", sizeof(REGISTRY_PERSON_URL), + min_page_size / sizeof(REGISTRY_PERSON_URL), max_page_size, + ®istry.aral_stats, + "registry_person_urls", + &netdata_configured_cache_dir, + use_mmap, true); + + registry.machine_urls_aral = aral_create("registry_machine_urls", sizeof(REGISTRY_MACHINE_URL), + min_page_size / sizeof(REGISTRY_MACHINE_URL), max_page_size, + ®istry.aral_stats, + "registry_machine_urls", + &netdata_configured_cache_dir, + use_mmap, true); + + // disable cancelability to avoid enable/disable per item in the dictionary locks + netdata_thread_disable_cancelability(); + registry_log_open(); registry_db_load(); registry_log_load(); if(unlikely(registry_db_should_be_saved())) registry_db_save(); + +// registry_db_stats(); +// registry_generate_curl_urls(); +// exit(0); + + netdata_thread_enable_cancelability(); } return 0; } -static int machine_urls_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data) { - REGISTRY_MACHINE *m = (REGISTRY_MACHINE *)data; - (void)m; +static int machine_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data __maybe_unused) { + REGISTRY_MACHINE *m = (REGISTRY_MACHINE *)entry; - REGISTRY_MACHINE_URL *mu = (REGISTRY_MACHINE_URL *)entry; + int count = 0; - debug(D_REGISTRY, "Registry: unlinking url '%s' from machine", mu->url->url); - registry_url_unlink(mu->url); + while(m->machine_urls) { + registry_machine_url_unlink_from_machine_and_free(m, m->machine_urls); + count++; + } - debug(D_REGISTRY, "Registry: freeing machine url"); - freez(mu); + aral_freez(registry.machines_aral, m); - return 1; + return count + 1; } -static int machine_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data __maybe_unused) { - REGISTRY_MACHINE *m = (REGISTRY_MACHINE *)entry; - int ret = dictionary_walkthrough_read(m->machine_urls, machine_urls_delete_callback, m); - - dictionary_destroy(m->machine_urls); - freez(m); - - return ret + 1; -} static int registry_person_del_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *d __maybe_unused) { REGISTRY_PERSON *p = (REGISTRY_PERSON *)entry; - debug(D_REGISTRY, "Registry: registry_person_del('%s'): deleting person", p->guid); + netdata_log_debug(D_REGISTRY, "Registry: registry_person_del('%s'): deleting person", p->guid); - while(p->person_urls.root) - registry_person_unlink_from_url(p, (REGISTRY_PERSON_URL *)p->person_urls.root); + while(p->person_urls) + registry_person_unlink_from_url(p, (REGISTRY_PERSON_URL *)p->person_urls); //debug(D_REGISTRY, "Registry: deleting person '%s' from persons registry", p->guid); //dictionary_del(registry.persons, p->guid); - debug(D_REGISTRY, "Registry: freeing person '%s'", p->guid); - freez(p); + netdata_log_debug(D_REGISTRY, "Registry: freeing person '%s'", p->guid); + aral_freez(registry.persons_aral, p); return 1; } void registry_free(void) { if(!registry.enabled) return; + registry.enabled = false; - debug(D_REGISTRY, "Registry: destroying persons dictionary"); + netdata_log_debug(D_REGISTRY, "Registry: destroying persons dictionary"); dictionary_walkthrough_read(registry.persons, registry_person_del_callback, NULL); dictionary_destroy(registry.persons); + registry.persons = NULL; - debug(D_REGISTRY, "Registry: destroying machines dictionary"); + netdata_log_debug(D_REGISTRY, "Registry: destroying machines dictionary"); dictionary_walkthrough_read(registry.machines, machine_delete_callback, NULL); dictionary_destroy(registry.machines); + registry.machines = NULL; + + aral_destroy(registry.persons_aral); + aral_destroy(registry.machines_aral); + aral_destroy(registry.person_urls_aral); + aral_destroy(registry.machine_urls_aral); + registry.persons_aral = NULL; + registry.machines_aral = NULL; + registry.person_urls_aral = NULL; + registry.machine_urls_aral = NULL; } diff --git a/registry/registry_internals.c b/registry/registry_internals.c index fe4d2dac5..74f12b558 100644 --- a/registry/registry_internals.c +++ b/registry/registry_internals.c @@ -13,7 +13,7 @@ struct registry registry; int regenerate_guid(const char *guid, char *result) { uuid_t uuid; if(unlikely(uuid_parse(guid, uuid) == -1)) { - info("Registry: GUID '%s' is not a valid GUID.", guid); + netdata_log_info("Registry: GUID '%s' is not a valid GUID.", guid); return -1; } else { @@ -21,7 +21,7 @@ int regenerate_guid(const char *guid, char *result) { #ifdef NETDATA_INTERNAL_CHECKS if(strcmp(guid, result) != 0) - info("GUID '%s' and re-generated GUID '%s' differ!", guid, result); + netdata_log_info("GUID '%s' and re-generated GUID '%s' differ!", guid, result); #endif /* NETDATA_INTERNAL_CHECKS */ } @@ -80,11 +80,11 @@ static inline char *registry_fix_url(char *url, size_t *len) { // HELPERS // verify the person, the machine and the URL exist in our DB -REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_guid, char *url, REGISTRY_PERSON **pp, REGISTRY_MACHINE **mm) { +REGISTRY_PERSON_URL *registry_verify_request(const char *person_guid, char *machine_guid, char *url, REGISTRY_PERSON **pp, REGISTRY_MACHINE **mm) { char pbuf[GUID_LEN + 1], mbuf[GUID_LEN + 1]; if(!person_guid || !*person_guid || !machine_guid || !*machine_guid || !url || !*url) { - info("Registry Request Verification: invalid request! person: '%s', machine '%s', url '%s'", person_guid?person_guid:"UNSET", machine_guid?machine_guid:"UNSET", url?url:"UNSET"); + netdata_log_info("Registry Request Verification: invalid request! person: '%s', machine '%s', url '%s'", person_guid?person_guid:"UNSET", machine_guid?machine_guid:"UNSET", url?url:"UNSET"); return NULL; } @@ -93,14 +93,14 @@ REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_gu // make sure the person GUID is valid if(regenerate_guid(person_guid, pbuf) == -1) { - info("Registry Request Verification: invalid person GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); + netdata_log_info("Registry Request Verification: invalid person GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } person_guid = pbuf; // make sure the machine GUID is valid if(regenerate_guid(machine_guid, mbuf) == -1) { - info("Registry Request Verification: invalid machine GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); + netdata_log_info("Registry Request Verification: invalid machine GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } machine_guid = mbuf; @@ -108,7 +108,7 @@ REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_gu // make sure the machine exists REGISTRY_MACHINE *m = registry_machine_find(machine_guid); if(!m) { - info("Registry Request Verification: machine not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); + netdata_log_info("Registry Request Verification: machine not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } if(mm) *mm = m; @@ -116,18 +116,21 @@ REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_gu // make sure the person exist REGISTRY_PERSON *p = registry_person_find(person_guid); if(!p) { - info("Registry Request Verification: person not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); + netdata_log_info("Registry Request Verification: person not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } if(pp) *pp = p; - REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, url); + STRING *u = string_strdupz(url); + REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, u); + string_freez(u); + if(!pu) { - info("Registry Request Verification: URL not found for person, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); + netdata_log_info("Registry Request Verification: URL not found for person, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } //else if (pu->machine != m) { - // info("Registry Request Verification: Machine mismatch: person: '%s', machine requested='%s' <> loaded='%s', url '%s'", person_guid, machine_guid, pu->machine->guid, url); + // netdata_log_info("Registry Request Verification: Machine mismatch: person: '%s', machine requested='%s' <> loaded='%s', url '%s'", person_guid, machine_guid, pu->machine->guid, url); // return NULL; //} @@ -138,23 +141,28 @@ REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_gu // ---------------------------------------------------------------------------- // REGISTRY REQUESTS -REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when) { - debug(D_REGISTRY, "registry_request_access('%s', '%s', '%s'): NEW REQUEST", (person_guid)?person_guid:"", machine_guid, url); +REGISTRY_PERSON *registry_request_access(const char *person_guid, char *machine_guid, char *url, char *name, time_t when) { + netdata_log_debug(D_REGISTRY, "registry_request_access('%s', '%s', '%s'): NEW REQUEST", (person_guid)?person_guid:"", machine_guid, url); + + bool is_dummy = is_dummy_person(person_guid); - REGISTRY_MACHINE *m = registry_machine_get(machine_guid, when); + REGISTRY_MACHINE *m = registry_machine_find_or_create(machine_guid, when, is_dummy); if(!m) return NULL; + REGISTRY_PERSON *p = registry_person_find_or_create(person_guid, when, is_dummy); + // make sure the name is valid - size_t namelen; - name = registry_fix_machine_name(name, &namelen); + size_t name_len; + name = registry_fix_machine_name(name, &name_len); - size_t urllen; - url = registry_fix_url(url, &urllen); + size_t url_len; + url = registry_fix_url(url, &url_len); - REGISTRY_PERSON *p = registry_person_get(person_guid, when); + STRING *u = string_strdupz(url); + + if(!is_dummy) + registry_person_link_to_url(p, m, u, name, name_len, when); - REGISTRY_URL *u = registry_url_get(url, urllen); - registry_person_link_to_url(p, m, u, name, namelen, when); registry_machine_link_to_url(m, u, when); registry_log('A', p, m, u, name); @@ -164,7 +172,7 @@ REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, return p; } -REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) { +REGISTRY_PERSON *registry_request_delete(const char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) { (void) when; REGISTRY_PERSON *p = NULL; @@ -178,82 +186,63 @@ REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, // make sure the user is not deleting the url it uses /* if(!strcmp(delete_url, pu->url->url)) { - info("Registry Delete Request: delete URL is the one currently accessed, person: '%s', machine '%s', url '%s', delete url '%s'" + netdata_log_info("Registry Delete Request: delete URL is the one currently accessed, person: '%s', machine '%s', url '%s', delete url '%s'" , p->guid, m->guid, pu->url->url, delete_url); return NULL; } */ - REGISTRY_PERSON_URL *dpu = registry_person_url_index_find(p, delete_url); + STRING *d_url = string_strdupz(delete_url); + REGISTRY_PERSON_URL *dpu = registry_person_url_index_find(p, d_url); + string_freez(d_url); + if(!dpu) { - info("Registry Delete Request: URL not found for person: '%s', machine '%s', url '%s', delete url '%s'", p->guid - , m->guid, pu->url->url, delete_url); + netdata_log_info("Registry Delete Request: URL not found for person: '%s', machine '%s', url '%s', delete url '%s'", p->guid + , m->guid, string2str(pu->url), delete_url); return NULL; } - registry_log('D', p, m, pu->url, dpu->url->url); + registry_log('D', p, m, pu->url, string2str(dpu->url)); registry_person_unlink_from_url(p, dpu); return p; } -// a structure to pass to the dictionary_walkthrough_read() callback handler -struct machine_request_callback_data { - REGISTRY_MACHINE *find_this_machine; - REGISTRY_PERSON_URL *result; -}; - -// the callback function -// this will be run for every PERSON_URL of this PERSON -static int machine_request_callback(void *entry, void *data) { - REGISTRY_PERSON_URL *mypu = (REGISTRY_PERSON_URL *)entry; - struct machine_request_callback_data *myrdata = (struct machine_request_callback_data *)data; - - if(mypu->machine == myrdata->find_this_machine) { - myrdata->result = mypu; - return -1; // this will also stop the walk through - } - - return 0; // continue -} - -REGISTRY_MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) { - (void)when; - +REGISTRY_MACHINE *registry_request_machine(const char *person_guid, char *request_machine, STRING **hostname) { + char pbuf[GUID_LEN + 1]; char mbuf[GUID_LEN + 1]; - REGISTRY_PERSON *p = NULL; - REGISTRY_MACHINE *m = NULL; - REGISTRY_PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m); - if(!pu || !p || !m) return NULL; + // make sure the person GUID is valid + if(regenerate_guid(person_guid, pbuf) == -1) { + netdata_log_info("REGISTRY: %s(): invalid person GUID '%s'", __FUNCTION__ , person_guid); + return NULL; + } + person_guid = pbuf; - // make sure the machine GUID is valid + // make sure the person GUID is valid if(regenerate_guid(request_machine, mbuf) == -1) { - info("Registry Machine URLs request: invalid machine GUID, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine); + netdata_log_info("REGISTRY: %s(): invalid search machine GUID '%s'", __FUNCTION__ , request_machine); return NULL; } request_machine = mbuf; - // make sure the machine exists - m = registry_machine_find(request_machine); - if(!m) { - info("Registry Machine URLs request: machine not found, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, machine_guid, pu->url->url, request_machine); - return NULL; - } + REGISTRY_PERSON *p = registry_person_find(person_guid); + if(!p) return NULL; + + REGISTRY_MACHINE *m = registry_machine_find(request_machine); + if(!m) return NULL; // Verify the user has in the past accessed this machine // We will walk through the PERSON_URLs to find the machine // linking to our machine - // a structure to pass to the dictionary_walkthrough_read() callback handler - struct machine_request_callback_data rdata = { m, NULL }; - - // request a walk through on the dictionary - avl_traverse(&p->person_urls, machine_request_callback, &rdata); - - if(rdata.result) - return m; + // make sure the user has access + for(REGISTRY_PERSON_URL *pu = p->person_urls; pu ;pu = pu->next) + if(pu->machine == m) { + *hostname = string_dup(pu->machine_name); + return m; + } return NULL; } @@ -270,7 +259,7 @@ static inline int is_machine_guid_blacklisted(const char *guid) { if(!strcmp(guid, "8a795b0c-2311-11e6-8563-000c295076a6") || !strcmp(guid, "4aed1458-1c3e-11e6-a53f-000c290fc8f5") ) { - error("Blacklisted machine GUID '%s' found.", guid); + netdata_log_error("Blacklisted machine GUID '%s' found.", guid); return 1; } @@ -292,11 +281,11 @@ char *registry_get_this_machine_guid(void) { if(fd != -1) { char buf[GUID_LEN + 1]; if(read(fd, buf, GUID_LEN) != GUID_LEN) - error("Failed to read machine GUID from '%s'", registry.machine_guid_filename); + netdata_log_error("Failed to read machine GUID from '%s'", registry.machine_guid_filename); else { buf[GUID_LEN] = '\0'; if(regenerate_guid(buf, guid) == -1) { - error("Failed to validate machine GUID '%s' from '%s'. Ignoring it - this might mean this netdata will appear as duplicate in the registry.", + netdata_log_error("Failed to validate machine GUID '%s' from '%s'. Ignoring it - this might mean this netdata will appear as duplicate in the registry.", buf, registry.machine_guid_filename); guid[0] = '\0'; diff --git a/registry/registry_internals.h b/registry/registry_internals.h index 3456d788d..c7f8f43dd 100644 --- a/registry/registry_internals.h +++ b/registry/registry_internals.h @@ -10,28 +10,24 @@ #define REGISTRY_DICTIONARY_OPTIONS (DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_SINGLE_THREADED) +#define REGISTRY_VERIFY_COOKIES_GUID "11111111-2222-3333-4444-555555555555" +#define is_dummy_person(person_guid) (strcmp(person_guid, REGISTRY_VERIFY_COOKIES_GUID) == 0) + // ---------------------------------------------------------------------------- // COMMON structures struct registry { int enabled; + netdata_mutex_t lock; // entries counters / statistics unsigned long long persons_count; unsigned long long machines_count; unsigned long long usages_count; - unsigned long long urls_count; unsigned long long persons_urls_count; unsigned long long machines_urls_count; unsigned long long log_count; - // memory counters / statistics - unsigned long long persons_memory; - unsigned long long machines_memory; - unsigned long long urls_memory; - unsigned long long persons_urls_memory; - unsigned long long machines_urls_memory; - // configuration unsigned long long save_registry_every_entries; char *registry_domain; @@ -58,12 +54,15 @@ struct registry { DICTIONARY *persons; // dictionary of REGISTRY_PERSON *, with key the REGISTRY_PERSON.guid DICTIONARY *machines; // dictionary of REGISTRY_MACHINE *, with key the REGISTRY_MACHINE.guid - avl_tree_type registry_urls_root_index; + ARAL *persons_aral; + ARAL *machines_aral; - netdata_mutex_t lock; + ARAL *person_urls_aral; + ARAL *machine_urls_aral; + + struct aral_statistics aral_stats; }; -#include "registry_url.h" #include "registry_machine.h" #include "registry_person.h" #include "registry.h" @@ -71,12 +70,12 @@ struct registry { extern struct registry registry; // REGISTRY LOW-LEVEL REQUESTS (in registry-internals.c) -REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when); -REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); -REGISTRY_MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when); +REGISTRY_PERSON *registry_request_access(const char *person_guid, char *machine_guid, char *url, char *name, time_t when); +REGISTRY_PERSON *registry_request_delete(const char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); +REGISTRY_MACHINE *registry_request_machine(const char *person_guid, char *request_machine, STRING **hostname); // REGISTRY LOG (in registry_log.c) -void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name); +void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, STRING *u, const char *name); int registry_log_open(void); void registry_log_close(void); void registry_log_recreate(void); diff --git a/registry/registry_log.c b/registry/registry_log.c index b048135e6..118d47c15 100644 --- a/registry/registry_log.c +++ b/registry/registry_log.c @@ -3,7 +3,7 @@ #include "daemon/common.h" #include "registry_internals.h" -void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name) { +void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, STRING *u, const char *name) { if(likely(registry.log_fp)) { if(unlikely(fprintf(registry.log_fp, "%c\t%08x\t%s\t%s\t%s\t%s\n", action, @@ -11,8 +11,8 @@ void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY p->guid, m->guid, name, - u->url) < 0)) - error("Registry: failed to save log. Registry data may be lost in case of abnormal restart."); + string2str(u)) < 0)) + netdata_log_error("Registry: failed to save log. Registry data may be lost in case of abnormal restart."); // we increase the counter even on failures // so that the registry will be saved periodically @@ -33,11 +33,11 @@ int registry_log_open(void) { registry.log_fp = fopen(registry.log_filename, "a"); if(registry.log_fp) { if (setvbuf(registry.log_fp, NULL, _IOLBF, 0) != 0) - error("Cannot set line buffering on registry log file."); + netdata_log_error("Cannot set line buffering on registry log file."); return 0; } - error("Cannot open registry log file '%s'. Registry data will be lost in case of netdata or server crash.", registry.log_filename); + netdata_log_error("Cannot open registry log file '%s'. Registry data will be lost in case of netdata or server crash.", registry.log_filename); return -1; } @@ -55,7 +55,8 @@ void registry_log_recreate(void) { // open it with truncate registry.log_fp = fopen(registry.log_filename, "w"); if(registry.log_fp) fclose(registry.log_fp); - else error("Cannot truncate registry log '%s'", registry.log_filename); + else + netdata_log_error("Cannot truncate registry log '%s'", registry.log_filename); registry.log_fp = NULL; registry_log_open(); @@ -69,10 +70,10 @@ ssize_t registry_log_load(void) { // otherwise we will append to it the values we read registry_log_close(); - debug(D_REGISTRY, "Registry: loading active db from: %s", registry.log_filename); + netdata_log_debug(D_REGISTRY, "Registry: loading active db from: %s", registry.log_filename); FILE *fp = fopen(registry.log_filename, "r"); if(!fp) - error("Registry: cannot open registry file: %s", registry.log_filename); + netdata_log_error("Registry: cannot open registry file: %s", registry.log_filename); else { char *s, buf[4096 + 1]; line = 0; @@ -87,13 +88,13 @@ ssize_t registry_log_load(void) { // verify it is valid if (unlikely(len < 85 || s[1] != '\t' || s[10] != '\t' || s[47] != '\t' || s[84] != '\t')) { - error("Registry: log line %zd is wrong (len = %zu).", line, len); + netdata_log_error("Registry: log line %zd is wrong (len = %zu).", line, len); continue; } s[1] = s[10] = s[47] = s[84] = '\0'; // get the variables - time_t when = strtoul(&s[2], NULL, 16); + time_t when = (time_t)strtoul(&s[2], NULL, 16); char *person_guid = &s[11]; char *machine_guid = &s[48]; char *name = &s[85]; @@ -102,7 +103,7 @@ ssize_t registry_log_load(void) { char *url = name; while(*url && *url != '\t') url++; if(!*url) { - error("Registry: log line %zd does not have a url.", line); + netdata_log_error("Registry: log line %zd does not have a url.", line); continue; } *url++ = '\0'; @@ -121,7 +122,7 @@ ssize_t registry_log_load(void) { break; default: - error("Registry: ignoring line %zd of filename '%s': %s.", line, registry.log_filename, s); + netdata_log_error("Registry: ignoring line %zd of filename '%s': %s.", line, registry.log_filename, s); break; } } diff --git a/registry/registry_machine.c b/registry/registry_machine.c index 414cd16d9..a94fb8ea4 100644 --- a/registry/registry_machine.c +++ b/registry/registry_machine.c @@ -7,52 +7,59 @@ // MACHINE REGISTRY_MACHINE *registry_machine_find(const char *machine_guid) { - debug(D_REGISTRY, "Registry: registry_machine_find('%s')", machine_guid); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_find('%s')", machine_guid); return dictionary_get(registry.machines, machine_guid); } -REGISTRY_MACHINE_URL *registry_machine_url_allocate(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when) { - debug(D_REGISTRY, "registry_machine_url_allocate('%s', '%s'): allocating %zu bytes", m->guid, u->url, sizeof(REGISTRY_MACHINE_URL)); +REGISTRY_MACHINE_URL *registry_machine_url_find(REGISTRY_MACHINE *m, STRING *url) { + REGISTRY_MACHINE_URL *mu; - REGISTRY_MACHINE_URL *mu = mallocz(sizeof(REGISTRY_MACHINE_URL)); + for(mu = m->machine_urls; mu ;mu = mu->next) + if(mu->url == url) + break; + + return mu; +} + +void registry_machine_url_unlink_from_machine_and_free(REGISTRY_MACHINE *m, REGISTRY_MACHINE_URL *mu) { + DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(m->machine_urls, mu, prev, next); + string_freez(mu->url); + aral_freez(registry.machine_urls_aral, mu); +} + +REGISTRY_MACHINE_URL *registry_machine_url_allocate(REGISTRY_MACHINE *m, STRING *u, time_t when) { + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_url_allocate('%s', '%s'): allocating %zu bytes", m->guid, string2str(u), sizeof(REGISTRY_MACHINE_URL)); + + REGISTRY_MACHINE_URL *mu = aral_mallocz(registry.machine_urls_aral); mu->first_t = mu->last_t = (uint32_t)when; mu->usages = 1; - mu->url = u; + mu->url = string_dup(u); mu->flags = REGISTRY_URL_FLAGS_DEFAULT; - registry.machines_urls_memory += sizeof(REGISTRY_MACHINE_URL); - - debug(D_REGISTRY, "registry_machine_url_allocate('%s', '%s'): indexing URL in machine", m->guid, u->url); - - registry.machines_urls_memory -= dictionary_stats_for_registry(m->machine_urls); - dictionary_set(m->machine_urls, u->url, mu, sizeof(REGISTRY_MACHINE_URL)); - registry.machines_urls_memory += dictionary_stats_for_registry(m->machine_urls); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_url_allocate('%s', '%s'): indexing URL in machine", m->guid, string2str(u)); - registry_url_link(u); + DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(m->machine_urls, mu, prev, next); return mu; } REGISTRY_MACHINE *registry_machine_allocate(const char *machine_guid, time_t when) { - debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating new machine, sizeof(MACHINE)=%zu", machine_guid, sizeof(REGISTRY_MACHINE)); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_allocate('%s'): creating new machine, sizeof(MACHINE)=%zu", machine_guid, sizeof(REGISTRY_MACHINE)); - REGISTRY_MACHINE *m = mallocz(sizeof(REGISTRY_MACHINE)); + REGISTRY_MACHINE *m = aral_mallocz(registry.machines_aral); strncpyz(m->guid, machine_guid, GUID_LEN); - debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating dictionary of urls", machine_guid); - m->machine_urls = dictionary_create(REGISTRY_DICTIONARY_OPTIONS); + m->machine_urls = NULL; m->first_t = m->last_t = (uint32_t)when; m->usages = 0; + m->links = 0; - registry.machines_memory += sizeof(REGISTRY_MACHINE); registry.machines_count++; - registry.machines_urls_memory -= dictionary_stats_for_registry(m->machine_urls); dictionary_set(registry.machines, m->guid, m, sizeof(REGISTRY_MACHINE)); - registry.machines_urls_memory += dictionary_stats_for_registry(m->machine_urls); return m; } @@ -60,14 +67,14 @@ REGISTRY_MACHINE *registry_machine_allocate(const char *machine_guid, time_t whe // 1. validate machine GUID // 2. if it is valid, find it or create it and return it // 3. if it is not valid, return NULL -REGISTRY_MACHINE *registry_machine_get(const char *machine_guid, time_t when) { +REGISTRY_MACHINE *registry_machine_find_or_create(const char *machine_guid, time_t when, bool is_dummy __maybe_unused) { REGISTRY_MACHINE *m = NULL; if(likely(machine_guid && *machine_guid)) { // validate it is a GUID char buf[GUID_LEN + 1]; if(unlikely(regenerate_guid(machine_guid, buf) == -1)) - info("Registry: machine guid '%s' is not a valid guid. Ignoring it.", machine_guid); + netdata_log_info("REGISTRY: machine guid '%s' is not a valid guid. Ignoring it.", machine_guid); else { machine_guid = buf; m = registry_machine_find(machine_guid); @@ -82,17 +89,17 @@ REGISTRY_MACHINE *registry_machine_get(const char *machine_guid, time_t when) { // ---------------------------------------------------------------------------- // LINKING OF OBJECTS -REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when) { - debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): searching for URL in machine", m->guid, u->url); +REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, STRING *url, time_t when) { + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_link_to_url('%s', '%s'): searching for URL in machine", m->guid, string2str(url)); - REGISTRY_MACHINE_URL *mu = dictionary_get(m->machine_urls, u->url); + REGISTRY_MACHINE_URL *mu = registry_machine_url_find(m, url); if(!mu) { - debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): not found", m->guid, u->url); - mu = registry_machine_url_allocate(m, u, when); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_link_to_url('%s', '%s'): not found", m->guid, string2str(url)); + mu = registry_machine_url_allocate(m, url, when); registry.machines_urls_count++; } else { - debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): found", m->guid, u->url); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_link_to_url('%s', '%s'): found", m->guid, string2str(url)); mu->usages++; if(likely(mu->last_t < (uint32_t)when)) mu->last_t = (uint32_t)when; } @@ -101,7 +108,7 @@ REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, REGISTRY if(likely(m->last_t < (uint32_t)when)) m->last_t = (uint32_t)when; if(mu->flags & REGISTRY_URL_FLAGS_EXPIRED) { - debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): accessing an expired URL.", m->guid, u->url); + netdata_log_debug(D_REGISTRY, "REGISTRY: registry_machine_link_to_url('%s', '%s'): accessing an expired URL.", m->guid, string2str(url)); mu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED; } diff --git a/registry/registry_machine.h b/registry/registry_machine.h index bc95ecf69..4e8a407fe 100644 --- a/registry/registry_machine.h +++ b/registry/registry_machine.h @@ -10,13 +10,15 @@ // For each MACHINE-URL pair we keep this struct registry_machine_url { - REGISTRY_URL *url; // de-duplicated URL + STRING *url; // de-duplicated URL uint8_t flags; uint32_t first_t; // the first time we saw this uint32_t last_t; // the last time we saw this uint32_t usages; // how many times this has been accessed + + struct registry_machine_url *prev, *next; }; typedef struct registry_machine_url REGISTRY_MACHINE_URL; @@ -26,7 +28,7 @@ struct registry_machine { uint32_t links; // the number of REGISTRY_PERSON_URL linked to this machine - DICTIONARY *machine_urls; // MACHINE_URL * + REGISTRY_MACHINE_URL *machine_urls; // MACHINE_URL * uint32_t first_t; // the first time we saw this uint32_t last_t; // the last time we saw this @@ -35,9 +37,12 @@ struct registry_machine { typedef struct registry_machine REGISTRY_MACHINE; REGISTRY_MACHINE *registry_machine_find(const char *machine_guid); -REGISTRY_MACHINE_URL *registry_machine_url_allocate(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when); +REGISTRY_MACHINE_URL *registry_machine_url_allocate(REGISTRY_MACHINE *m, STRING *u, time_t when); REGISTRY_MACHINE *registry_machine_allocate(const char *machine_guid, time_t when); -REGISTRY_MACHINE *registry_machine_get(const char *machine_guid, time_t when); -REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when); +REGISTRY_MACHINE *registry_machine_find_or_create(const char *machine_guid, time_t when, bool is_dummy); +REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, STRING *url, time_t when); + +REGISTRY_MACHINE_URL *registry_machine_url_find(REGISTRY_MACHINE *m, STRING *url); +void registry_machine_url_unlink_from_machine_and_free(REGISTRY_MACHINE *m, REGISTRY_MACHINE_URL *mu); #endif //NETDATA_REGISTRY_MACHINE_H diff --git a/registry/registry_person.c b/registry/registry_person.c index 2f55e99d3..4fd40fd75 100644 --- a/registry/registry_person.c +++ b/registry/registry_person.c @@ -6,103 +6,78 @@ // ---------------------------------------------------------------------------- // PERSON_URL INDEX -int person_url_compare(void *a, void *b) { - register uint32_t hash1 = ((REGISTRY_PERSON_URL *)a)->url->hash; - register uint32_t hash2 = ((REGISTRY_PERSON_URL *)b)->url->hash; +inline REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, STRING *url) { + netdata_log_debug(D_REGISTRY, "Registry: registry_person_url_index_find('%s', '%s')", p->guid, string2str(url)); - if(hash1 < hash2) return -1; - else if(hash1 > hash2) return 1; - else return strcmp(((REGISTRY_PERSON_URL *)a)->url->url, ((REGISTRY_PERSON_URL *)b)->url->url); -} - -inline REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, const char *url) { - debug(D_REGISTRY, "Registry: registry_person_url_index_find('%s', '%s')", p->guid, url); - - char buf[sizeof(REGISTRY_URL) + strlen(url)]; - - REGISTRY_URL *u = (REGISTRY_URL *)&buf; - strcpy(u->url, url); - u->hash = simple_hash(u->url); + REGISTRY_PERSON_URL *pu; + for(pu = p->person_urls ; pu ;pu = pu->next) + if(pu->url == url) + break; - REGISTRY_PERSON_URL tpu = { .url = u }; - - REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)avl_search(&p->person_urls, (void *)&tpu); return pu; } inline REGISTRY_PERSON_URL *registry_person_url_index_add(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) { - debug(D_REGISTRY, "Registry: registry_person_url_index_add('%s', '%s')", p->guid, pu->url->url); - REGISTRY_PERSON_URL *tpu = (REGISTRY_PERSON_URL *)avl_insert(&(p->person_urls), (avl_t *)(pu)); - if(tpu != pu) - error("Registry: registry_person_url_index_add('%s', '%s') already exists as '%s'", p->guid, pu->url->url, tpu->url->url); - - return tpu; + DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(p->person_urls, pu, prev, next); + return pu; } inline REGISTRY_PERSON_URL *registry_person_url_index_del(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) { - debug(D_REGISTRY, "Registry: registry_person_url_index_del('%s', '%s')", p->guid, pu->url->url); - REGISTRY_PERSON_URL *tpu = (REGISTRY_PERSON_URL *)avl_remove(&(p->person_urls), (avl_t *)(pu)); - if(!tpu) - error("Registry: registry_person_url_index_del('%s', '%s') deleted nothing", p->guid, pu->url->url); - else if(tpu != pu) - error("Registry: registry_person_url_index_del('%s', '%s') deleted wrong URL '%s'", p->guid, pu->url->url, tpu->url->url); - - return tpu; + DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(p->person_urls, pu, prev, next); + return pu; } // ---------------------------------------------------------------------------- // PERSON_URL -REGISTRY_PERSON_URL *registry_person_url_allocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when) { - debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url, sizeof(REGISTRY_PERSON_URL) + namelen); +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) { + 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); // protection from too big names - if(namelen > registry.max_name_length) - namelen = registry.max_name_length; + if(machine_name_len > registry.max_name_length) + machine_name_len = registry.max_name_length; - REGISTRY_PERSON_URL *pu = mallocz(sizeof(REGISTRY_PERSON_URL) + namelen); + REGISTRY_PERSON_URL *pu = aral_mallocz(registry.person_urls_aral); - // a simple strcpy() should do the job - // but I prefer to be safe, since the caller specified urllen - strncpyz(pu->machine_name, name, namelen); + // a simple strcpy() should do the job, + // but I prefer to be safe, since the caller specified name_len + pu->machine_name = string_strdupz(machine_name); pu->machine = m; pu->first_t = pu->last_t = (uint32_t)when; pu->usages = 1; - pu->url = u; + pu->url = string_dup(url); pu->flags = REGISTRY_URL_FLAGS_DEFAULT; m->links++; - registry.persons_urls_memory += sizeof(REGISTRY_PERSON_URL) + namelen; - - debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, u->url); + netdata_log_debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, string2str(url)); REGISTRY_PERSON_URL *tpu = registry_person_url_index_add(p, pu); if(tpu != pu) { - error("Registry: Attempted to add duplicate person url '%s' with name '%s' to person '%s'", u->url, name, p->guid); - freez(pu); + netdata_log_error("Registry: Attempted to add duplicate person url '%s' with name '%s' to person '%s'", string2str(url), machine_name, p->guid); + string_freez(pu->machine_name); + string_freez(pu->url); + aral_freez(registry.person_urls_aral, pu); pu = tpu; } - else - registry_url_link(u); return pu; } -void registry_person_url_free(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) { - debug(D_REGISTRY, "registry_person_url_free('%s', '%s')", p->guid, pu->url->url); +void registry_person_url_deindex_and_free(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) { + netdata_log_debug(D_REGISTRY, "registry_person_url_deindex_and_free('%s', '%s')", p->guid, string2str(pu->url)); REGISTRY_PERSON_URL *tpu = registry_person_url_index_del(p, pu); if(tpu) { - registry_url_unlink(tpu->url); + string_freez(tpu->machine_name); + string_freez(tpu->url); tpu->machine->links--; - registry.persons_urls_memory -= sizeof(REGISTRY_PERSON_URL) + strlen(tpu->machine_name); - freez(tpu); + aral_freez(registry.person_urls_aral, tpu); } } // this function is needed to change the name of a PERSON_URL -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) { - debug(D_REGISTRY, "registry_person_url_reallocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url, sizeof(REGISTRY_PERSON_URL) + namelen); +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) { + 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); // keep a backup REGISTRY_PERSON_URL pu2 = { @@ -111,15 +86,15 @@ REGISTRY_PERSON_URL *registry_person_url_reallocate(REGISTRY_PERSON *p, REGISTRY .usages = pu->usages, .flags = pu->flags, .machine = pu->machine, - .machine_name = "" + .machine_name = NULL }; // remove the existing one from the index - registry_person_url_free(p, pu); + registry_person_url_deindex_and_free(p, pu); pu = &pu2; // allocate a new one - REGISTRY_PERSON_URL *tpu = registry_person_url_allocate(p, m, u, name, namelen, when); + REGISTRY_PERSON_URL *tpu = registry_person_url_allocate(p, m, url, machine_name, machine_name_len, when); tpu->first_t = pu->first_t; tpu->last_t = pu->last_t; tpu->usages = pu->usages; @@ -133,40 +108,37 @@ REGISTRY_PERSON_URL *registry_person_url_reallocate(REGISTRY_PERSON *p, REGISTRY // PERSON REGISTRY_PERSON *registry_person_find(const char *person_guid) { - debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid); + netdata_log_debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid); return dictionary_get(registry.persons, person_guid); } REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when) { - debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(REGISTRY_PERSON)); + netdata_log_debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(REGISTRY_PERSON)); - REGISTRY_PERSON *p = mallocz(sizeof(REGISTRY_PERSON)); + REGISTRY_PERSON *p = aral_mallocz(registry.persons_aral); if(!person_guid) { for(;;) { uuid_t uuid; uuid_generate(uuid); uuid_unparse_lower(uuid, p->guid); - debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid); + netdata_log_debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid); if (!dictionary_get(registry.persons, p->guid)) { - debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid); + netdata_log_debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid); break; } else - info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid); + netdata_log_info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid); } } else strncpyz(p->guid, person_guid, GUID_LEN); - debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): creating dictionary of urls", p->guid); - avl_init(&p->person_urls, person_url_compare); + p->person_urls = NULL; p->first_t = p->last_t = (uint32_t)when; p->usages = 0; - registry.persons_memory += sizeof(REGISTRY_PERSON); - registry.persons_count++; dictionary_set(registry.persons, p->guid, p, sizeof(REGISTRY_PERSON)); @@ -178,23 +150,29 @@ REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when) // 2. if it is valid, find it // 3. if it is not valid, create a new one // 4. return it -REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when) { - debug(D_REGISTRY, "Registry: registry_person_get('%s'): creating dictionary of urls", person_guid); +REGISTRY_PERSON *registry_person_find_or_create(const char *person_guid, time_t when, bool is_dummy) { + netdata_log_debug(D_REGISTRY, "Registry: registry_person_find_or_create('%s'): creating dictionary of urls", person_guid); + char buf[GUID_LEN + 1]; REGISTRY_PERSON *p = NULL; if(person_guid && *person_guid) { - char buf[GUID_LEN + 1]; // validate it is a GUID - if(unlikely(regenerate_guid(person_guid, buf) == -1)) - info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid); + if(unlikely(regenerate_guid(person_guid, buf) == -1)) { + netdata_log_info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid); + person_guid = NULL; + } else { person_guid = buf; p = registry_person_find(person_guid); + if(!p && !is_dummy) + person_guid = NULL; } } + else + person_guid = NULL; - if(!p) p = registry_person_allocate(NULL, when); + if(!p) p = registry_person_allocate(person_guid, when); return p; } @@ -202,39 +180,39 @@ REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when) { // ---------------------------------------------------------------------------- // LINKING OF OBJECTS -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) { - debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, u->url); +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) { + netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, string2str(url)); - REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, u->url); + REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, url); if(!pu) { - debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url); - pu = registry_person_url_allocate(p, m, u, name, namelen, when); + netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, string2str(url)); + pu = registry_person_url_allocate(p, m, url, machine_name, machine_name_len, when); registry.persons_urls_count++; } else { - debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url); + netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, string2str(url)); pu->usages++; if(likely(pu->last_t < (uint32_t)when)) pu->last_t = (uint32_t)when; if(pu->machine != m) { - REGISTRY_MACHINE_URL *mu = dictionary_get(pu->machine->machine_urls, u->url); + REGISTRY_MACHINE_URL *mu = registry_machine_url_find(pu->machine, url); if(mu) { - debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.", - p->guid, m->guid, u->url, pu->machine->guid); + netdata_log_debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.", + p->guid, m->guid, string2str(url), pu->machine->guid); mu->flags |= REGISTRY_URL_FLAGS_EXPIRED; } else { - 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.", - p->guid, m->guid, u->url, pu->machine->guid); + 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.", + p->guid, m->guid, string2str(url), pu->machine->guid); } pu->machine->links--; pu->machine = m; } - if(strcmp(pu->machine_name, name) != 0) { + if(strcmp(string2str(pu->machine_name), machine_name) != 0) { // the name of the PERSON_URL has changed ! - pu = registry_person_url_reallocate(p, m, u, name, namelen, when, pu); + pu = registry_person_url_reallocate(p, m, url, machine_name, machine_name_len, when, pu); } } @@ -242,7 +220,7 @@ REGISTRY_PERSON_URL *registry_person_link_to_url(REGISTRY_PERSON *p, REGISTRY_MA if(likely(p->last_t < (uint32_t)when)) p->last_t = (uint32_t)when; if(pu->flags & REGISTRY_URL_FLAGS_EXPIRED) { - debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): accessing an expired URL. Re-enabling URL.", p->guid, m->guid, u->url); + 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)); pu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED; } @@ -250,5 +228,5 @@ REGISTRY_PERSON_URL *registry_person_link_to_url(REGISTRY_PERSON *p, REGISTRY_MA } void registry_person_unlink_from_url(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) { - registry_person_url_free(p, pu); + registry_person_url_deindex_and_free(p, pu); } diff --git a/registry/registry_person.h b/registry/registry_person.h index 674596be6..4c2ca710f 100644 --- a/registry/registry_person.h +++ b/registry/registry_person.h @@ -10,19 +10,18 @@ // for each PERSON-URL pair we keep this struct registry_person_url { - avl_t avl; // binary tree node - - REGISTRY_URL *url; // de-duplicated URL - REGISTRY_MACHINE *machine; // link the MACHINE of this URL - uint8_t flags; + uint32_t usages; // how many times this has been accessed + uint32_t first_t; // the first time we saw this uint32_t last_t; // the last time we saw this - uint32_t usages; // how many times this has been accessed - char machine_name[1]; // the name of the machine, as known by the user - // dynamically allocated to fit properly + REGISTRY_MACHINE *machine; // link the MACHINE of this URL + STRING *machine_name; // the hostname of the machine + STRING *url; // de-duplicated URL + + struct registry_person_url *prev, *next; }; typedef struct registry_person_url REGISTRY_PERSON_URL; @@ -30,32 +29,29 @@ typedef struct registry_person_url REGISTRY_PERSON_URL; struct registry_person { char guid[GUID_LEN + 1]; // the person GUID - avl_tree_type person_urls; // dictionary of PERSON_URLs + REGISTRY_PERSON_URL *person_urls; // dictionary of PERSON_URLs uint32_t first_t; // the first time we saw this uint32_t last_t; // the last time we saw this uint32_t usages; // how many times this has been accessed - - //uint32_t flags; - //char *email; }; typedef struct registry_person REGISTRY_PERSON; // PERSON_URL -REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, const char *url); +REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, STRING *url); REGISTRY_PERSON_URL *registry_person_url_index_add(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) NEVERNULL WARNUNUSED; REGISTRY_PERSON_URL *registry_person_url_index_del(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) WARNUNUSED; -REGISTRY_PERSON_URL *registry_person_url_allocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when); -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); +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); +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); // PERSON REGISTRY_PERSON *registry_person_find(const char *person_guid); REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when); -REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when); +REGISTRY_PERSON *registry_person_find_or_create(const char *person_guid, time_t when, bool is_dummy); // LINKING PERSON -> PERSON_URL -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); +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); void registry_person_unlink_from_url(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu); #endif //NETDATA_REGISTRY_PERSON_H diff --git a/registry/registry_url.c b/registry/registry_url.c deleted file mode 100644 index 699e5e680..000000000 --- a/registry/registry_url.c +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "daemon/common.h" -#include "registry_internals.h" - -// ---------------------------------------------------------------------------- -// REGISTRY_URL - -int registry_url_compare(void *a, void *b) { - if(((REGISTRY_URL *)a)->hash < ((REGISTRY_URL *)b)->hash) return -1; - else if(((REGISTRY_URL *)a)->hash > ((REGISTRY_URL *)b)->hash) return 1; - else return strcmp(((REGISTRY_URL *)a)->url, ((REGISTRY_URL *)b)->url); -} - -inline REGISTRY_URL *registry_url_index_add(REGISTRY_URL *u) { - return (REGISTRY_URL *)avl_insert(&(registry.registry_urls_root_index), (avl_t *)(u)); -} - -inline REGISTRY_URL *registry_url_index_del(REGISTRY_URL *u) { - return (REGISTRY_URL *)avl_remove(&(registry.registry_urls_root_index), (avl_t *)(u)); -} - -REGISTRY_URL *registry_url_get(const char *url, size_t urllen) { - // protection from too big URLs - if(urllen > registry.max_url_length) - urllen = registry.max_url_length; - - debug(D_REGISTRY, "Registry: registry_url_get('%s', %zu)", url, urllen); - - char buf[sizeof(REGISTRY_URL) + urllen]; // no need for +1, 1 is already in REGISTRY_URL - REGISTRY_URL *n = (REGISTRY_URL *)&buf[0]; - n->len = (uint16_t)urllen; - strncpyz(n->url, url, n->len); - n->hash = simple_hash(n->url); - - REGISTRY_URL *u = (REGISTRY_URL *)avl_search(&(registry.registry_urls_root_index), (avl_t *)n); - if(!u) { - debug(D_REGISTRY, "Registry: registry_url_get('%s', %zu): allocating %zu bytes", url, urllen, sizeof(REGISTRY_URL) + urllen); - u = callocz(1, sizeof(REGISTRY_URL) + urllen); // no need for +1, 1 is already in REGISTRY_URL - - // a simple strcpy() should do the job - // but I prefer to be safe, since the caller specified urllen - u->len = (uint16_t)urllen; - strncpyz(u->url, url, u->len); - u->links = 0; - u->hash = simple_hash(u->url); - - registry.urls_memory += sizeof(REGISTRY_URL) + urllen; // no need for +1, 1 is already in REGISTRY_URL - - debug(D_REGISTRY, "Registry: registry_url_get('%s'): indexing it", url); - n = registry_url_index_add(u); - if(n != u) { - error("INTERNAL ERROR: registry_url_get(): url '%s' already exists in the registry as '%s'", u->url, n->url); - freez(u); - u = n; - } - else - registry.urls_count++; - } - - return u; -} - -void registry_url_link(REGISTRY_URL *u) { - u->links++; - debug(D_REGISTRY, "Registry: registry_url_link('%s'): URL has now %u links", u->url, u->links); -} - -void registry_url_unlink(REGISTRY_URL *u) { - u->links--; - if(!u->links) { - debug(D_REGISTRY, "Registry: registry_url_unlink('%s'): No more links for this URL", u->url); - REGISTRY_URL *n = registry_url_index_del(u); - if(!n) { - error("INTERNAL ERROR: registry_url_unlink('%s'): cannot find url in index", u->url); - } - else { - if(n != u) { - error("INTERNAL ERROR: registry_url_unlink('%s'): deleted different url '%s'", u->url, n->url); - } - - registry.urls_memory -= sizeof(REGISTRY_URL) + n->len; // no need for +1, 1 is already in REGISTRY_URL - freez(n); - } - } - else - debug(D_REGISTRY, "Registry: registry_url_unlink('%s'): URL has %u links left", u->url, u->links); -} diff --git a/registry/registry_url.h b/registry/registry_url.h deleted file mode 100644 index 8ba0391bc..000000000 --- a/registry/registry_url.h +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef NETDATA_REGISTRY_URL_H -#define NETDATA_REGISTRY_URL_H 1 - -#include "registry_internals.h" - -// ---------------------------------------------------------------------------- -// URL structures -// Save memory by de-duplicating URLs -// so instead of storing URLs all over the place -// we store them here and we keep pointers elsewhere - -struct registry_url { - avl_t avl; - uint32_t hash; // the index hash - - uint32_t links; // the number of links to this URL - when none is left, we free it - - uint16_t len; // the length of the URL in bytes - char url[1]; // the URL - dynamically allocated to more size -}; -typedef struct registry_url REGISTRY_URL; - -// REGISTRY_URL INDEX -int registry_url_compare(void *a, void *b); -REGISTRY_URL *registry_url_index_del(REGISTRY_URL *u) WARNUNUSED; -REGISTRY_URL *registry_url_index_add(REGISTRY_URL *u) NEVERNULL WARNUNUSED; - -// REGISTRY_URL MANAGEMENT -REGISTRY_URL *registry_url_get(const char *url, size_t urllen) NEVERNULL; -void registry_url_link(REGISTRY_URL *u); -void registry_url_unlink(REGISTRY_URL *u); - -#endif //NETDATA_REGISTRY_URL_H |