static inline struct config *config_section_create(const char *section) { debug(D_CONFIG, "Creating section '%s'.", section); struct config *co = calloc(1, sizeof(struct config)); if(!co) fatal("Cannot allocate config"); co->name = strdup(section); if(!co->name) fatal("Cannot allocate config.name"); 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; }
RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type) { if(!type || !type[0]) { fatal("Cannot create rrd stats without a type."); return NULL; } if(!id || !id[0]) { fatal("Cannot create rrd stats without an id."); return NULL; } char fullid[RRD_ID_LENGTH_MAX + 1]; char fullfilename[FILENAME_MAX + 1]; RRDSET *st = NULL; snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); st = rrdset_find(fullid); if(st) { error("Cannot create rrd stats for '%s', it already exists.", fullid); return st; } long entries = config_get_number(fullid, "history", rrd_default_history_entries); if(entries < 5) entries = config_set_number(fullid, "history", 5); if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX); int enabled = config_get_boolean(fullid, "enabled", 1); if(!enabled) entries = 5; unsigned long size = sizeof(RRDSET); char *cache_dir = rrdset_cache_dir(fullid); debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id); snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir); if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0); if(st) { if(strcmp(st->magic, RRDSET_MAGIC) != 0) { errno = 0; info("Initializing file %s.", fullfilename); bzero(st, size); } else if(strcmp(st->id, fullid) != 0) { errno = 0; error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid); // munmap(st, size); // st = NULL; bzero(st, size); } else if(st->memsize != size || st->entries != entries) { errno = 0; error("File %s does not have the desired size. Clearing it.", fullfilename); bzero(st, size); } else if(st->update_every != update_every) { errno = 0; error("File %s does not have the desired update frequency. Clearing it.", fullfilename); bzero(st, size); } else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) { errno = 0; error("File %s is too old. Clearing it.", fullfilename); bzero(st, size); } } if(st) { st->name = NULL; st->type = NULL; st->family = NULL; st->context = NULL; st->title = NULL; st->units = NULL; st->dimensions = NULL; st->next = NULL; st->mapped = rrd_memory_mode; } else { st = calloc(1, size); if(!st) { fatal("Cannot allocate memory for RRD_STATS %s.%s", type, id); return NULL; } st->mapped = RRD_MEMORY_MODE_RAM; } st->memsize = size; st->entries = entries; st->update_every = update_every; if(st->current_entry >= st->entries) st->current_entry = 0; strcpy(st->cache_filename, fullfilename); strcpy(st->magic, RRDSET_MAGIC); strcpy(st->id, fullid); st->hash = simple_hash(st->id); st->cache_dir = cache_dir; st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type))); st->type = config_get(st->id, "type", type); st->family = config_get(st->id, "family", family?family:st->type); st->context = config_get(st->id, "context", context?context:st->id); st->units = config_get(st->id, "units", units?units:""); st->priority = config_get_number(st->id, "priority", priority); st->enabled = enabled; st->isdetail = 0; st->debug = 0; st->last_collected_time.tv_sec = 0; st->last_collected_time.tv_usec = 0; st->counter_done = 0; st->gap_when_lost_iterations_above = (int) ( config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2); avl_init_lock(&st->dimensions_index, rrddim_compare); pthread_rwlock_init(&st->rwlock, NULL); pthread_rwlock_wrlock(&rrdset_root_rwlock); if(name && *name) rrdset_set_name(st, name); else rrdset_set_name(st, id); { char varvalue[CONFIG_MAX_VALUE + 1]; snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name); st->title = config_get(st->id, "title", varvalue); } st->next = rrdset_root; rrdset_root = st; rrdset_index_add(st); pthread_rwlock_unlock(&rrdset_root_rwlock); return(st); }
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; }