From: Costa Tsaousis (ktsaou) Date: Sat, 18 Feb 2017 11:03:53 +0000 (+0200) Subject: localhost is now dynamic X-Git-Tag: ab-debian_0.20170227.01-0ab1~1^2~14^2~73 X-Git-Url: https://arthur.barton.de/gitweb/?a=commitdiff_plain;ds=sidebyside;h=eb304fda7a26091ffc2a4dd6392b65f06d387149;p=netdata.git localhost is now dynamic --- diff --git a/src/Makefile.am b/src/Makefile.am index c562b27e..0421ce38 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,7 +30,7 @@ endif netdata_SOURCES = \ appconfig.c appconfig.h \ - adaptive_resortable_list.c \adaptive_resortable_list.h \ + adaptive_resortable_list.c adaptive_resortable_list.h \ avl.c avl.h \ backends.c backends.h \ clocks.c clocks.h \ diff --git a/src/backends.c b/src/backends.c index b1c10d9d..c95a93a5 100644 --- a/src/backends.c +++ b/src/backends.c @@ -157,7 +157,7 @@ void *backends_main(void *ptr) { const char *type = config_get("backend", "type", "graphite"); const char *destination = config_get("backend", "destination", "localhost"); const char *prefix = config_get("backend", "prefix", "netdata"); - const char *hostname = config_get("backend", "hostname", localhost.hostname); + const char *hostname = config_get("backend", "hostname", localhost->hostname); int frequency = (int)config_get_number("backend", "update every", 10); int buffer_on_failures = (int)config_get_number("backend", "buffer on failures", 10); long timeoutms = config_get_number("backend", "timeout ms", frequency * 2 * 1000); @@ -310,19 +310,19 @@ void *backends_main(void *ptr) { if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); - rrdhost_rdlock(&localhost); - for(st = localhost.rrdset_root; st ;st = st->next) { + rrdhost_rdlock(localhost); + for(st = localhost->rrdset_root; st ;st = st->next) { pthread_rwlock_rdlock(&st->rwlock); RRDDIM *rd; for(rd = st->dimensions; rd ;rd = rd->next) { if(rd->last_collected_time.tv_sec >= after) - chart_buffered_metrics += backend_request_formatter(b, prefix, &localhost, hostname, st, rd, after, before, options); + chart_buffered_metrics += backend_request_formatter(b, prefix, localhost, hostname, st, rd, after, before, options); } pthread_rwlock_unlock(&st->rwlock); } - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); if(unlikely(pthread_setcancelstate(pthreadoldcancelstate, NULL) != 0)) error("Cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate); diff --git a/src/health.c b/src/health.c index 9df2e241..f60c702b 100644 --- a/src/health.c +++ b/src/health.c @@ -1555,7 +1555,7 @@ static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { if (rrdcalc_exists(host, rc->chart, rc->name, rc->hash_chart, rc->hash)) return 0; - rc->id = rrdcalc_get_unique_id(&localhost, rc->chart, rc->name, &rc->next_event_id); + rc->id = rrdcalc_get_unique_id(localhost, rc->chart, rc->name, &rc->next_event_id); debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", rc->chart?rc->chart:"NOCHART", @@ -2040,12 +2040,12 @@ int health_readfile(const char *path, const char *filename) { uint32_t hash = simple_uhash(key); if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { - if(rc && !rrdcalc_add_alarm_from_config(&localhost, rc)) - rrdcalc_free(&localhost, rc); + if(rc && !rrdcalc_add_alarm_from_config(localhost, rc)) + rrdcalc_free(localhost, rc); if(rt) { - if (!rrdcalctemplate_add_template_from_config(&localhost, rt)) - rrdcalctemplate_free(&localhost, rt); + if (!rrdcalctemplate_add_template_from_config(localhost, rt)) + rrdcalctemplate_free(localhost, rt); rt = NULL; } @@ -2065,13 +2065,13 @@ int health_readfile(const char *path, const char *filename) { } else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) { if(rc) { - if(!rrdcalc_add_alarm_from_config(&localhost, rc)) - rrdcalc_free(&localhost, rc); + if(!rrdcalc_add_alarm_from_config(localhost, rc)) + rrdcalc_free(localhost, rc); rc = NULL; } - if(rt && !rrdcalctemplate_add_template_from_config(&localhost, rt)) - rrdcalctemplate_free(&localhost, rt); + if(rt && !rrdcalctemplate_add_template_from_config(localhost, rt)) + rrdcalctemplate_free(localhost, rt); rt = callocz(1, sizeof(RRDCALCTEMPLATE)); rt->name = strdupz(value); @@ -2332,11 +2332,11 @@ int health_readfile(const char *path, const char *filename) { } } - if(rc && !rrdcalc_add_alarm_from_config(&localhost, rc)) - rrdcalc_free(&localhost, rc); + if(rc && !rrdcalc_add_alarm_from_config(localhost, rc)) + rrdcalc_free(localhost, rc); - if(rt && !rrdcalctemplate_add_template_from_config(&localhost, rt)) - rrdcalctemplate_free(&localhost, rt); + if(rt && !rrdcalctemplate_add_template_from_config(localhost, rt)) + rrdcalctemplate_free(localhost, rt); fclose(fp); return 1; @@ -2410,7 +2410,7 @@ void health_init(void) { snprintfz(filename, FILENAME_MAX, "%s/health-log.db", pathname); health.log_filename = config_get("health", "health db file", filename); - health_alarm_log_load(&localhost); + health_alarm_log_load(localhost); health_alarm_log_open(); char *path = health_config_dir(); @@ -2418,16 +2418,16 @@ void health_init(void) { snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir); health.health_default_exec = config_get("health", "script to execute on alarm", filename); - long n = config_get_number("health", "in memory max health log entries", (long)localhost.health_log.max); + long n = config_get_number("health", "in memory max health log entries", (long)localhost->health_log.max); if(n < 10) { - error("Health configuration has invalid max log entries %ld. Using default %u", n, localhost.health_log.max); - config_set_number("health", "in memory max health log entries", (long)localhost.health_log.max); + error("Health configuration has invalid max log entries %ld. Using default %u", n, localhost->health_log.max); + config_set_number("health", "in memory max health log entries", (long)localhost->health_log.max); } - else localhost.health_log.max = (unsigned int)n; + else localhost->health_log.max = (unsigned int)n; - rrdhost_rwlock(&localhost); + rrdhost_rwlock(localhost); health_readdir(path); - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); } // ---------------------------------------------------------------------------- @@ -2651,7 +2651,7 @@ static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) { void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) { int i; - rrdhost_rdlock(&localhost); + rrdhost_rdlock(localhost); buffer_sprintf(wb, "{\n\t\"hostname\": \"%s\"," "\n\t\"latest_alarm_log_unique_id\": %u," "\n\t\"status\": %s," @@ -2681,7 +2681,7 @@ void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) { // health_rrdcalctemplate2json_nolock(wb, rt); buffer_strcat(wb, "\n\t}\n}\n"); - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); } @@ -2705,37 +2705,37 @@ void health_reload(void) { char *path = health_config_dir(); // free all running alarms - rrdhost_rwlock(&localhost); - health_free_all_nolock(&localhost); - rrdhost_unlock(&localhost); + rrdhost_rwlock(localhost); + health_free_all_nolock(localhost); + rrdhost_unlock(localhost); // invalidate all previous entries in the alarm log ALARM_ENTRY *t; - for(t = localhost.health_log.alarms ; t ; t = t->next) { + for(t = localhost->health_log.alarms ; t ; t = t->next) { if(t->new_status != RRDCALC_STATUS_REMOVED) t->flags |= HEALTH_ENTRY_FLAG_UPDATED; } // reset all thresholds to all charts RRDSET *st; - for(st = localhost.rrdset_root; st ; st = st->next) { + for(st = localhost->rrdset_root; st ; st = st->next) { st->green = NAN; st->red = NAN; } // load the new alarms - rrdhost_rwlock(&localhost); + rrdhost_rwlock(localhost); health_readdir(path); - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); // link the loaded alarms to their charts - for(st = localhost.rrdset_root; st ; st = st->next) { - rrdhost_rwlock(&localhost); + for(st = localhost->rrdset_root; st ; st = st->next) { + rrdhost_rwlock(localhost); rrdsetcalc_link_matching(st); rrdcalctemplate_link_matching(st); - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); } } @@ -3013,10 +3013,10 @@ void *health_main(void *ptr) { if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); - rrdhost_rdlock(&localhost); + rrdhost_rdlock(localhost); // the first loop is to lookup values from the db - for(rc = localhost.alarms; rc; rc = rc->next) { + for(rc = localhost->alarms; rc; rc = rc->next) { if(unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) { if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE)) rc->rrdcalc_flags &= ~RRDCALC_FLAG_RUNNABLE; @@ -3121,12 +3121,12 @@ void *health_main(void *ptr) { } } } - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); if(unlikely(runnable && !netdata_exit)) { - rrdhost_rdlock(&localhost); + rrdhost_rdlock(localhost); - for(rc = localhost.alarms; rc; rc = rc->next) { + for(rc = localhost->alarms; rc; rc = rc->next) { if(unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE))) continue; @@ -3251,7 +3251,7 @@ void *health_main(void *ptr) { rc->delay_last = delay; rc->delay_up_to_timestamp = now + delay; health_alarm_log( - &localhost, + localhost, rc->id, rc->next_event_id++, now, @@ -3282,7 +3282,7 @@ void *health_main(void *ptr) { next_run = rc->next_update; } - rrdhost_unlock(&localhost); + rrdhost_unlock(localhost); } if (unlikely(pthread_setcancelstate(oldstate, NULL) != 0)) @@ -3293,7 +3293,7 @@ void *health_main(void *ptr) { // execute notifications // and cleanup - health_alarm_log_process(&localhost); + health_alarm_log_process(localhost); if(unlikely(netdata_exit)) break; diff --git a/src/ipc.c b/src/ipc.c index b66d6527..0d13d1ef 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -184,8 +184,8 @@ int do_ipc(int update_every, usec_t dt) { return 1; } - arrays_max = rrdvar_custom_host_variable_create(&localhost, "ipc.semaphores.arrays.max"); - semaphores_max = rrdvar_custom_host_variable_create(&localhost, "ipc.semaphores.max"); + arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.arrays.max"); + semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.max"); if(arrays_max) rrdvar_custom_host_variable_set(arrays_max, limits.semmni); if(semaphores_max) rrdvar_custom_host_variable_set(semaphores_max, limits.semmns); diff --git a/src/log.c b/src/log.c index d4c7fa14..02cbca40 100644 --- a/src/log.c +++ b/src/log.c @@ -1,7 +1,7 @@ #include "common.h" const char *program_name = ""; -unsigned long long debug_flags = DEBUG; +uint64_t debug_flags = DEBUG; int access_log_syslog = 1; int error_log_syslog = 1; diff --git a/src/log.h b/src/log.h index e61ffdd0..24b971e2 100644 --- a/src/log.h +++ b/src/log.h @@ -1,38 +1,39 @@ #ifndef NETDATA_LOG_H #define NETDATA_LOG_H 1 -#define D_WEB_BUFFER 0x00000001 -#define D_WEB_CLIENT 0x00000002 -#define D_LISTENER 0x00000004 -#define D_WEB_DATA 0x00000008 -#define D_OPTIONS 0x00000010 -#define D_PROCNETDEV_LOOP 0x00000020 -#define D_RRD_STATS 0x00000040 -#define D_WEB_CLIENT_ACCESS 0x00000080 -#define D_TC_LOOP 0x00000100 -#define D_DEFLATE 0x00000200 -#define D_CONFIG 0x00000400 -#define D_PLUGINSD 0x00000800 -#define D_CHILDS 0x00001000 -#define D_EXIT 0x00002000 -#define D_CHECKS 0x00004000 -#define D_NFACCT_LOOP 0x00008000 -#define D_PROCFILE 0x00010000 -#define D_RRD_CALLS 0x00020000 -#define D_DICTIONARY 0x00040000 -#define D_MEMORY 0x00080000 -#define D_CGROUP 0x00100000 -#define D_REGISTRY 0x00200000 -#define D_VARIABLES 0x00400000 -#define D_HEALTH 0x00800000 -#define D_CONNECT_TO 0x01000000 -#define D_SYSTEM 0x80000000 +#define D_WEB_BUFFER 0x0000000000000001 +#define D_WEB_CLIENT 0x0000000000000002 +#define D_LISTENER 0x0000000000000004 +#define D_WEB_DATA 0x0000000000000008 +#define D_OPTIONS 0x0000000000000010 +#define D_PROCNETDEV_LOOP 0x0000000000000020 +#define D_RRD_STATS 0x0000000000000040 +#define D_WEB_CLIENT_ACCESS 0x0000000000000080 +#define D_TC_LOOP 0x0000000000000100 +#define D_DEFLATE 0x0000000000000200 +#define D_CONFIG 0x0000000000000400 +#define D_PLUGINSD 0x0000000000000800 +#define D_CHILDS 0x0000000000001000 +#define D_EXIT 0x0000000000002000 +#define D_CHECKS 0x0000000000004000 +#define D_NFACCT_LOOP 0x0000000000008000 +#define D_PROCFILE 0x0000000000010000 +#define D_RRD_CALLS 0x0000000000020000 +#define D_DICTIONARY 0x0000000000040000 +#define D_MEMORY 0x0000000000080000 +#define D_CGROUP 0x0000000000100000 +#define D_REGISTRY 0x0000000000200000 +#define D_VARIABLES 0x0000000000400000 +#define D_HEALTH 0x0000000000800000 +#define D_CONNECT_TO 0x0000000001000000 +#define D_RRDHOST 0x0000000002000000 +#define D_SYSTEM 0x8000000000000000 //#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS) //#define DEBUG 0xffffffff #define DEBUG (0) -extern unsigned long long debug_flags; +extern uint64_t debug_flags; extern const char *program_name; diff --git a/src/main.c b/src/main.c index 61e2fa39..28cd5cbd 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ void netdata_cleanup_and_exit(int ret) { //kill_childs(); // free database + sleep(2); rrdhost_free_all(); #endif @@ -578,11 +579,11 @@ int main(int argc, char **argv) { char *user = NULL; { - char *flags = config_get("global", "debug flags", "0x00000000"); + char *flags = config_get("global", "debug flags", "0x0000000000000000"); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); - debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); + debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; @@ -795,14 +796,14 @@ int main(int argc, char **argv) { } // ------------------------------------------------------------------------ - // initialize rrd host + // initialize the registry - rrdhost_init(hostname); + registry_init(); // ------------------------------------------------------------------------ - // initialize the registry + // initialize rrd host - registry_init(); + rrd_init(hostname); // ------------------------------------------------------------------------ // initialize health monitoring diff --git a/src/plugins_d.c b/src/plugins_d.c index c40f221d..b79608ef 100644 --- a/src/plugins_d.c +++ b/src/plugins_d.c @@ -109,7 +109,7 @@ void *pluginsd_worker_thread(void *arg) { #endif size_t count = 0; - RRDHOST *host = &localhost; + RRDHOST *host = localhost; for(;;) { if(unlikely(netdata_exit)) break; diff --git a/src/proc_net_stat_conntrack.c b/src/proc_net_stat_conntrack.c index 3088383b..c5dbaa9f 100644 --- a/src/proc_net_stat_conntrack.c +++ b/src/proc_net_stat_conntrack.c @@ -47,7 +47,7 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { if(!do_sockets && !read_full) return 1; - rrdvar_max = rrdvar_custom_host_variable_create(&localhost, "netfilter.conntrack.max"); + rrdvar_max = rrdvar_custom_host_variable_create(localhost, "netfilter.conntrack.max"); } if(likely(read_full)) { diff --git a/src/registry.c b/src/registry.c index 30202822..58f6ae5f 100644 --- a/src/registry.c +++ b/src/registry.c @@ -45,7 +45,7 @@ static inline void registry_json_header(struct web_client *w, const char *action buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; buffer_sprintf(w->response.data, "{\n\t\"action\": \"%s\",\n\t\"status\": \"%s\",\n\t\"hostname\": \"%s\",\n\t\"machine_guid\": \"%s\"", - action, status, registry.hostname, localhost.machine_guid); + action, status, registry.hostname, localhost->machine_guid); } static inline void registry_json_footer(struct web_client *w) { diff --git a/src/registry.h b/src/registry.h index 4947486c..3f109b11 100644 --- a/src/registry.h +++ b/src/registry.h @@ -69,4 +69,6 @@ extern int registry_request_hello_json(struct web_client *w); // update the registry monitoring charts extern void registry_statistics(void); +extern char *registry_get_this_machine_guid(void); + #endif /* NETDATA_REGISTRY_H */ diff --git a/src/registry_init.c b/src/registry_init.c index a846f861..6d24ea2d 100644 --- a/src/registry_init.c +++ b/src/registry_init.c @@ -15,7 +15,6 @@ int registry_init(void) { // filenames snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname); registry.machine_guid_filename = config_get("registry", "netdata unique id file", filename); - registry_get_this_machine_guid(); snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname); registry.db_filename = config_get("registry", "registry db file", filename); @@ -28,7 +27,7 @@ int registry_init(void) { registry.persons_expiration = config_get_number("registry", "registry expire idle persons days", 365) * 86400; registry.registry_domain = config_get("registry", "registry domain", ""); registry.registry_to_announce = config_get("registry", "registry to announce", "https://registry.my-netdata.io"); - registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", localhost.hostname)); + registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", "localhost")); registry.verify_cookies_redirects = config_get_boolean("registry", "verify browser cookies support", 1); setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1); diff --git a/src/registry_internals.c b/src/registry_internals.c index 04fcf347..df330cc8 100644 --- a/src/registry_internals.c +++ b/src/registry_internals.c @@ -275,8 +275,10 @@ static inline int is_machine_guid_blacklisted(const char *guid) { } char *registry_get_this_machine_guid(void) { - if(likely(localhost.machine_guid[0])) - return localhost.machine_guid; + static char guid[GUID_LEN + 1] = ""; + + if(likely(guid[0])) + return guid; // read it from disk int fd = open(registry.machine_guid_filename, O_RDONLY); @@ -286,38 +288,38 @@ char *registry_get_this_machine_guid(void) { error("Failed to read machine GUID from '%s'", registry.machine_guid_filename); else { buf[GUID_LEN] = '\0'; - if(registry_regenerate_guid(buf, localhost.machine_guid) == -1) { + if(registry_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.", buf, registry.machine_guid_filename); - localhost.machine_guid[0] = '\0'; + guid[0] = '\0'; } - else if(is_machine_guid_blacklisted(localhost.machine_guid)) - localhost.machine_guid[0] = '\0'; + else if(is_machine_guid_blacklisted(guid)) + guid[0] = '\0'; } close(fd); } // generate a new one? - if(!localhost.machine_guid[0]) { + if(!guid[0]) { uuid_t uuid; uuid_generate_time(uuid); - uuid_unparse_lower(uuid, localhost.machine_guid); - localhost.machine_guid[GUID_LEN] = '\0'; + uuid_unparse_lower(uuid, guid); + guid[GUID_LEN] = '\0'; // save it fd = open(registry.machine_guid_filename, O_WRONLY|O_CREAT|O_TRUNC, 444); if(fd == -1) fatal("Cannot create unique machine id file '%s'. Please fix this.", registry.machine_guid_filename); - if(write(fd, localhost.machine_guid, GUID_LEN) != GUID_LEN) + if(write(fd, guid, GUID_LEN) != GUID_LEN) fatal("Cannot write the unique machine id file '%s'. Please fix this.", registry.machine_guid_filename); close(fd); } - setenv("NETDATA_REGISTRY_UNIQUE_ID", localhost.machine_guid, 1); + setenv("NETDATA_REGISTRY_UNIQUE_ID", guid, 1); - return localhost.machine_guid; + return guid; } diff --git a/src/registry_internals.h b/src/registry_internals.h index 42c36620..8aef16b2 100644 --- a/src/registry_internals.h +++ b/src/registry_internals.h @@ -68,8 +68,6 @@ extern int registry_regenerate_guid(const char *guid, char *result); extern struct registry registry; -extern char *registry_get_this_machine_guid(void); - // REGISTRY LOW-LEVEL REQUESTS (in registry-internals.c) extern REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when); extern REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); diff --git a/src/rrd.h b/src/rrd.h index d09fe628..ceae9963 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -120,7 +120,7 @@ struct rrddim { // (the user overwrites the name of the charts) // DO NOT FREE THIS - IT IS ALLOCATED IN CONFIG - RRD_ALGORITHM algorithm; // the algorithm that is applied to add new collected values + RRD_ALGORITHM algorithm; // the algorithm that is applied to add new collected values RRD_MEMORY_MODE memory_mode; // the memory mode for this dimension collected_number multiplier; // the multiplier of the collected values @@ -297,7 +297,10 @@ struct rrdhost { avl avl; char *hostname; + uint32_t hash_hostname; + char machine_guid[GUID_LEN + 1]; + uint32_t hash_machine_guid; RRDSET *rrdset_root; pthread_rwlock_t rrdset_root_rwlock; @@ -326,8 +329,12 @@ struct rrdhost { struct rrdhost *next; }; typedef struct rrdhost RRDHOST; -extern RRDHOST localhost; -extern void rrdhost_init(char *hostname); + +extern RRDHOST *localhost; + +extern void rrd_init(char *hostname); + +extern RRDHOST *rrdhost_find(const char *guid, uint32_t hash); #ifdef NETDATA_INTERNAL_CHECKS #define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__) @@ -345,7 +352,7 @@ extern void rrdhost_rdlock(RRDHOST *host); extern void rrdhost_unlock(RRDHOST *host); // ---------------------------------------------------------------------------- -// RRD SET functions +// RRDSET functions extern void rrdset_set_name(RRDSET *st, const char *name); @@ -367,13 +374,13 @@ extern void rrdhost_free(RRDHOST *host); extern void rrdhost_save(RRDHOST *host); extern RRDSET *rrdset_find(RRDHOST *host, const char *id); -#define rrdset_find_localhost(id) rrdset_find(&localhost, id) +#define rrdset_find_localhost(id) rrdset_find(localhost, id) extern RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id); -#define rrdset_find_bytype_localhost(type, id) rrdset_find_bytype(&localhost, type, id) +#define rrdset_find_bytype_localhost(type, id) rrdset_find_bytype(localhost, type, id) extern RRDSET *rrdset_find_byname(RRDHOST *host, const char *name); -#define rrdset_find_byname_localhost(name) rrdset_find_byname(&localhost, name) +#define rrdset_find_byname_localhost(name) rrdset_find_byname(localhost, name) extern void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds); extern void rrdset_next_usec(RRDSET *st, usec_t microseconds); @@ -434,6 +441,8 @@ extern collected_number rrddim_set(RRDSET *st, const char *id, collected_number #ifdef NETDATA_RRD_INTERNALS +extern avl_tree_lock rrdhost_root_index; + extern char *rrdset_strncpyz_name(char *to, const char *from, size_t length); extern char *rrdset_cache_dir(const char *id); diff --git a/src/rrd2json.c b/src/rrd2json.c index 21b013d0..b06fb4ae 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -90,15 +90,15 @@ void rrd_stats_api_v1_charts(BUFFER *wb) ",\n\t\"update_every\": %d" ",\n\t\"history\": %d" ",\n\t\"charts\": {" - , localhost.hostname + , localhost->hostname , program_version , os_type , rrd_update_every , rrd_default_history_entries ); - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); - for(st = localhost.rrdset_root, c = 0; st ; st = st->next) { + pthread_rwlock_rdlock(&localhost->rrdset_root_rwlock); + for(st = localhost->rrdset_root, c = 0; st ; st = st->next) { if(st->enabled && st->dimensions) { if(c) buffer_strcat(wb, ","); buffer_strcat(wb, "\n\t\t\""); @@ -110,11 +110,11 @@ void rrd_stats_api_v1_charts(BUFFER *wb) } RRDCALC *rc; - for(rc = localhost.alarms; rc ; rc = rc->next) { + for(rc = localhost->alarms; rc ; rc = rc->next) { if(rc->rrdset) alarms++; } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + pthread_rwlock_unlock(&localhost->rrdset_root_rwlock); buffer_sprintf(wb, "\n\t}" ",\n\t\"charts_count\": %zu" @@ -151,14 +151,14 @@ static inline size_t prometheus_name_copy(char *d, const char *s, size_t usable) void rrd_stats_api_v1_charts_allmetrics_prometheus(BUFFER *wb) { - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); + pthread_rwlock_rdlock(&localhost->rrdset_root_rwlock); char host[PROMETHEUS_ELEMENT_MAX + 1]; prometheus_name_copy(host, config_get("global", "hostname", "localhost"), PROMETHEUS_ELEMENT_MAX); // for each chart RRDSET *st; - for(st = localhost.rrdset_root; st ; st = st->next) { + for(st = localhost->rrdset_root; st ; st = st->next) { char chart[PROMETHEUS_ELEMENT_MAX + 1]; prometheus_name_copy(chart, st->id, PROMETHEUS_ELEMENT_MAX); @@ -201,7 +201,7 @@ void rrd_stats_api_v1_charts_allmetrics_prometheus(BUFFER *wb) } } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + pthread_rwlock_unlock(&localhost->rrdset_root_rwlock); } // ---------------------------------------------------------------------------- @@ -226,14 +226,14 @@ static inline size_t shell_name_copy(char *d, const char *s, size_t usable) { void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) { - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); + pthread_rwlock_rdlock(&localhost->rrdset_root_rwlock); char host[SHELL_ELEMENT_MAX + 1]; shell_name_copy(host, config_get("global", "hostname", "localhost"), SHELL_ELEMENT_MAX); // for each chart RRDSET *st; - for(st = localhost.rrdset_root; st ; st = st->next) { + for(st = localhost->rrdset_root; st ; st = st->next) { calculated_number total = 0.0; char chart[SHELL_ELEMENT_MAX + 1]; shell_name_copy(chart, st->id, SHELL_ELEMENT_MAX); @@ -271,7 +271,7 @@ void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) buffer_strcat(wb, "\n# NETDATA ALARMS RUNNING\n"); RRDCALC *rc; - for(rc = localhost.alarms; rc ;rc = rc->next) { + for(rc = localhost->alarms; rc ;rc = rc->next) { if(!rc->rrdset) continue; char chart[SHELL_ELEMENT_MAX + 1]; @@ -292,7 +292,7 @@ void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status)); } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + pthread_rwlock_unlock(&localhost->rrdset_root_rwlock); } // ---------------------------------------------------------------------------- @@ -421,15 +421,15 @@ void rrd_stats_all_json(BUFFER *wb) buffer_strcat(wb, RRD_GRAPH_JSON_HEADER); - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); - for(st = localhost.rrdset_root, c = 0; st ; st = st->next) { + pthread_rwlock_rdlock(&localhost->rrdset_root_rwlock); + for(st = localhost->rrdset_root, c = 0; st ; st = st->next) { if(st->enabled && st->dimensions) { if(c) buffer_strcat(wb, ",\n"); memory += rrd_stats_one_json(st, NULL, wb); c++; } } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + pthread_rwlock_unlock(&localhost->rrdset_root_rwlock); buffer_sprintf(wb, "\n\t],\n" "\t\"hostname\": \"%s\",\n" @@ -437,7 +437,7 @@ void rrd_stats_all_json(BUFFER *wb) "\t\"history\": %d,\n" "\t\"memory\": %lu\n" "}\n" - , localhost.hostname + , localhost->hostname , rrd_update_every , rrd_default_history_entries , memory diff --git a/src/rrdhost.c b/src/rrdhost.c index 6ec171b1..64a96c59 100644 --- a/src/rrdhost.c +++ b/src/rrdhost.c @@ -2,46 +2,88 @@ #include "common.h" // ---------------------------------------------------------------------------- -// RRDHOST - -RRDHOST localhost = { - .hostname = "localhost", - .machine_guid = "", - .rrdset_root = NULL, - .rrdset_root_rwlock = PTHREAD_RWLOCK_INITIALIZER, - .rrdset_root_index = { - { NULL, rrdset_compare }, - AVL_LOCK_INITIALIZER - }, - .rrdset_root_index_name = { - { NULL, rrdset_compare_name }, - AVL_LOCK_INITIALIZER - }, - .rrdfamily_root_index = { - { NULL, rrdfamily_compare }, - AVL_LOCK_INITIALIZER - }, - .variables_root_index = { - { NULL, rrdvar_compare }, - AVL_LOCK_INITIALIZER - }, - .health_log = { - .next_log_id = 1, - .next_alarm_id = 1, - .count = 0, - .max = 1000, - .alarms = NULL, - .alarm_log_rwlock = PTHREAD_RWLOCK_INITIALIZER - }, - .next = NULL +// RRDHOST index + +int rrdhost_compare(void* a, void* b) { + if(((RRDHOST *)a)->hash_machine_guid < ((RRDHOST *)b)->hash_machine_guid) return -1; + else if(((RRDHOST *)a)->hash_machine_guid > ((RRDHOST *)b)->hash_machine_guid) return 1; + else return strcmp(((RRDHOST *)a)->machine_guid, ((RRDHOST *)b)->machine_guid); +} + +avl_tree_lock rrdhost_root_index = { + .avl_tree = { NULL, rrdhost_compare }, + .rwlock = AVL_LOCK_INITIALIZER }; -void rrdhost_init(char *hostname) { - localhost.hostname = hostname; - localhost.health_log.next_log_id = - localhost.health_log.next_alarm_id = (uint32_t)now_realtime_sec(); +RRDHOST *rrdhost_find(const char *guid, uint32_t hash) { + RRDHOST tmp; + strncpyz(tmp.machine_guid, guid, GUID_LEN); + tmp.hash_machine_guid = (hash)?hash:simple_hash(tmp.machine_guid); + + return (RRDHOST *)avl_search_lock(&(rrdhost_root_index), (avl *) &tmp); } +#define rrdhost_index_add(rrdhost) (RRDHOST *)avl_insert_lock(&(rrdhost_root_index), (avl *)(rrdhost)) +#define rrdhost_index_del(rrdhost) (RRDHOST *)avl_remove_lock(&(rrdhost_root_index), (avl *)(rrdhost)) + + +// ---------------------------------------------------------------------------- +// RRDHOST - internal helpers + +static inline void rrdhost_init_hostname(RRDHOST *host, const char *hostname) { + freez(host->hostname); + host->hostname = strdupz(hostname); + host->hash_hostname = simple_hash(host->hostname); +} + +static inline void rrdhost_init_machine_guid(RRDHOST *host, const char *machine_guid) { + strncpy(host->machine_guid, machine_guid, GUID_LEN); + host->machine_guid[GUID_LEN] = '\0'; + host->hash_machine_guid = simple_hash(host->machine_guid); +} + +// ---------------------------------------------------------------------------- +// RRDHOST - add a host + +RRDHOST *rrdhost_create(const char *hostname, const char *guid) { + RRDHOST *host = callocz(1, sizeof(RRDHOST)); + + pthread_rwlock_init(&(host->rrdset_root_rwlock), NULL); + + rrdhost_init_hostname(host, hostname); + rrdhost_init_machine_guid(host, guid); + + avl_init_lock(&(host->rrdset_root_index), rrdset_compare); + avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name); + avl_init_lock(&(host->rrdfamily_root_index), rrdfamily_compare); + avl_init_lock(&(host->variables_root_index), rrdvar_compare); + + host->health_log.next_log_id = 1; + host->health_log.next_alarm_id = 1; + host->health_log.max = 1000; + host->health_log.next_log_id = + host->health_log.next_alarm_id = (uint32_t)now_realtime_sec(); + pthread_rwlock_init(&(host->health_log.alarm_log_rwlock), NULL); + + if(rrdhost_index_add(host) != host) + fatal("Cannot add host '%s' to index. It already exists.", hostname); + + debug(D_RRDHOST, "Added host '%s'", host->hostname); + return host; +} + +// ---------------------------------------------------------------------------- +// RRDHOST global / startup initialization + +RRDHOST *localhost = NULL; + +void rrd_init(char *hostname) { + localhost = rrdhost_create(hostname, registry_get_this_machine_guid()); +} + +// ---------------------------------------------------------------------------- +// RRDHOST - locks + void rrdhost_rwlock(RRDHOST *host) { pthread_rwlock_wrlock(&host->rrdset_root_rwlock); } @@ -69,7 +111,9 @@ void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *funct } void rrdhost_free(RRDHOST *host) { - info("Freeing all memory..."); + if(!host) return; + + info("Freeing all memory for host '%s'...", host->hostname); rrdhost_rwlock(host); @@ -110,13 +154,17 @@ void rrdhost_free(RRDHOST *host) { } host->rrdset_root = NULL; + freez(host->hostname); rrdhost_unlock(host); + freez(host); - info("Memory cleanup completed..."); + info("Host memory cleanup completed..."); } void rrdhost_save(RRDHOST *host) { - info("Saving database..."); + if(!host) return; + + info("Saving host '%s' database...", host->hostname); RRDSET *st; RRDDIM *rd; @@ -147,21 +195,23 @@ void rrdhost_save(RRDHOST *host) { } void rrdhost_free_all(void) { - RRDHOST *host; + RRDHOST *host = localhost; // FIXME: lock all hosts - for(host = &localhost; host ;) { + while(host) { RRDHOST *next = host = host->next; rrdhost_free(host); host = next; } + localhost = NULL; + // FIXME: unlock all hosts } void rrdhost_save_all(void) { RRDHOST *host; - for(host = &localhost; host ; host = host->next) + for(host = localhost; host ; host = host->next) rrdhost_save(host); } diff --git a/src/rrdset.c b/src/rrdset.c index 60fc19af..4c07c121 100644 --- a/src/rrdset.c +++ b/src/rrdset.c @@ -210,7 +210,7 @@ static inline void timeval_align(struct timeval *tv, int update_every) { // RRDSET - create a chart RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type) { - RRDHOST *host = &localhost; + RRDHOST *host = localhost; if(!type || !type[0]) { fatal("Cannot create rrd stats without a type."); diff --git a/src/web_client.c b/src/web_client.c index 5b0ab6f9..e38d70b9 100644 --- a/src/web_client.c +++ b/src/web_client.c @@ -683,7 +683,7 @@ int web_client_api_request_v1_alarms(struct web_client *w, char *url) buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; - health_alarms2json(&localhost, w->response.data, all); + health_alarms2json(localhost, w->response.data, all); return 200; } @@ -704,7 +704,7 @@ int web_client_api_request_v1_alarm_log(struct web_client *w, char *url) buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; - health_alarm_log2json(&localhost, w->response.data, after); + health_alarm_log2json(localhost, w->response.data, after); return 200; } @@ -2202,7 +2202,7 @@ void web_client_process(struct web_client *w) { debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id); buffer_flush(w->response.data); - RRDSET *st = localhost.rrdset_root; + RRDSET *st = localhost->rrdset_root; for ( ; st ; st = st->next ) buffer_sprintf(w->response.data, "%s\n", st->name);