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 \
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);
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);
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",
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;
}
}
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);
}
}
- 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;
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();
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);
}
// ----------------------------------------------------------------------------
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,"
// health_rrdcalctemplate2json_nolock(wb, rt);
buffer_strcat(wb, "\n\t}\n}\n");
- rrdhost_unlock(&localhost);
+ rrdhost_unlock(localhost);
}
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);
}
}
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;
}
}
}
- 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;
rc->delay_last = delay;
rc->delay_up_to_timestamp = now + delay;
health_alarm_log(
- &localhost,
+ localhost,
rc->id,
rc->next_event_id++,
now,
next_run = rc->next_update;
}
- rrdhost_unlock(&localhost);
+ rrdhost_unlock(localhost);
}
if (unlikely(pthread_setcancelstate(oldstate, NULL) != 0))
// execute notifications
// and cleanup
- health_alarm_log_process(&localhost);
+ health_alarm_log_process(localhost);
if(unlikely(netdata_exit))
break;
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);
#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;
#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;
//kill_childs();
// free database
+ sleep(2);
rrdhost_free_all();
#endif
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 };
}
// ------------------------------------------------------------------------
- // 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
#endif
size_t count = 0;
- RRDHOST *host = &localhost;
+ RRDHOST *host = localhost;
for(;;) {
if(unlikely(netdata_exit)) break;
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)) {
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) {
// update the registry monitoring charts
extern void registry_statistics(void);
+extern char *registry_get_this_machine_guid(void);
+
#endif /* NETDATA_REGISTRY_H */
// 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);
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);
}
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);
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;
}
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);
// (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
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;
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__)
extern void rrdhost_unlock(RRDHOST *host);
// ----------------------------------------------------------------------------
-// RRD SET functions
+// RRDSET functions
extern void rrdset_set_name(RRDSET *st, const char *name);
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);
#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);
",\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\"");
}
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"
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);
}
}
- pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
+ pthread_rwlock_unlock(&localhost->rrdset_root_rwlock);
}
// ----------------------------------------------------------------------------
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);
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];
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);
}
// ----------------------------------------------------------------------------
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"
"\t\"history\": %d,\n"
"\t\"memory\": %lu\n"
"}\n"
- , localhost.hostname
+ , localhost->hostname
, rrd_update_every
, rrd_default_history_entries
, memory
#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);
}
}
void rrdhost_free(RRDHOST *host) {
- info("Freeing all memory...");
+ if(!host) return;
+
+ info("Freeing all memory for host '%s'...", host->hostname);
rrdhost_rwlock(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;
}
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);
}
// 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.");
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;
}
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;
}
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);