コード例 #1
0
ファイル: statistical.c プロジェクト: swinsey/netdata
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;
}
コード例 #2
0
ファイル: dictionary.c プロジェクト: NAStools/netdata
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;
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: plugin_tc.c プロジェクト: rlugojr/netdata
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);
}
コード例 #5
0
ファイル: plugin_tc.c プロジェクト: firehol/netdata
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);
}
コード例 #6
0
ファイル: dictionary.c プロジェクト: NAStools/netdata
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;
}
コード例 #7
0
ファイル: median.c プロジェクト: josealgardataborges/netdata
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;
}
コード例 #8
0
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;
}
コード例 #9
0
ファイル: web_buffer.c プロジェクト: acecommerce/netdata
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);
}
コード例 #10
0
ファイル: rrdsetvar.c プロジェクト: baidjay/netdata
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;
}
コード例 #11
0
ファイル: threads.c プロジェクト: Peoplecantfly/netdata
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;
}
コード例 #12
0
ファイル: rrdvar.c プロジェクト: cppmx/netdata
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;
}
コード例 #13
0
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);
}
コード例 #14
0
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;
}
コード例 #15
0
ファイル: appconfig.c プロジェクト: congdonglinux/netdata
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;
}
コード例 #16
0
ファイル: rrdvar.c プロジェクト: cppmx/netdata
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;
}
コード例 #17
0
ファイル: appconfig.c プロジェクト: congdonglinux/netdata
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;
}
コード例 #18
0
ファイル: health_config.c プロジェクト: baidjay/netdata
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;
}
コード例 #19
0
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;
}
コード例 #20
0
ファイル: rrdhost.c プロジェクト: darrentangdt/netdata
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;
}
コード例 #21
0
ファイル: web_server.c プロジェクト: NAStools/netdata
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;
}
コード例 #22
0
ファイル: sum.c プロジェクト: FedericoCeratto/netdata
void *grouping_create_sum(RRDR *r) {
    (void)r;
    return callocz(1, sizeof(struct grouping_sum));
}
コード例 #23
0
ファイル: plugins_d.c プロジェクト: jasonwbarnett/netdata
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;
}
コード例 #24
0
ファイル: proc_stat.c プロジェクト: firehol/netdata
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;
}