long double holtwinters(const long double *series, size_t entries, long double alpha, long double beta, long double gamma, long double *forecast) { if(unlikely(isnan(alpha))) alpha = 0.3; if(unlikely(isnan(beta))) beta = 0.05; if(unlikely(isnan(gamma))) gamma = 0; int seasonal = 0; int period = 0; long double a0 = series[0]; long double b0 = 0; long double s[] = {}; long double errors = 0.0; size_t nb_computations = entries; long double *estimated_level = callocz(nb_computations, sizeof(long double)); long double *estimated_trend = callocz(nb_computations, sizeof(long double)); long double *estimated_season = callocz(nb_computations, sizeof(long double)); int ret = __HoltWinters( series, (int)entries, alpha, beta, gamma, &seasonal, &period, &a0, &b0, s, &errors, estimated_level, estimated_trend, estimated_season ); long double value = estimated_level[nb_computations - 1]; if(forecast) *forecast = 0.0; freez(estimated_level); freez(estimated_trend); freez(estimated_season); if(!ret) return 0.0; return value; }
static NAME_VALUE *dictionary_name_value_create_nolock(DICTIONARY *dict, const char *name, void *value, size_t value_len, uint32_t hash) { debug(D_DICTIONARY, "Creating name value entry for name '%s'.", name); NAME_VALUE *nv = callocz(1, sizeof(NAME_VALUE)); if(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE) nv->name = (char *)name; else { nv->name = strdupz(name); } nv->hash = (hash)?hash:simple_hash(nv->name); if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE) nv->value = value; else { nv->value = mallocz(value_len); memcpy(nv->value, value, value_len); } // index it dictionary_name_value_index_add_nolock(dict, nv); NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict); return nv; }
static struct web_client *web_client_alloc(void) { struct web_client *w = callocz(1, sizeof(struct web_client)); w->response.data = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE); w->response.header = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE); w->response.header_output = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE); return w; }
static inline struct tc_class *tc_class_add(struct tc_device *n, char *id, char qdisc, char *parentid, char *leafid) { struct tc_class *c = tc_class_index_find(n, id, 0); if(!c) { debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", n->id, id, parentid?parentid:"", leafid?leafid:""); c = callocz(1, sizeof(struct tc_class)); if(n->classes) n->classes->prev = c; c->next = n->classes; n->classes = c; c->id = strdupz(id); c->hash = simple_hash(c->id); c->isqdisc = qdisc; if(parentid && *parentid) { c->parentid = strdupz(parentid); c->parent_hash = simple_hash(c->parentid); } if(leafid && *leafid) { c->leafid = strdupz(leafid); c->leaf_hash = simple_hash(c->leafid); } if(unlikely(tc_class_index_add(n, c) != c)) error("plugin_tc: INTERNAL ERROR: attempt index class '%s' on device '%s': already exists", c->id, n->id); } return(c); }
static inline struct tc_device *tc_device_create(char *id) { struct tc_device *d = tc_device_index_find(id, 0); if(!d) { debug(D_TC_LOOP, "TC: Creating device '%s'", id); d = callocz(1, sizeof(struct tc_device)); d->id = strdupz(id); d->hash = simple_hash(d->id); d->enabled = (char)-1; avl_init(&d->classes_index, tc_class_compare); if(unlikely(tc_device_index_add(d) != d)) error("plugin_tc: INTERNAL ERROR: removing device '%s' removed a different device.", d->id); if(!tc_device_root) { tc_device_root = d; } else { d->next = tc_device_root; tc_device_root->prev = d; tc_device_root = d; } } return(d); }
DICTIONARY *dictionary_create(uint8_t flags) { debug(D_DICTIONARY, "Creating dictionary."); DICTIONARY *dict = callocz(1, sizeof(DICTIONARY)); if(flags & DICTIONARY_FLAG_WITH_STATISTICS) dict->stats = callocz(1, sizeof(struct dictionary_stats)); if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) { dict->rwlock = callocz(1, sizeof(pthread_rwlock_t)); pthread_rwlock_init(dict->rwlock, NULL); } avl_init(&dict->values_index, name_value_compare); dict->flags = flags; return dict; }
void *grouping_init_median(RRDR *r) { long entries = (r->group > r->group_points) ? r->group : r->group_points; if(entries < 0) entries = 0; struct grouping_median *g = (struct grouping_median *)callocz(1, sizeof(struct grouping_median) + entries * sizeof(LONG_DOUBLE)); g->series_size = (size_t)entries; return g; }
static inline struct simple_pattern *parse_pattern(char *str, SIMPLE_PREFIX_MODE default_mode) { // fprintf(stderr, "PARSING PATTERN: '%s'\n", str); SIMPLE_PREFIX_MODE mode; struct simple_pattern *child = NULL; char *s = str, *c = str; // skip asterisks in front while(*c == '*') c++; // find the next asterisk while(*c && *c != '*') c++; // do we have an asterisk in the middle? if(*c == '*' && c[1] != '\0') { // yes, we have child = parse_pattern(c, default_mode); c[1] = '\0'; } // check what this one matches size_t len = strlen(s); if(len >= 2 && *s == '*' && s[len - 1] == '*') { s[len - 1] = '\0'; s++; mode = SIMPLE_PATTERN_SUBSTRING; } else if(len >= 1 && *s == '*') { s++; mode = SIMPLE_PATTERN_SUFFIX; } else if(len >= 1 && s[len - 1] == '*') { s[len - 1] = '\0'; mode = SIMPLE_PATTERN_PREFIX; } else mode = default_mode; // allocate the structure struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern)); if(*s) { m->match = strdupz(s); m->len = strlen(m->match); m->mode = mode; } else { m->mode = SIMPLE_PATTERN_SUBSTRING; } m->child = child; return m; }
BUFFER *buffer_create(size_t size) { BUFFER *b; debug(D_WEB_BUFFER, "Creating new web buffer of size %zu.", size); b = callocz(1, sizeof(BUFFER)); b->buffer = mallocz(size + sizeof(BUFFER_OVERFLOW_EOF) + 2); b->buffer[0] = '\0'; b->size = size; b->contenttype = CT_TEXT_PLAIN; buffer_overflow_init(b); buffer_overflow_check(b); return(b); }
RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options) { debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable); RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR)); rs->variable = strdupz(variable); rs->hash = simple_hash(rs->variable); rs->type = type; rs->value = value; rs->options = options; rs->rrdset = st; rs->next = st->variables; st->variables = rs; rrdsetvar_create_variables(rs); return rs; }
size_t netdata_threads_init(void) { int i; // -------------------------------------------------------------------- // get the required stack size of the threads of netdata attr = callocz(1, sizeof(pthread_attr_t)); i = pthread_attr_init(attr); if(i != 0) fatal("pthread_attr_init() failed with code %d.", i); i = pthread_attr_getstacksize(attr, &default_stacksize); if(i != 0) fatal("pthread_attr_getstacksize() failed with code %d.", i); else debug(D_OPTIONS, "initial pthread stack size is %zu bytes", default_stacksize); return default_stacksize; }
static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *tree_lock, const char *name) { calculated_number *v = callocz(1, sizeof(calculated_number)); *v = NAN; RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); if(unlikely(!rv)) { free(v); debug(D_VARIABLES, "Requested variable '%s' already exists - possibly 2 plugins are updating it at the same time.", name); char *variable = strdupz(name); rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); rv = rrdvar_index_find(tree_lock, variable, hash); freez(variable); } return rv; }
static void find_all_mc() { char name[FILENAME_MAX + 1]; snprintfz(name, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/edac/mc"); char *dirname = config_get("plugin:proc:/sys/devices/system/edac/mc", "directory to monitor", name); DIR *dir = opendir(dirname); if(unlikely(!dir)) { error("Cannot read ECC memory errors directory '%s'", dirname); return; } struct dirent *de = NULL; while((de = readdir(dir))) { if(de->d_type == DT_DIR && de->d_name[0] == 'm' && de->d_name[1] == 'c' && isdigit(de->d_name[2])) { struct mc *m = callocz(1, sizeof(struct mc)); m->name = strdupz(de->d_name); struct stat st; snprintfz(name, FILENAME_MAX, "%s/%s/ce_count", dirname, de->d_name); if(stat(name, &st) != -1) m->ce_count_filename = strdupz(name); snprintfz(name, FILENAME_MAX, "%s/%s/ue_count", dirname, de->d_name); if(stat(name, &st) != -1) m->ue_count_filename = strdupz(name); if(!m->ce_count_filename && !m->ue_count_filename) { freez(m->name); freez(m); } else { m->next = mc_root; mc_root = m; } } } closedir(dir); }
static struct cgroup_network_interface *get_network_interface(const char *name) { struct cgroup_network_interface *ifm; uint32_t hash = simple_hash(name); // search it, from the last position to the end for(ifm = network_interfaces_last_used ; ifm ; ifm = ifm->next) { if (unlikely(hash == ifm->hash && !strcmp(name, ifm->name))) { network_interfaces_last_used = ifm->next; return ifm; } } // search it from the beginning to the last position we used for(ifm = network_interfaces_root ; ifm != network_interfaces_last_used ; ifm = ifm->next) { if (unlikely(hash == ifm->hash && !strcmp(name, ifm->name))) { network_interfaces_last_used = ifm->next; return ifm; } } // create a new one ifm = callocz(1, sizeof(struct cgroup_network_interface)); ifm->name = strdupz(name); ifm->hash = simple_hash(ifm->name); ifm->len = strlen(ifm->name); network_interfaces_added++; // link it to the end if (network_interfaces_root) { struct cgroup_network_interface *e; for(e = network_interfaces_root; e->next ; e = e->next) ; e->next = ifm; } else network_interfaces_root = ifm; return ifm; }
static inline struct config_value *config_value_create(struct config *co, const char *name, const char *value) { debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name); struct config_value *cv = callocz(1, sizeof(struct config_value)); cv->name = strdupz(name); cv->hash = simple_hash(cv->name); cv->value = strdupz(value); config_value_index_add(co, cv); config_section_write_lock(co); struct config_value *cv2 = co->values; if(cv2) { while (cv2->next) cv2 = cv2->next; cv2->next = cv; } else co->values = cv; config_section_unlock(co); return cv; }
inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value) { char *variable = strdupz(name); rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); RRDVAR *rv = rrdvar_index_find(tree, variable, hash); if(unlikely(!rv)) { debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", variable, scope); rv = callocz(1, sizeof(RRDVAR)); rv->name = variable; rv->hash = hash; rv->type = type; rv->value = value; RRDVAR *ret = rrdvar_index_add(tree, rv); if(unlikely(ret != rv)) { debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", variable, scope); freez(rv); freez(variable); rv = NULL; } else debug(D_VARIABLES, "Variable '%s' created in scope '%s'", variable, scope); } else { debug(D_VARIABLES, "Variable '%s' is already found in scope '%s'.", variable, scope); // already exists freez(variable); // this is important // it must return NULL - not the existing variable - or double-free will happen rv = NULL; } return rv; }
static inline struct config *config_section_create(const char *section) { debug(D_CONFIG, "Creating section '%s'.", section); struct config *co = callocz(1, sizeof(struct config)); co->name = strdupz(section); co->hash = simple_hash(co->name); avl_init_lock(&co->values_index, config_value_compare); config_index_add(co); config_global_write_lock(); struct config *co2 = config_root; if(co2) { while (co2->next) co2 = co2->next; co2->next = co; } else config_root = co; config_global_unlock(); return co; }
static int health_readfile(const char *filename, void *data) { RRDHOST *host = (RRDHOST *)data; debug(D_HEALTH, "Health configuration reading file '%s'", filename); static uint32_t hash_alarm = 0, hash_template = 0, hash_os = 0, hash_on = 0, hash_host = 0, hash_families = 0, hash_calc = 0, hash_green = 0, hash_red = 0, hash_warn = 0, hash_crit = 0, hash_exec = 0, hash_every = 0, hash_lookup = 0, hash_units = 0, hash_info = 0, hash_recipient = 0, hash_delay = 0, hash_options = 0; char buffer[HEALTH_CONF_MAX_LINE + 1]; if(unlikely(!hash_alarm)) { hash_alarm = simple_uhash(HEALTH_ALARM_KEY); hash_template = simple_uhash(HEALTH_TEMPLATE_KEY); hash_on = simple_uhash(HEALTH_ON_KEY); hash_os = simple_uhash(HEALTH_OS_KEY); hash_host = simple_uhash(HEALTH_HOST_KEY); hash_families = simple_uhash(HEALTH_FAMILIES_KEY); hash_calc = simple_uhash(HEALTH_CALC_KEY); hash_lookup = simple_uhash(HEALTH_LOOKUP_KEY); hash_green = simple_uhash(HEALTH_GREEN_KEY); hash_red = simple_uhash(HEALTH_RED_KEY); hash_warn = simple_uhash(HEALTH_WARN_KEY); hash_crit = simple_uhash(HEALTH_CRIT_KEY); hash_exec = simple_uhash(HEALTH_EXEC_KEY); hash_every = simple_uhash(HEALTH_EVERY_KEY); hash_units = simple_hash(HEALTH_UNITS_KEY); hash_info = simple_hash(HEALTH_INFO_KEY); hash_recipient = simple_hash(HEALTH_RECIPIENT_KEY); hash_delay = simple_uhash(HEALTH_DELAY_KEY); hash_options = simple_uhash(HEALTH_OPTIONS_KEY); } FILE *fp = fopen(filename, "r"); if(!fp) { error("Health configuration cannot read file '%s'.", filename); return 0; } RRDCALC *rc = NULL; RRDCALCTEMPLATE *rt = NULL; int ignore_this = 0; size_t line = 0, append = 0; char *s; while((s = fgets(&buffer[append], (int)(HEALTH_CONF_MAX_LINE - append), fp)) || append) { int stop_appending = !s; line++; s = trim(buffer); if(!s || *s == '#') continue; append = strlen(s); if(!stop_appending && s[append - 1] == '\\') { s[append - 1] = ' '; append = &s[append] - buffer; if(append < HEALTH_CONF_MAX_LINE) continue; else { error("Health configuration has too long muli-line at line %zu of file '%s'.", line, filename); } } append = 0; char *key = s; while(*s && *s != ':') s++; if(!*s) { error("Health configuration has invalid line %zu of file '%s'. It does not contain a ':'. Ignoring it.", line, filename); continue; } *s = '\0'; s++; char *value = s; key = trim_all(key); value = trim_all(value); if(!key) { error("Health configuration has invalid line %zu of file '%s'. Keyword is empty. Ignoring it.", line, filename); continue; } if(!value) { error("Health configuration has invalid line %zu of file '%s'. value is empty. Ignoring it.", line, filename); continue; } uint32_t hash = simple_uhash(key); if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { if (rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc))) rrdcalc_free(rc); if(rt) { if (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)) rrdcalctemplate_free(rt); rt = NULL; } rc = callocz(1, sizeof(RRDCALC)); rc->next_event_id = 1; rc->name = strdupz(value); rc->hash = simple_hash(rc->name); rc->source = health_source_file(line, filename); rc->green = NAN; rc->red = NAN; rc->value = NAN; rc->old_value = NAN; rc->delay_multiplier = 1.0; if(rrdvar_fix_name(rc->name)) error("Health configuration renamed alarm '%s' to '%s'", value, rc->name); ignore_this = 0; } else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) { if(rc) { if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc)) rrdcalc_free(rc); rc = NULL; } if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))) rrdcalctemplate_free(rt); rt = callocz(1, sizeof(RRDCALCTEMPLATE)); rt->name = strdupz(value); rt->hash_name = simple_hash(rt->name); rt->source = health_source_file(line, filename); rt->green = NAN; rt->red = NAN; rt->delay_multiplier = 1.0; if(rrdvar_fix_name(rt->name)) error("Health configuration renamed template '%s' to '%s'", value, rt->name); ignore_this = 0; } else if(hash == hash_os && !strcasecmp(key, HEALTH_OS_KEY)) { char *os_match = value; SIMPLE_PATTERN *os_pattern = simple_pattern_create(os_match, NULL, SIMPLE_PATTERN_EXACT); if(!simple_pattern_matches(os_pattern, host->os)) { if(rc) debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rc->name, line, filename, os_match); if(rt) debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rt->name, line, filename, os_match); ignore_this = 1; } simple_pattern_free(os_pattern); } else if(hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) { char *host_match = value; SIMPLE_PATTERN *host_pattern = simple_pattern_create(host_match, NULL, SIMPLE_PATTERN_EXACT); if(!simple_pattern_matches(host_pattern, host->hostname)) { if(rc) debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rc->name, line, filename, host_match); if(rt) debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rt->name, line, filename, host_match); ignore_this = 1; } simple_pattern_free(host_pattern); } else if(rc) { if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { if(rc->chart) { if(strcmp(rc->chart, value) != 0) error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rc->name, key, rc->chart, value, value); freez(rc->chart); } rc->chart = strdupz(value); rc->hash_chart = simple_hash(rc->chart); } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { health_parse_db_lookup(line, filename, value, &rc->group, &rc->after, &rc->before, &rc->update_every, &rc->options, &rc->dimensions); } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!health_parse_duration(value, &rc->update_every)) error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", line, filename, rc->name, key, value); } else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { char *e; rc->green = str2ld(value, &e); if(e && *e) { error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", line, filename, rc->name, key, e); } } else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { char *e; rc->red = str2ld(value, &e); if(e && *e) { error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", line, filename, rc->name, key, e); } } else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { const char *failed_at = NULL; int error = 0; rc->calculation = expression_parse(value, &failed_at, &error); if(!rc->calculation) { error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { const char *failed_at = NULL; int error = 0; rc->warning = expression_parse(value, &failed_at, &error); if(!rc->warning) { error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { const char *failed_at = NULL; int error = 0; rc->critical = expression_parse(value, &failed_at, &error); if(!rc->critical) { error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { if(rc->exec) { if(strcmp(rc->exec, value) != 0) error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rc->name, key, rc->exec, value, value); freez(rc->exec); } rc->exec = strdupz(value); } else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { if(rc->recipient) { if(strcmp(rc->recipient, value) != 0) error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rc->name, key, rc->recipient, value, value); freez(rc->recipient); } rc->recipient = strdupz(value); } else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { if(rc->units) { if(strcmp(rc->units, value) != 0) error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rc->name, key, rc->units, value, value); freez(rc->units); } rc->units = strdupz(value); strip_quotes(rc->units); } else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { if(rc->info) { if(strcmp(rc->info, value) != 0) error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rc->name, key, rc->info, value, value); freez(rc->info); } rc->info = strdupz(value); strip_quotes(rc->info); } else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { health_parse_delay(line, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier); } else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { rc->options |= health_parse_options(value); } else { error("Health configuration at line %zu of file '%s' for alarm '%s' has unknown key '%s'.", line, filename, rc->name, key); } } else if(rt) { if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { if(rt->context) { if(strcmp(rt->context, value) != 0) error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rt->name, key, rt->context, value, value); freez(rt->context); } rt->context = strdupz(value); rt->hash_context = simple_hash(rt->context); } else if(hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) { freez(rt->family_match); simple_pattern_free(rt->family_pattern); rt->family_match = strdupz(value); rt->family_pattern = simple_pattern_create(rt->family_match, NULL, SIMPLE_PATTERN_EXACT); } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { health_parse_db_lookup(line, filename, value, &rt->group, &rt->after, &rt->before, &rt->update_every, &rt->options, &rt->dimensions); } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!health_parse_duration(value, &rt->update_every)) error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' cannot parse duration: '%s'.", line, filename, rt->name, key, value); } else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { char *e; rt->green = str2ld(value, &e); if(e && *e) { error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", line, filename, rt->name, key, e); } } else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { char *e; rt->red = str2ld(value, &e); if(e && *e) { error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", line, filename, rt->name, key, e); } } else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { const char *failed_at = NULL; int error = 0; rt->calculation = expression_parse(value, &failed_at, &error); if(!rt->calculation) { error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", line, filename, rt->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { const char *failed_at = NULL; int error = 0; rt->warning = expression_parse(value, &failed_at, &error); if(!rt->warning) { error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", line, filename, rt->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { const char *failed_at = NULL; int error = 0; rt->critical = expression_parse(value, &failed_at, &error); if(!rt->critical) { error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", line, filename, rt->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { if(rt->exec) { if(strcmp(rt->exec, value) != 0) error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rt->name, key, rt->exec, value, value); freez(rt->exec); } rt->exec = strdupz(value); } else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { if(rt->recipient) { if(strcmp(rt->recipient, value) != 0) error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rt->name, key, rt->recipient, value, value); freez(rt->recipient); } rt->recipient = strdupz(value); } else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { if(rt->units) { if(strcmp(rt->units, value) != 0) error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rt->name, key, rt->units, value, value); freez(rt->units); } rt->units = strdupz(value); strip_quotes(rt->units); } else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { if(rt->info) { if(strcmp(rt->info, value) != 0) error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", line, filename, rt->name, key, rt->info, value, value); freez(rt->info); } rt->info = strdupz(value); strip_quotes(rt->info); } else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { health_parse_delay(line, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier); } else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { rt->options |= health_parse_options(value); } else { error("Health configuration at line %zu of file '%s' for template '%s' has unknown key '%s'.", line, filename, rt->name, key); } } else { error("Health configuration at line %zu of file '%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.", line, filename, key); } } if(rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc))) rrdcalc_free(rc); if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))) rrdcalctemplate_free(rt); fclose(fp); return 1; }
int do_sys_class_power_supply(int update_every, usec_t dt) { (void)dt; static int do_capacity = -1, do_property[3] = {-1}; static int keep_fds_open = CONFIG_BOOLEAN_NO, keep_fds_open_config = -1; static char *dirname = NULL; if(unlikely(do_capacity == -1)) { do_capacity = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery capacity", CONFIG_BOOLEAN_YES); do_property[0] = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery charge", CONFIG_BOOLEAN_NO); do_property[1] = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery energy", CONFIG_BOOLEAN_NO); do_property[2] = config_get_boolean("plugin:proc:/sys/class/power_supply", "power supply voltage", CONFIG_BOOLEAN_NO); keep_fds_open_config = config_get_boolean_ondemand("plugin:proc:/sys/class/power_supply", "keep files open", CONFIG_BOOLEAN_AUTO); char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/class/power_supply"); dirname = config_get("plugin:proc:/sys/class/power_supply", "directory to monitor", filename); } DIR *dir = opendir(dirname); if(unlikely(!dir)) { error("Cannot read directory '%s'", dirname); return 1; } struct dirent *de = NULL; while(likely(de = readdir(dir))) { if(likely(de->d_type == DT_DIR && ( (de->d_name[0] == '.' && de->d_name[1] == '\0') || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') ))) continue; if(likely(de->d_type == DT_LNK || de->d_type == DT_DIR)) { uint32_t hash = simple_hash(de->d_name); struct power_supply *ps; for(ps = power_supply_root; ps; ps = ps->next) { if(unlikely(ps->hash == hash && !strcmp(ps->name, de->d_name))) { ps->found = 1; break; } } // allocate memory for power supply and initialize it if(unlikely(!ps)) { ps = callocz(sizeof(struct power_supply), 1); ps->name = strdupz(de->d_name); ps->hash = simple_hash(de->d_name); ps->found = 1; ps->next = power_supply_root; power_supply_root = ps; struct stat stbuf; if(likely(do_capacity != CONFIG_BOOLEAN_NO)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/%s/%s", dirname, de->d_name, "capacity"); if (stat(filename, &stbuf) == 0) { ps->capacity = callocz(sizeof(struct capacity), 1); ps->capacity->filename = strdupz(filename); ps->capacity->fd = -1; files_num++; } } // allocate memory and initialize structures for every property and file found size_t pr_idx, pd_idx; size_t prev_idx = 3; // there is no property with this index for(pr_idx = 0; pr_idx < 3; pr_idx++) { if(unlikely(do_property[pr_idx] != CONFIG_BOOLEAN_NO)) { struct ps_property *pr = NULL; for(pd_idx = pr_idx * 5; pd_idx < pr_idx * 5 + 5; pd_idx++) { // check if file exists char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/%s/%s_%s", dirname, de->d_name, ps_property_names[pr_idx], ps_property_dim_names[pd_idx]); if (stat(filename, &stbuf) == 0) { // add chart if(unlikely(prev_idx != pr_idx)) { pr = callocz(sizeof(struct ps_property), 1); pr->name = strdupz(ps_property_names[pr_idx]); pr->title = strdupz(ps_property_titles[pr_idx]); pr->units = strdupz(ps_property_units[pr_idx]); prev_idx = pr_idx; pr->next = ps->property_root; ps->property_root = pr; } // add dimension struct ps_property_dim *pd; pd= callocz(sizeof(struct ps_property_dim), 1); pd->name = strdupz(ps_property_dim_names[pd_idx]); pd->filename = strdupz(filename); pd->fd = -1; files_num++; pd->next = pr->property_dim_root; pr->property_dim_root = pd; } } } } } // read capacity file if(likely(ps->capacity)) { char buffer[30 + 1]; if(unlikely(ps->capacity->fd == -1)) { ps->capacity->fd = open(ps->capacity->filename, O_RDONLY, 0666); if(unlikely(ps->capacity->fd == -1)) { error("Cannot open file '%s'", ps->capacity->filename); power_supply_free(ps); } } ssize_t r = read(ps->capacity->fd, buffer, 30); if(unlikely(r < 1)) { error("Cannot read file '%s'", ps->capacity->filename); power_supply_free(ps); } else { buffer[r] = '\0'; ps->capacity->value = str2ull(buffer); } if(unlikely(!keep_fds_open)) { close(ps->capacity->fd); ps->capacity->fd = -1; } else if(unlikely(lseek(ps->capacity->fd, 0, SEEK_SET) == -1)) { error("Cannot seek in file '%s'", ps->capacity->filename); close(ps->capacity->fd); ps->capacity->fd = -1; } } // read property files int read_error = 0; struct ps_property *pr; for(pr = ps->property_root; pr && !read_error; pr = pr->next) { struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { char buffer[30 + 1]; if(unlikely(pd->fd == -1)) { pd->fd = open(pd->filename, O_RDONLY, 0666); if(unlikely(pd->fd == -1)) { error("Cannot open file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } } ssize_t r = read(pd->fd, buffer, 30); if(unlikely(r < 1)) { error("Cannot read file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } buffer[r] = '\0'; pd->value = str2ull(buffer); if(unlikely(!keep_fds_open)) { close(pd->fd); pd->fd = -1; } else if(unlikely(lseek(pd->fd, 0, SEEK_SET) == -1)) { error("Cannot seek in file '%s'", pd->filename); close(pd->fd); pd->fd = -1; } } } } } closedir(dir); keep_fds_open = keep_fds_open_config; if(likely(keep_fds_open_config == CONFIG_BOOLEAN_AUTO)) { if(unlikely(files_num > 32)) keep_fds_open = CONFIG_BOOLEAN_NO; else keep_fds_open = CONFIG_BOOLEAN_YES; } // -------------------------------------------------------------------- struct power_supply *ps = power_supply_root; while(unlikely(ps)) { if(unlikely(!ps->found)) { struct power_supply *f = ps; ps = ps->next; power_supply_free(f); continue; } if(likely(ps->capacity)) { if(unlikely(!ps->capacity->st)) { ps->capacity->st = rrdset_create_localhost( "powersupply_capacity" , ps->name , NULL , ps->name , "powersupply.capacity" , "Battery capacity" , "percentage" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_POWER_SUPPLY_NAME , NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY , update_every , RRDSET_TYPE_LINE ); } else rrdset_next(ps->capacity->st); if(unlikely(!ps->capacity->rd)) ps->capacity->rd = rrddim_add(ps->capacity->st, "capacity", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(ps->capacity->st, ps->capacity->rd, ps->capacity->value); rrdset_done(ps->capacity->st); } struct ps_property *pr; for(pr = ps->property_root; pr; pr = pr->next) { if(unlikely(!pr->st)) { char id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "powersupply_%s", pr->name); snprintfz(context, RRD_ID_LENGTH_MAX, "powersupply.%s", pr->name); pr->st = rrdset_create_localhost( id , ps->name , NULL , ps->name , context , pr->title , pr->units , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_POWER_SUPPLY_NAME , NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY , update_every , RRDSET_TYPE_LINE ); } else rrdset_next(pr->st); struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { if(unlikely(!pd->rd)) pd->rd = rrddim_add(pr->st, pd->name, NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(pr->st, pd->rd, pd->value); } rrdset_done(pr->st); } ps->found = 0; ps = ps->next; } return 0; }
RRDHOST *rrdhost_create(const char *hostname, const char *guid, const char *os, int update_every, long entries, RRD_MEMORY_MODE memory_mode, int health_enabled, int rrdpush_enabled, char *rrdpush_destination, char *rrdpush_api_key, int is_localhost ) { debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid); rrd_check_wrlock(); RRDHOST *host = callocz(1, sizeof(RRDHOST)); host->rrd_update_every = (update_every > 0)?update_every:1; host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries); host->rrd_memory_mode = memory_mode; host->health_enabled = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled; host->rrdpush_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key); host->rrdpush_destination = (host->rrdpush_enabled)?strdupz(rrdpush_destination):NULL; host->rrdpush_api_key = (host->rrdpush_enabled)?strdupz(rrdpush_api_key):NULL; host->rrdpush_pipe[0] = -1; host->rrdpush_pipe[1] = -1; host->rrdpush_socket = -1; netdata_mutex_init(&host->rrdpush_mutex); netdata_rwlock_init(&host->rrdhost_rwlock); rrdhost_init_hostname(host, hostname); rrdhost_init_machine_guid(host, guid); rrdhost_init_os(host, os); 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); if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete obsolete charts files", 1)) rrdhost_flag_set(host, RRDHOST_DELETE_OBSOLETE_FILES); if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete orphan hosts files", 1) && !is_localhost) rrdhost_flag_set(host, RRDHOST_DELETE_ORPHAN_FILES); // ------------------------------------------------------------------------ // initialize health variables 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(); long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max); if(n < 10) { error("Host '%s': health configuration has invalid max log entries %ld. Using default %u", host->hostname, n, host->health_log.max); config_set_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", (long)host->health_log.max); } else host->health_log.max = (unsigned int)n; netdata_rwlock_init(&host->health_log.alarm_log_rwlock); char filename[FILENAME_MAX + 1]; if(is_localhost) { host->cache_dir = strdupz(netdata_configured_cache_dir); host->varlib_dir = strdupz(netdata_configured_varlib_dir); } else { // this is not localhost - append our GUID to localhost path snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid); host->cache_dir = strdupz(filename); if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { int r = mkdir(host->cache_dir, 0775); if(r != 0 && errno != EEXIST) error("Host '%s': cannot create directory '%s'", host->hostname, host->cache_dir); } snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid); host->varlib_dir = strdupz(filename); if(host->health_enabled) { int r = mkdir(host->varlib_dir, 0775); if(r != 0 && errno != EEXIST) error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir); } } if(host->health_enabled) { snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir); int r = mkdir(filename, 0775); if(r != 0 && errno != EEXIST) error("Host '%s': cannot create directory '%s'", host->hostname, filename); } snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir); host->health_log_filename = strdupz(filename); snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir); host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename)); host->health_default_recipient = strdup("root"); // ------------------------------------------------------------------------ // load health configuration if(host->health_enabled) { health_alarm_log_load(host); health_alarm_log_open(host); rrdhost_wrlock(host); health_readdir(host, health_config_dir()); rrdhost_unlock(host); } // ------------------------------------------------------------------------ // link it and add it to the index if(is_localhost) { host->next = localhost; localhost = host; } else { if(localhost) { host->next = localhost->next; localhost->next = host; } else localhost = host; } RRDHOST *t = rrdhost_index_add(host); if(t != host) { error("Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.", host->hostname, host->machine_guid, t->hostname, t->machine_guid); rrdhost_free(host); host = NULL; } else { info("Host '%s' with guid '%s' initialized" ", os %s" ", update every %d" ", memory mode %s" ", history entries %ld" ", streaming %s" " (to '%s' with api key '%s')" ", health %s" ", cache_dir '%s'" ", varlib_dir '%s'" ", health_log '%s'" ", alarms default handler '%s'" ", alarms default recipient '%s'" , host->hostname , host->machine_guid , host->os , host->rrd_update_every , rrd_memory_mode_name(host->rrd_memory_mode) , host->rrd_history_entries , host->rrdpush_enabled?"enabled":"disabled" , host->rrdpush_destination?host->rrdpush_destination:"" , host->rrdpush_api_key?host->rrdpush_api_key:"" , host->health_enabled?"enabled":"disabled" , host->cache_dir , host->varlib_dir , host->health_log_filename , host->health_default_exec , host->health_default_recipient ); } rrd_hosts_available++; return host; }
void *socket_listen_main_multi_threaded(void *ptr) { (void)ptr; web_server_mode = WEB_SERVER_MODE_MULTI_THREADED; info("Multi-threaded WEB SERVER thread created with task id %d", gettid()); struct web_client *w; int retval, counter = 0; if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); if(!listen_fds_count) fatal("LISTENER: No sockets to listen to."); struct pollfd *fds = callocz(sizeof(struct pollfd), listen_fds_count); size_t i; for(i = 0; i < listen_fds_count ;i++) { fds[i].fd = listen_fds[i]; fds[i].events = POLLIN; fds[i].revents = 0; info("Listening on '%s'", (listen_fds_names[i])?listen_fds_names[i]:"UNKNOWN"); } int timeout = 10 * 1000; for(;;) { // debug(D_WEB_CLIENT, "LISTENER: Waiting..."); retval = poll(fds, listen_fds_count, timeout); if(unlikely(retval == -1)) { error("LISTENER: poll() failed."); continue; } else if(unlikely(!retval)) { debug(D_WEB_CLIENT, "LISTENER: select() timeout."); counter = 0; cleanup_web_clients(); continue; } for(i = 0 ; i < listen_fds_count ; i++) { short int revents = fds[i].revents; // check for new incoming connections if(revents & POLLIN || revents & POLLPRI) { fds[i].revents = 0; w = web_client_create(fds[i].fd); if(unlikely(!w)) { // no need for error log - web_client_create already logged the error continue; } if(pthread_create(&w->thread, NULL, web_client_main, w) != 0) { error("%llu: failed to create new thread for web client.", w->id); w->obsolete = 1; } else if(pthread_detach(w->thread) != 0) { error("%llu: Cannot request detach of newly created web client thread.", w->id); w->obsolete = 1; } } } // cleanup unused clients counter++; if(counter >= CLEANUP_EVERY_EVENTS) { counter = 0; cleanup_web_clients(); } } debug(D_WEB_CLIENT, "LISTENER: exit!"); close_listen_sockets(); return NULL; }
void *grouping_create_sum(RRDR *r) { (void)r; return callocz(1, sizeof(struct grouping_sum)); }
void *pluginsd_main(void *ptr) { (void)ptr; info("PLUGINS.D thread created with task id %d", gettid()); if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); char *dir_name = config_get("plugins", "plugins directory", PLUGINS_DIR); int automatic_run = config_get_boolean("plugins", "enable running new plugins", 1); int scan_frequency = (int) config_get_number("plugins", "check for new plugins every", 60); DIR *dir = NULL; struct dirent *file = NULL; struct plugind *cd; // enable the apps plugin by default // config_get_boolean("plugins", "apps", 1); if(scan_frequency < 1) scan_frequency = 1; while(likely(1)) { if(unlikely(netdata_exit)) break; dir = opendir(dir_name); if(unlikely(!dir)) { error("Cannot open directory '%s'.", dir_name); pthread_exit(NULL); return NULL; } while(likely((file = readdir(dir)))) { if(unlikely(netdata_exit)) break; debug(D_PLUGINSD, "PLUGINSD: Examining file '%s'", file->d_name); if(unlikely(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)) continue; int len = (int) strlen(file->d_name); if(unlikely(len <= (int)PLUGINSD_FILE_SUFFIX_LEN)) continue; if(unlikely(strcmp(PLUGINSD_FILE_SUFFIX, &file->d_name[len - (int)PLUGINSD_FILE_SUFFIX_LEN]) != 0)) { debug(D_PLUGINSD, "PLUGINSD: File '%s' does not end in '%s'.", file->d_name, PLUGINSD_FILE_SUFFIX); continue; } char pluginname[CONFIG_MAX_NAME + 1]; snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name); int enabled = config_get_boolean("plugins", pluginname, automatic_run); if(unlikely(!enabled)) { debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is not enabled", file->d_name); continue; } // check if it runs already for(cd = pluginsd_root ; likely(cd) ; cd = cd->next) { if(unlikely(strcmp(cd->filename, file->d_name) == 0)) break; } if(likely(cd && !cd->obsolete)) { debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is already running", cd->filename); continue; } // it is not running // allocate a new one, or use the obsolete one if(unlikely(!cd)) { cd = callocz(sizeof(struct plugind), 1); snprintfz(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname); strncpyz(cd->filename, file->d_name, FILENAME_MAX); snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", dir_name, cd->filename); cd->enabled = enabled; cd->update_every = (int) config_get_number(cd->id, "update every", rrd_update_every); cd->started_t = time(NULL); char *def = ""; snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def)); // link it if(likely(pluginsd_root)) cd->next = pluginsd_root; pluginsd_root = cd; } cd->obsolete = 0; if(unlikely(!cd->enabled)) continue; // spawn a new thread for it if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) { error("PLUGINSD: failed to create new thread for plugin '%s'.", cd->filename); cd->obsolete = 1; } else if(unlikely(pthread_detach(cd->thread) != 0)) error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename); } closedir(dir); sleep((unsigned int) scan_frequency); } pthread_exit(NULL); return NULL; }
static int read_cpuidle_states(char *cpuidle_name_filename , char *cpuidle_time_filename, struct per_core_cpuidle_chart *cpuidle_charts, size_t core) { char filename[FILENAME_MAX + 1]; static char next_state_filename[FILENAME_MAX + 1]; struct stat stbuf; struct per_core_cpuidle_chart *cc = &cpuidle_charts[core]; size_t state; if(unlikely(!cc->cpuidle_state_len || cc->rescan_cpu_states)) { int state_file_found = 1; // check at least one state if(cc->cpuidle_state_len) { for(state = 0; state < cc->cpuidle_state_len; state++) { freez(cc->cpuidle_state[state].name); freez(cc->cpuidle_state[state].time_filename); close(cc->cpuidle_state[state].time_fd); cc->cpuidle_state[state].time_fd = -1; } freez(cc->cpuidle_state); cc->cpuidle_state = NULL; cc->cpuidle_state_len = 0; cc->active_time_rd = NULL; cc->st = NULL; } while(likely(state_file_found)) { snprintfz(filename, FILENAME_MAX, cpuidle_name_filename, core, cc->cpuidle_state_len); if (stat(filename, &stbuf) == 0) cc->cpuidle_state_len++; else state_file_found = 0; } snprintfz(next_state_filename, FILENAME_MAX, cpuidle_name_filename, core, cc->cpuidle_state_len); if(likely(cc->cpuidle_state_len)) cc->cpuidle_state = callocz(cc->cpuidle_state_len, sizeof(struct cpuidle_state)); for(state = 0; state < cc->cpuidle_state_len; state++) { char name_buf[50 + 1]; snprintfz(filename, FILENAME_MAX, cpuidle_name_filename, core, state); int fd = open(filename, O_RDONLY, 0666); if(unlikely(fd == -1)) { error("Cannot open file '%s'", filename); cc->rescan_cpu_states = 1; return 1; } ssize_t r = read(fd, name_buf, 50); if(unlikely(r < 1)) { error("Cannot read file '%s'", filename); close(fd); cc->rescan_cpu_states = 1; return 1; } name_buf[r - 1] = '\0'; // erase extra character cc->cpuidle_state[state].name = strdupz(trim(name_buf)); close(fd); snprintfz(filename, FILENAME_MAX, cpuidle_time_filename, core, state); cc->cpuidle_state[state].time_filename = strdupz(filename); cc->cpuidle_state[state].time_fd = -1; } cc->rescan_cpu_states = 0; } for(state = 0; state < cc->cpuidle_state_len; state++) { struct cpuidle_state *cs = &cc->cpuidle_state[state]; if(unlikely(cs->time_fd == -1)) { cs->time_fd = open(cs->time_filename, O_RDONLY); if (unlikely(cs->time_fd == -1)) { error("Cannot open file '%s'", cs->time_filename); cc->rescan_cpu_states = 1; return 1; } } char time_buf[50 + 1]; if(likely(read_one_state(time_buf, cs->time_filename, &cs->time_fd))) { cs->value = str2ll(time_buf, NULL); } else { cc->rescan_cpu_states = 1; return 1; } } // check if the number of states was increased if(unlikely(stat(next_state_filename, &stbuf) == 0)) { cc->rescan_cpu_states = 1; return 1; } return 0; }