hosts except localhost save files in subdirectory in /var/cache/netdata and /var/lib/netdata
Costa Tsaousis (ktsaou) committed
Feb 18, 2017 at 23:50 UTC
1c8a9f944e75831ca700852d7e8dad0e5c3fd0f7
5 files changed
+175
-104
src/rrd.c
+3
-3
@@ -113,15 +113,15 @@ const char *rrdset_type_name(RRDSET_TYPE chart_type) {
113
// ----------------------------------------------------------------------------
114
// RRD - cache directory
115
116
-char *rrdset_cache_dir(RRDHOST *host, const char *id) {
116
+char *rrdset_cache_dir(RRDHOST *host, const char *id, const char *config_section) {
117
char *ret = NULL;
118
119
char b[FILENAME_MAX + 1];
120
char n[FILENAME_MAX + 1];
121
rrdset_strncpyz_name(b, id, FILENAME_MAX);
122
123
- snprintfz(n, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, b);
124
- ret = config_get(id, "cache directory", n);
123
+ snprintfz(n, FILENAME_MAX, "%s/%s", host->cache_dir, b);
124
+ ret = config_get(config_section, "cache directory", n);
125
126
if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
127
int r = mkdir(ret, 0775);
src/rrd.h
+8
-2
@@ -216,6 +216,8 @@ struct rrdset {
216
// since the config always has a higher priority
217
// (the user overwrites the name of the charts)
218
219
+ char *config_section; // the config section for the chart
220
+
221
char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
222
char *family; // grouping sets under the same family
223
char *title; // title shown to user
@@ -325,6 +327,9 @@ struct rrdhost {
327
avl_tree_lock rrdfamily_root_index; // the host's chart families index
328
avl_tree_lock variables_root_index; // the host's chart variables index
329
330
+ char *cache_dir; // the directory to save RRD cache files
331
+ char *varlib_dir; // the directory to save health log
332
+
333
// all RRDCALCs are primarily allocated and linked here
334
// RRDCALCs may be linked to charts at any point
335
// (charts may or may not exist when these are loaded)
@@ -385,7 +390,7 @@ extern RRDSET *rrdset_create(RRDHOST *host
390
, const char *units
391
, long priority
392
, int update_every
388
- , int chart_type);
393
+ , RRDSET_TYPE chart_type);
394
395
#define rrdset_create_localhost(type, id, name, family, context, title, units, priority, update_every, chart_type) rrdset_create(localhost, type, id, name, family, context, title, units, priority, update_every, chart_type)
396
@@ -463,10 +468,11 @@ extern collected_number rrddim_set(RRDSET *st, const char *id, collected_number
468
469
#ifdef NETDATA_RRD_INTERNALS
470
471
+extern void rrdset_free(RRDSET *st);
472
extern avl_tree_lock rrdhost_root_index;
473
474
extern char *rrdset_strncpyz_name(char *to, const char *from, size_t length);
469
-extern char *rrdset_cache_dir(RRDHOST *host, const char *id);
475
+extern char *rrdset_cache_dir(RRDHOST *host, const char *id, const char *config_section);
476
477
extern void rrdset_reset(RRDSET *st);
478
src/rrddim.c
+9
-6
@@ -43,7 +43,7 @@ inline void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) {
43
44
char varname[CONFIG_MAX_NAME + 1];
45
snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
46
- rd->name = config_set_default(st->id, varname, name);
46
+ rd->name = config_set_default(st->config_section, varname, name);
47
rd->hash_name = simple_hash(rd->name);
48
49
rrddimvar_rename_all(rd);
@@ -84,7 +84,6 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, collected_numbe
84
rd->variables = NULL;
85
rd->next = NULL;
86
rd->rrdset = NULL;
87
- rd->rrd_memory_mode = st->rrd_memory_mode;
87
88
struct timeval now;
89
now_realtime_timeval(&now);
@@ -124,6 +123,10 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, collected_numbe
123
error("File %s does not have the expected algorithm (expected %u '%s', found %u '%s'). Previous values may be wrong."
124
, fullfilename, algorithm, rrd_algorithm_name(algorithm), rd->algorithm,
125
rrd_algorithm_name(rd->algorithm));
126
+
127
+ // make sure we have the right memory mode
128
+ // even if we cleared the memory
129
+ rd->rrd_memory_mode = st->rrd_memory_mode;
130
}
131
}
132
@@ -143,17 +146,17 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, collected_numbe
146
rd->cache_filename = strdupz(fullfilename);
147
148
snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
146
- rd->name = config_get(st->id, varname, (name && *name)?name:rd->id);
149
+ rd->name = config_get(st->config_section, varname, (name && *name)?name:rd->id);
150
rd->hash_name = simple_hash(rd->name);
151
152
snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id);
150
- rd->algorithm = rrd_algorithm_id(config_get(st->id, varname, rrd_algorithm_name(algorithm)));
153
+ rd->algorithm = rrd_algorithm_id(config_get(st->config_section, varname, rrd_algorithm_name(algorithm)));
154
155
snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id);
153
- rd->multiplier = config_get_number(st->id, varname, multiplier);
156
+ rd->multiplier = config_get_number(st->config_section, varname, multiplier);
157
158
snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id);
156
- rd->divisor = config_get_number(st->id, varname, divisor);
159
+ rd->divisor = config_get_number(st->config_section, varname, divisor);
160
if(!rd->divisor) rd->divisor = 1;
161
162
rd->entries = st->entries;
src/rrdhost.c
+30
-25
@@ -93,13 +93,38 @@ RRDHOST *rrdhost_create(const char *hostname, const char *guid) {
93
94
if(!localhost) {
95
// this is localhost
96
- snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", netdata_configured_varlib_dir);
96
+
97
+ host->cache_dir = strdupz(netdata_configured_cache_dir);
98
+ host->varlib_dir = strdupz(netdata_configured_varlib_dir);
99
+
100
+ snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
101
host->health_log_filename = strdupz(config_get("health", "health db file", filename));
102
+
103
}
104
else {
105
// this is not localhost - append our GUID to localhost path
101
- snprintfz(filename, FILENAME_MAX, "%s.%s", localhost->health_log_filename, host->machine_guid);
106
+
107
+ snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid);
108
+ host->cache_dir = strdupz(filename);
109
+
110
+ if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
111
+ int r = mkdir(host->cache_dir, 0775);
112
+ if(r != 0 && errno != EEXIST)
113
+ error("Cannot create directory '%s'", host->cache_dir);
114
+ }
115
+
116
+ snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid);
117
+ host->varlib_dir = strdupz(filename);
118
+
119
+ if(host->health_enabled) {
120
+ int r = mkdir(host->varlib_dir, 0775);
121
+ if(r != 0 && errno != EEXIST)
122
+ error("Cannot create directory '%s'", host->varlib_dir);
123
+ }
124
+
125
+ snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
126
host->health_log_filename = strdupz(filename);
127
+
128
}
129
130
snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir);
@@ -191,34 +216,14 @@ void rrdhost_free(RRDHOST *host) {
216
for(st = host->rrdset_root; st ;) {
217
RRDSET *next = st->next;
218
194
- pthread_rwlock_wrlock(&st->rwlock);
195
-
196
- while(st->variables) rrdsetvar_free(st->variables);
197
- while(st->alarms) rrdsetcalc_unlink(st->alarms);
198
- while(st->dimensions) rrddim_free(st, st->dimensions);
199
-
200
- if(unlikely(rrdset_index_del(host, st) != st))
201
- error("RRDSET: INTERNAL ERROR: attempt to remove from index chart '%s', removed a different chart.", st->id);
202
-
203
- rrdset_index_del_name(host, st);
204
-
205
- st->rrdfamily->use_count--;
206
- if(!st->rrdfamily->use_count)
207
- rrdfamily_free(host, st->rrdfamily);
208
-
209
- pthread_rwlock_unlock(&st->rwlock);
210
-
211
- if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) {
212
- debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
213
- munmap(st, st->memsize);
214
- }
215
- else
216
- freez(st);
219
+ rrdset_free(st);
220
221
st = next;
222
}
223
host->rrdset_root = NULL;
224
225
+ freez(host->cache_dir);
226
+ freez(host->varlib_dir);
227
freez(host->health_default_exec);
228
freez(host->health_default_recipient);
229
freez(host->health_log_filename);
src/rrdset.c
+125
-68
@@ -133,12 +133,12 @@ void rrdset_set_name(RRDSET *st, const char *name) {
133
134
if(st->name) {
135
rrdset_index_del_name(st->rrdhost, st);
136
- st->name = config_set_default(st->id, "name", b);
136
+ st->name = config_set_default(st->config_section, "name", b);
137
st->hash_name = simple_hash(st->name);
138
rrdsetvar_rename_all(st);
139
}
140
else {
141
- st->name = config_get(st->id, "name", b);
141
+ st->name = config_get(st->config_section, "name", b);
142
st->hash_name = simple_hash(st->name);
143
}
144
@@ -206,12 +206,44 @@ static inline void timeval_align(struct timeval *tv, int update_every) {
206
tv->tv_usec = 500000;
207
}
208
209
+// ----------------------------------------------------------------------------
210
+// RRDSET - free a chart
211
+
212
+void rrdset_free(RRDSET *st) {
213
+ pthread_rwlock_wrlock(&st->rwlock);
214
+
215
+ while(st->variables) rrdsetvar_free(st->variables);
216
+ while(st->alarms) rrdsetcalc_unlink(st->alarms);
217
+ while(st->dimensions) rrddim_free(st, st->dimensions);
218
+
219
+ if(unlikely(rrdset_index_del(st->rrdhost, st) != st))
220
+ error("RRDSET: INTERNAL ERROR: attempt to remove from index chart '%s', removed a different chart.", st->id);
221
+
222
+ rrdset_index_del_name(st->rrdhost, st);
223
+
224
+ st->rrdfamily->use_count--;
225
+ if(!st->rrdfamily->use_count)
226
+ rrdfamily_free(st->rrdhost, st->rrdfamily);
227
+
228
+ pthread_rwlock_unlock(&st->rwlock);
229
+
230
+ // free directly allocated memory
231
+ freez(st->config_section);
232
+
233
+ if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) {
234
+ debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
235
+ munmap(st, st->memsize);
236
+ }
237
+ else
238
+ freez(st);
239
+}
240
+
241
// ----------------------------------------------------------------------------
242
// RRDSET - create a chart
243
244
RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const char *name, const char *family
245
, const char *context, const char *title, const char *units, long priority
214
- , int update_every, int chart_type) {
246
+ , int update_every, RRDSET_TYPE chart_type) {
247
248
if(!type || !type[0]) {
249
fatal("Cannot create rrd stats without a type.");
@@ -223,9 +255,10 @@ RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const cha
255
return NULL;
256
}
257
226
- char fullid[RRD_ID_LENGTH_MAX + 1];
227
- char fullfilename[FILENAME_MAX + 1];
258
+ // ------------------------------------------------------------------------
259
+ // check if it already exists
260
261
+ char fullid[RRD_ID_LENGTH_MAX + 1];
262
snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);
263
264
RRDSET *st = rrdset_find(host, fullid);
@@ -234,77 +267,101 @@ RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const cha
267
return st;
268
}
269
237
- long rentries = config_get_number(fullid, "history", host->rrd_history_entries);
270
+ char fullfilename[FILENAME_MAX + 1];
271
+
272
+ // ------------------------------------------------------------------------
273
+ // compose the config_section for this chart
274
+
275
+ char config_section[RRD_ID_LENGTH_MAX + 1];
276
+ if(host == localhost)
277
+ strcpy(config_section, fullid);
278
+ else
279
+ snprintfz(config_section, RRD_ID_LENGTH_MAX, "%s/%s", host->machine_guid, fullid);
280
+
281
+ // ------------------------------------------------------------------------
282
+ // get the options from the config, we need to create it
283
+
284
+ long rentries = config_get_number(config_section, "history", host->rrd_history_entries);
285
long entries = align_entries_to_pagesize(rentries);
239
- if(entries != rentries) entries = config_set_number(fullid, "history", entries);
286
+ if(entries != rentries) entries = config_set_number(config_section, "history", entries);
287
241
- int enabled = config_get_boolean(fullid, "enabled", 1);
288
+ int enabled = config_get_boolean(config_section, "enabled", 1);
289
if(!enabled) entries = 5;
290
291
unsigned long size = sizeof(RRDSET);
245
- char *cache_dir = rrdset_cache_dir(host, fullid);
292
+ char *cache_dir = rrdset_cache_dir(host, fullid, config_section);
293
+
294
+ // ------------------------------------------------------------------------
295
+ // load it or allocate it
296
297
debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
298
299
snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
250
- if(host->rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((host->rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0);
251
- if(st) {
252
- if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
253
- errno = 0;
254
- info("Initializing file %s.", fullfilename);
255
- memset(st, 0, size);
256
- }
257
- else if(strcmp(st->id, fullid) != 0) {
258
- errno = 0;
259
- error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
260
- // munmap(st, size);
261
- // st = NULL;
262
- memset(st, 0, size);
263
- }
264
- else if(st->memsize != size || st->entries != entries) {
265
- errno = 0;
266
- error("File %s does not have the desired size. Clearing it.", fullfilename);
267
- memset(st, 0, size);
268
- }
269
- else if(st->update_every != update_every) {
270
- errno = 0;
271
- error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
272
- memset(st, 0, size);
273
- }
274
- else if((now_realtime_sec() - st->last_updated.tv_sec) > update_every * entries) {
275
- errno = 0;
276
- error("File %s is too old. Clearing it.", fullfilename);
277
- memset(st, 0, size);
278
- }
300
+ if(host->rrd_memory_mode != RRD_MEMORY_MODE_RAM) {
301
+ st = (RRDSET *) mymmap(fullfilename, size, ((host->rrd_memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 0);
302
+ if(st) {
303
+ memset(&st->avl, 0, sizeof(avl));
304
+ memset(&st->avlname, 0, sizeof(avl));
305
+ memset(&st->variables_root_index, 0, sizeof(avl_tree_lock));
306
+ memset(&st->dimensions_index, 0, sizeof(avl_tree_lock));
307
+ memset(&st->rwlock, 0, sizeof(pthread_rwlock_t));
308
+
309
+ st->name = NULL;
310
+ st->type = NULL;
311
+ st->family = NULL;
312
+ st->context = NULL;
313
+ st->title = NULL;
314
+ st->units = NULL;
315
+ st->dimensions = NULL;
316
+ st->next = NULL;
317
+ st->variables = NULL;
318
+ st->alarms = NULL;
319
+ st->flags = 0x00000000;
320
+
321
+ if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
322
+ errno = 0;
323
+ info("Initializing file %s.", fullfilename);
324
+ memset(st, 0, size);
325
+ }
326
+ else if(strcmp(st->id, fullid) != 0) {
327
+ errno = 0;
328
+ error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
329
+ // munmap(st, size);
330
+ // st = NULL;
331
+ memset(st, 0, size);
332
+ }
333
+ else if(st->memsize != size || st->entries != entries) {
334
+ errno = 0;
335
+ error("File %s does not have the desired size. Clearing it.", fullfilename);
336
+ memset(st, 0, size);
337
+ }
338
+ else if(st->update_every != update_every) {
339
+ errno = 0;
340
+ error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
341
+ memset(st, 0, size);
342
+ }
343
+ else if((now_realtime_sec() - st->last_updated.tv_sec) > update_every * entries) {
344
+ errno = 0;
345
+ error("File %s is too old. Clearing it.", fullfilename);
346
+ memset(st, 0, size);
347
+ }
348
280
- // make sure the database is aligned
281
- if(st->last_updated.tv_sec)
282
- timeval_align(&st->last_updated, update_every);
283
- }
349
+ // make sure the database is aligned
350
+ if(st->last_updated.tv_sec)
351
+ timeval_align(&st->last_updated, update_every);
352
285
- if(st) {
286
- st->name = NULL;
287
- st->type = NULL;
288
- st->family = NULL;
289
- st->context = NULL;
290
- st->title = NULL;
291
- st->units = NULL;
292
- st->dimensions = NULL;
293
- st->next = NULL;
294
- st->rrd_memory_mode = host->rrd_memory_mode;
295
- st->variables = NULL;
296
- st->alarms = NULL;
297
- memset(&st->rwlock, 0, sizeof(pthread_rwlock_t));
298
- memset(&st->avl, 0, sizeof(avl));
299
- memset(&st->avlname, 0, sizeof(avl));
300
- memset(&st->variables_root_index, 0, sizeof(avl_tree_lock));
301
- memset(&st->dimensions_index, 0, sizeof(avl_tree_lock));
353
+ // make sure we have the right memory mode
354
+ // even if we cleared the memory
355
+ st->rrd_memory_mode = host->rrd_memory_mode;
356
+ }
357
}
303
- else {
358
+
359
+ if(unlikely(!st)) {
360
st = callocz(1, size);
361
st->rrd_memory_mode = RRD_MEMORY_MODE_RAM;
362
}
363
364
+ st->config_section = strdup(config_section);
365
st->rrdhost = host;
366
st->memsize = size;
367
st->entries = entries;
@@ -320,15 +377,15 @@ RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const cha
377
378
st->cache_dir = cache_dir;
379
323
- st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type)));
324
- st->type = config_get(st->id, "type", type);
325
- st->family = config_get(st->id, "family", family?family:st->type);
326
- st->units = config_get(st->id, "units", units?units:"");
380
+ st->chart_type = rrdset_type_id(config_get(st->config_section, "chart type", rrdset_type_name(chart_type)));
381
+ st->type = config_get(st->config_section, "type", type);
382
+ st->family = config_get(st->config_section, "family", family?family:st->type);
383
+ st->units = config_get(st->config_section, "units", units?units:"");
384
328
- st->context = config_get(st->id, "context", context?context:st->id);
385
+ st->context = config_get(st->config_section, "context", context?context:st->id);
386
st->hash_context = simple_hash(st->context);
387
331
- st->priority = config_get_number(st->id, "priority", priority);
388
+ st->priority = config_get_number(st->config_section, "priority", priority);
389
if(enabled)
390
rrdset_flag_set(st, RRDSET_FLAG_ENABLED);
391
else
@@ -351,7 +408,7 @@ RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const cha
408
st->counter_done = 0;
409
410
st->gap_when_lost_iterations_above = (int) (
354
- config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2);
411
+ config_get_number(st->config_section, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2);
412
413
avl_init_lock(&st->dimensions_index, rrddim_compare);
414
avl_init_lock(&st->variables_root_index, rrdvar_compare);
@@ -367,7 +424,7 @@ RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const cha
424
char varvalue2[CONFIG_MAX_VALUE + 1];
425
snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name);
426
json_escape_string(varvalue2, varvalue, sizeof(varvalue2));
370
- st->title = config_get(st->id, "title", varvalue2);
427
+ st->title = config_get(st->config_section, "title", varvalue2);
428
}
429
430
st->rrdfamily = rrdfamily_create(host, st->family);