for(st = host->rrdset_root; st; st = st->next) {
// for each chart
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
RRDDIM *rd;
for(rd = st->dimensions; rd; rd = rd->next) {
chart_buffered_metrics += backend_request_formatter(b, prefix, host, (host == localhost)?hostname:host->hostname, st, rd, after, before, options);
}
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
}
rrdhost_unlock(host);
char *path = health_config_dir();
// free all running alarms
- rrdhost_rwlock(host);
+ rrdhost_wrlock(host);
health_free_host_nolock(host);
rrdhost_unlock(host);
}
// load the new alarms
- rrdhost_rwlock(host);
+ rrdhost_wrlock(host);
health_readdir(host, path);
rrdhost_unlock(host);
// link the loaded alarms to their charts
for(st = host->rrdset_root; st ; st = st->next) {
- rrdhost_rwlock(host);
+ rrdhost_wrlock(host);
rrdsetcalc_link_matching(st);
rrdcalctemplate_link_matching(st);
char *cache_dir; // the directory to store dimensions
char cache_filename[FILENAME_MAX+1]; // the filename to store this set
- pthread_rwlock_t rwlock;
+ pthread_rwlock_t rrdset_rwlock;
unsigned long counter; // the number of times we added values to this rrd
unsigned long counter_done; // the number of times we added values to this rrd
};
typedef struct rrdset RRDSET;
+#define rrdset_rdlock(st) pthread_rwlock_rdlock(&((st)->rrdset_rwlock))
+#define rrdset_wrlock(st) pthread_rwlock_wrlock(&((st)->rrdset_rwlock))
+#define rrdset_unlock(st) pthread_rwlock_unlock(&((st)->rrdset_rwlock))
+
// ----------------------------------------------------------------------------
// RRD HOST
RRD_MEMORY_MODE rrd_memory_mode; // the memory more for the charts of this host
RRDSET *rrdset_root; // the host charts
- pthread_rwlock_t rrdset_root_rwlock; // lock for the host charts
+
+ pthread_rwlock_t rrdhost_rwlock; // lock for this RRDHOST
avl_tree_lock rrdset_root_index; // the host's charts index (by id)
avl_tree_lock rrdset_root_index_name; // the host's charts index (by name)
struct rrdhost *next;
};
typedef struct rrdhost RRDHOST;
-
extern RRDHOST *localhost;
+#define rrdhost_rdlock(h) pthread_rwlock_rdlock(&((h)->rrdhost_rwlock))
+#define rrdhost_wrlock(h) pthread_rwlock_wrlock(&((h)->rrdhost_rwlock))
+#define rrdhost_unlock(h) pthread_rwlock_unlock(&((h)->rrdhost_rwlock))
+
extern void rrd_init(char *hostname);
extern RRDHOST *rrdhost_find(const char *guid, uint32_t hash);
extern RRDHOST *rrdhost_find_or_create(const char *hostname, const char *guid);
#ifdef NETDATA_INTERNAL_CHECKS
-#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__)
#define rrdhost_check_rdlock(host) rrdhost_check_rdlock_int(host, __FILE__, __FUNCTION__, __LINE__)
+#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__)
#else
#define rrdhost_check_rdlock(host) (void)0
#define rrdhost_check_wrlock(host) (void)0
extern void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line);
extern void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line);
-extern void rrdhost_rwlock(RRDHOST *host);
-extern void rrdhost_rdlock(RRDHOST *host);
-extern void rrdhost_unlock(RRDHOST *host);
-
// ----------------------------------------------------------------------------
// RRDSET functions
void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used)
{
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
buffer_sprintf(wb,
"\t\t{\n"
"\n\t\t}"
);
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
}
void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) {
, host->rrd_history_entries
);
- pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
+ rrdhost_rdlock(host);
for(st = host->rrdset_root, c = 0; st ; st = st->next) {
if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) {
if(c) buffer_strcat(wb, ",");
if(rc->rrdset)
alarms++;
}
- pthread_rwlock_unlock(&host->rrdset_root_rwlock);
+ rrdhost_unlock(host);
buffer_sprintf(wb, "\n\t}"
",\n\t\"charts_count\": %zu"
#define PROMETHEUS_ELEMENT_MAX 256
void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb) {
- pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
+ rrdhost_rdlock(host);
char hostname[PROMETHEUS_ELEMENT_MAX + 1];
prometheus_name_copy(hostname, config_get("global", "hostname", "localhost"), PROMETHEUS_ELEMENT_MAX);
buffer_strcat(wb, "\n");
if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) {
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
// for each dimension
RRDDIM *rd;
}
}
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
}
}
- pthread_rwlock_unlock(&host->rrdset_root_rwlock);
+ rrdhost_unlock(host);
}
// ----------------------------------------------------------------------------
#define SHELL_ELEMENT_MAX 100
void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) {
- pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
+ rrdhost_rdlock(host);
// for each chart
RRDSET *st;
buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name);
if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) {
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
// for each dimension
RRDDIM *rd;
total = roundl(total);
buffer_sprintf(wb, "NETDATA_%s_VISIBLETOTAL=\"%0.0Lf\" # %s\n", chart, total, st->units);
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
}
}
buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status));
}
- pthread_rwlock_unlock(&host->rrdset_root_rwlock);
+ rrdhost_unlock(host);
}
// ----------------------------------------------------------------------------
{
time_t now = now_realtime_sec();
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
buffer_sprintf(wb,
"\t\t{\n"
, memory
);
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
return memory;
}
buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
- pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
+ rrdhost_rdlock(host);
+
for(st = host->rrdset_root, c = 0; st ; st = st->next) {
if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) {
if(c) buffer_strcat(wb, ",\n");
c++;
}
}
- pthread_rwlock_unlock(&host->rrdset_root_rwlock);
buffer_sprintf(wb, "\n\t],\n"
"\t\"hostname\": \"%s\",\n"
, host->rrd_history_entries
, memory
);
+
+ rrdhost_unlock(host);
}
return;
}
- pthread_rwlock_rdlock(&r->st->rwlock);
+ rrdset_rdlock(r->st);
r->has_st_lock = 1;
}
}
if(likely(r->has_st_lock)) {
- pthread_rwlock_unlock(&r->st->rwlock);
+ rrdset_unlock(r->st);
r->has_st_lock = 0;
}
}
time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, int group_method, time_t after, time_t before, int only_non_zero)
{
int c;
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
// -------------------------------------------------------------------------
RRDDIM *rd;
for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
if(!dimensions) {
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
buffer_strcat(wb, "No dimensions yet.");
return 0;
}
debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %zu bytes", st->name, wb->len);
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
return last_timestamp;
}
rd->rrdset = st;
// append this dimension
- pthread_rwlock_wrlock(&st->rwlock);
+ rrdset_wrlock(st);
if(!st->dimensions)
st->dimensions = rd;
else {
rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, 0);
}
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
if(unlikely(rrddim_index_add(st, rd) != rd))
error("RRDDIM: INTERNAL ERROR: attempt to index duplicate dimension '%s' on chart '%s'", rd->id, st->id);
host->rrd_memory_mode = memory_mode;
host->health_enabled = health_enabled;
- pthread_rwlock_init(&(host->rrdset_root_rwlock), NULL);
+ pthread_rwlock_init(&(host->rrdhost_rwlock), NULL);
rrdhost_init_hostname(host, hostname);
rrdhost_init_machine_guid(host, guid);
health_alarm_log_load(host);
health_alarm_log_open(host);
- rrdhost_rwlock(host);
+ rrdhost_wrlock(host);
health_readdir(host, health_config_dir());
rrdhost_unlock(host);
}
// ----------------------------------------------------------------------------
-// RRDHOST - locks
-
-void rrdhost_rwlock(RRDHOST *host) {
- debug(D_RRDHOST, "Write lock host '%s'", host->hostname);
- pthread_rwlock_wrlock(&host->rrdset_root_rwlock);
-}
-
-void rrdhost_rdlock(RRDHOST *host) {
- debug(D_RRDHOST, "Read lock host '%s'", host->hostname);
- pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
-}
-
-void rrdhost_unlock(RRDHOST *host) {
- debug(D_RRDHOST, "Unlock host '%s'", host->hostname);
- pthread_rwlock_unlock(&host->rrdset_root_rwlock);
-}
+// RRDHOST - lock validations
+// there are only used when NETDATA_INTERNAL_CHECKS is set
void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
- debug(D_RRDHOST, "Read lock host '%s'", host->hostname);
+ debug(D_RRDHOST, "Checking read lock on host '%s'", host->hostname);
- int ret = pthread_rwlock_trywrlock(&host->rrdset_root_rwlock);
+ int ret = pthread_rwlock_trywrlock(&host->rrdhost_rwlock);
if(ret == 0)
fatal("RRDHOST '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
}
void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
- debug(D_RRDHOST, "Write lock host '%s'", host->hostname);
+ debug(D_RRDHOST, "Checking write lock on host '%s'", host->hostname);
- int ret = pthread_rwlock_tryrdlock(&host->rrdset_root_rwlock);
+ int ret = pthread_rwlock_tryrdlock(&host->rrdhost_rwlock);
if(ret == 0)
fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
}
+// ----------------------------------------------------------------------------
+// RRDHOST - free
+
void rrdhost_free(RRDHOST *host) {
if(!host) return;
info("Freeing all memory for host '%s'...", host->hostname);
- rrdhost_rwlock(host);
+ rrdhost_wrlock(host);
RRDSET *st;
for(st = host->rrdset_root; st ;) {
info("Host memory cleanup completed...");
}
+void rrdhost_free_all(void) {
+ RRDHOST *host = localhost;
+
+ // FIXME: lock all hosts
+
+ while(host) {
+ RRDHOST *next = host = host->next;
+ rrdhost_free(host);
+ host = next;
+ }
+
+ localhost = NULL;
+
+ // FIXME: unlock all hosts
+}
+
+// ----------------------------------------------------------------------------
+// RRDHOST - save
+
void rrdhost_save(RRDHOST *host) {
if(!host) return;
// we get a write lock
// to ensure only one thread is saving the database
- rrdhost_rwlock(host);
+ rrdhost_wrlock(host);
for(st = host->rrdset_root; st ; st = st->next) {
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
}
}
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
}
rrdhost_unlock(host);
}
-void rrdhost_free_all(void) {
- RRDHOST *host = localhost;
-
- // FIXME: lock all hosts
-
- while(host) {
- RRDHOST *next = host = host->next;
- rrdhost_free(host);
- host = next;
- }
-
- localhost = NULL;
-
- // FIXME: unlock all hosts
-}
-
void rrdhost_save_all(void) {
info("Saving database...");
return(st);
}
-
// ----------------------------------------------------------------------------
// RRDSET - rename charts
st->hash_name = simple_hash(st->name);
}
- pthread_rwlock_wrlock(&st->rwlock);
+ rrdset_wrlock(st);
RRDDIM *rd;
for(rd = st->dimensions; rd ;rd = rd->next)
rrddimvar_rename_all(rd);
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
if(unlikely(rrdset_index_add_name(st->rrdhost, st) != st))
error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name);
// RRDSET - free a chart
void rrdset_free(RRDSET *st) {
- pthread_rwlock_wrlock(&st->rwlock);
+ rrdset_wrlock(st);
while(st->variables) rrdsetvar_free(st->variables);
while(st->alarms) rrdsetcalc_unlink(st->alarms);
if(!st->rrdfamily->use_count)
rrdfamily_free(st->rrdhost, st->rrdfamily);
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
// free directly allocated memory
freez(st->config_section);
memset(&st->avlname, 0, sizeof(avl));
memset(&st->variables_root_index, 0, sizeof(avl_tree_lock));
memset(&st->dimensions_index, 0, sizeof(avl_tree_lock));
- memset(&st->rwlock, 0, sizeof(pthread_rwlock_t));
+ memset(&st->rrdset_rwlock, 0, sizeof(pthread_rwlock_t));
st->name = NULL;
st->type = NULL;
avl_init_lock(&st->dimensions_index, rrddim_compare);
avl_init_lock(&st->variables_root_index, rrdvar_compare);
- pthread_rwlock_init(&st->rwlock, NULL);
- rrdhost_rwlock(host);
+ pthread_rwlock_init(&st->rrdset_rwlock, NULL);
+ rrdhost_wrlock(host);
if(name && *name) rrdset_set_name(st, name);
else rrdset_set_name(st, id);
error("Cannot set pthread cancel state to DISABLE.");
// a read lock is OK here
- pthread_rwlock_rdlock(&st->rwlock);
+ rrdset_rdlock(st);
/*
// enable the chart, if it was disabled
RRDDIM *last;
// there is dimension to free
// upgrade our read lock to a write lock
- pthread_rwlock_unlock(&st->rwlock);
- pthread_rwlock_wrlock(&st->rwlock);
+ pthread_rwlock_unlock(&st->rrdset_rwlock);
+ pthread_rwlock_wrlock(&st->rrdset_rwlock);
for( rd = st->dimensions, last = NULL ; likely(rd) ; ) {
// remove it only it is not updated in rrd_delete_unupdated_dimensions seconds
}
*/
- pthread_rwlock_unlock(&st->rwlock);
+ rrdset_unlock(st);
if(unlikely(pthread_setcancelstate(pthreadoldcancelstate, NULL) != 0))
error("Cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate);