]> arthur.barton.de Git - netdata.git/blob - src/common.c
varnish plugin: rename some dimensions
[netdata.git] / src / common.c
1 #include "common.h"
2
3 #ifdef __APPLE__
4 #define INHERIT_NONE 0
5 #endif /* __APPLE__ */
6 #if defined(__FreeBSD__) || defined(__APPLE__)
7 #    define O_NOATIME     0
8 #    define MADV_DONTFORK INHERIT_NONE
9 #endif /* __FreeBSD__ || __APPLE__*/
10
11 char *global_host_prefix = "";
12 int enable_ksm = 1;
13
14 volatile sig_atomic_t netdata_exit = 0;
15
16 // ----------------------------------------------------------------------------
17 // memory allocation functions that handle failures
18
19 // although netdata does not use memory allocations too often (netdata tries to
20 // maintain its memory footprint stable during runtime, i.e. all buffers are
21 // allocated during initialization and are adapted to current use throughout
22 // its lifetime), these can be used to override the default system allocation
23 // routines.
24
25 #ifdef NETDATA_LOG_ALLOCATIONS
26 static struct memory_statistics {
27     volatile size_t malloc_calls_made;
28     volatile size_t calloc_calls_made;
29     volatile size_t realloc_calls_made;
30     volatile size_t strdup_calls_made;
31     volatile size_t free_calls_made;
32     volatile size_t memory_calls_made;
33     volatile size_t allocated_memory;
34     volatile size_t mmapped_memory;
35 } memory_statistics;
36
37 static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
38     static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
39
40     //if(unlikely(!(memory_statistics.memory_calls_made % 5))) {
41         fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n",
42                 line, file, function,
43                 (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
44                 (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
45                 memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
46                 memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
47                 memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
48                 memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
49                 memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
50         );
51
52         memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
53     //}
54 }
55
56 static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
57 #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
58     __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
59     __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
60     __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
61 #else
62     // this is for debugging - we don't care locking it
63     memory_statistics.memory_calls_made++;
64     memory_statistics.malloc_calls_made++;
65     memory_statistics.allocated_memory += size;
66 #endif
67     print_allocations(file, function, line);
68 }
69
70 static inline void mmap_accounting(size_t size) {
71 #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
72     __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
73     __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST);
74 #else
75     // this is for debugging - we don't care locking it
76     memory_statistics.memory_calls_made++;
77     memory_statistics.mmapped_memory += size;
78 #endif
79 }
80
81 static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
82 #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
83     __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
84     __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST);
85     __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
86 #else
87     // this is for debugging - we don't care locking it
88     memory_statistics.memory_calls_made++;
89     memory_statistics.calloc_calls_made++;
90     memory_statistics.allocated_memory += size;
91 #endif
92     print_allocations(file, function, line);
93 }
94
95 static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
96     (void)ptr;
97
98 #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
99     __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
100     __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST);
101     __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
102 #else
103     // this is for debugging - we don't care locking it
104     memory_statistics.memory_calls_made++;
105     memory_statistics.realloc_calls_made++;
106     memory_statistics.allocated_memory += size;
107 #endif
108     print_allocations(file, function, line);
109 }
110
111 static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
112     size_t size = strlen(s) + 1;
113
114 #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
115     __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
116     __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST);
117     __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
118 #else
119     // this is for debugging - we don't care locking it
120     memory_statistics.memory_calls_made++;
121     memory_statistics.strdup_calls_made++;
122     memory_statistics.allocated_memory += size;
123 #endif
124     print_allocations(file, function, line);
125 }
126
127 static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) {
128     (void)file;
129     (void)function;
130     (void)line;
131
132     if(likely(ptr)) {
133 #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
134         __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
135         __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST);
136 #else
137         // this is for debugging - we don't care locking it
138         memory_statistics.memory_calls_made++;
139         memory_statistics.free_calls_made++;
140 #endif
141     }
142 }
143 #endif
144
145 #ifdef NETDATA_LOG_ALLOCATIONS
146 char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
147     strdup_accounting(file, function, line, s);
148 #else
149 char *strdupz(const char *s) {
150 #endif
151
152     char *t = strdup(s);
153     if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
154     return t;
155 }
156
157 #ifdef NETDATA_LOG_ALLOCATIONS
158 void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
159     malloc_accounting(file, function, line, size);
160 #else
161 void *mallocz(size_t size) {
162 #endif
163
164     void *p = malloc(size);
165     if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
166     return p;
167 }
168
169 #ifdef NETDATA_LOG_ALLOCATIONS
170 void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
171     calloc_accounting(file, function, line, nmemb * size);
172 #else
173 void *callocz(size_t nmemb, size_t size) {
174 #endif
175
176     void *p = calloc(nmemb, size);
177     if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
178     return p;
179 }
180
181 #ifdef NETDATA_LOG_ALLOCATIONS
182 void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
183     realloc_accounting(file, function, line, ptr, size);
184 #else
185 void *reallocz(void *ptr, size_t size) {
186 #endif
187
188     void *p = realloc(ptr, size);
189     if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
190     return p;
191 }
192
193 #ifdef NETDATA_LOG_ALLOCATIONS
194 void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
195     free_accounting(file, function, line, ptr);
196 #else
197 void freez(void *ptr) {
198 #endif
199
200     free(ptr);
201 }
202
203 void json_escape_string(char *dst, const char *src, size_t size) {
204     const char *t;
205     char *d = dst, *e = &dst[size - 1];
206
207     for(t = src; *t && d < e ;t++) {
208         if(unlikely(*t == '\\' || *t == '"')) {
209             if(unlikely(d + 1 >= e)) break;
210             *d++ = '\\';
211         }
212         *d++ = *t;
213     }
214
215     *d = '\0';
216 }
217
218 int sleep_usec(usec_t usec) {
219
220 #ifndef NETDATA_WITH_USLEEP
221     // we expect microseconds (1.000.000 per second)
222     // but timespec is nanoseconds (1.000.000.000 per second)
223     struct timespec rem, req = {
224             .tv_sec = (time_t) (usec / 1000000),
225             .tv_nsec = (suseconds_t) ((usec % 1000000) * 1000)
226     };
227
228     while (nanosleep(&req, &rem) == -1) {
229         if (likely(errno == EINTR)) {
230             debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
231             req.tv_sec = rem.tv_sec;
232             req.tv_nsec = rem.tv_nsec;
233         } else {
234             error("Cannot nanosleep() for %llu microseconds.", usec);
235             break;
236         }
237     }
238
239     return 0;
240 #else
241     int ret = usleep(usec);
242     if(unlikely(ret == -1 && errno == EINVAL)) {
243         // on certain systems, usec has to be up to 999999
244         if(usec > 999999) {
245             int counter = usec / 999999;
246             while(counter--)
247                 usleep(999999);
248
249             usleep(usec % 999999);
250         }
251         else {
252             error("Cannot usleep() for %llu microseconds.", usec);
253             return ret;
254         }
255     }
256
257     if(ret != 0)
258         error("usleep() failed for %llu microseconds.", usec);
259
260     return ret;
261 #endif
262 }
263
264 unsigned char netdata_map_chart_names[256] = {
265         [0] = '\0', //
266         [1] = '_', //
267         [2] = '_', //
268         [3] = '_', //
269         [4] = '_', //
270         [5] = '_', //
271         [6] = '_', //
272         [7] = '_', //
273         [8] = '_', //
274         [9] = '_', //
275         [10] = '_', //
276         [11] = '_', //
277         [12] = '_', //
278         [13] = '_', //
279         [14] = '_', //
280         [15] = '_', //
281         [16] = '_', //
282         [17] = '_', //
283         [18] = '_', //
284         [19] = '_', //
285         [20] = '_', //
286         [21] = '_', //
287         [22] = '_', //
288         [23] = '_', //
289         [24] = '_', //
290         [25] = '_', //
291         [26] = '_', //
292         [27] = '_', //
293         [28] = '_', //
294         [29] = '_', //
295         [30] = '_', //
296         [31] = '_', //
297         [32] = '_', //
298         [33] = '_', // !
299         [34] = '_', // "
300         [35] = '_', // #
301         [36] = '_', // $
302         [37] = '_', // %
303         [38] = '_', // &
304         [39] = '_', // '
305         [40] = '_', // (
306         [41] = '_', // )
307         [42] = '_', // *
308         [43] = '_', // +
309         [44] = '.', // ,
310         [45] = '-', // -
311         [46] = '.', // .
312         [47] = '/', // /
313         [48] = '0', // 0
314         [49] = '1', // 1
315         [50] = '2', // 2
316         [51] = '3', // 3
317         [52] = '4', // 4
318         [53] = '5', // 5
319         [54] = '6', // 6
320         [55] = '7', // 7
321         [56] = '8', // 8
322         [57] = '9', // 9
323         [58] = '_', // :
324         [59] = '_', // ;
325         [60] = '_', // <
326         [61] = '_', // =
327         [62] = '_', // >
328         [63] = '_', // ?
329         [64] = '_', // @
330         [65] = 'a', // A
331         [66] = 'b', // B
332         [67] = 'c', // C
333         [68] = 'd', // D
334         [69] = 'e', // E
335         [70] = 'f', // F
336         [71] = 'g', // G
337         [72] = 'h', // H
338         [73] = 'i', // I
339         [74] = 'j', // J
340         [75] = 'k', // K
341         [76] = 'l', // L
342         [77] = 'm', // M
343         [78] = 'n', // N
344         [79] = 'o', // O
345         [80] = 'p', // P
346         [81] = 'q', // Q
347         [82] = 'r', // R
348         [83] = 's', // S
349         [84] = 't', // T
350         [85] = 'u', // U
351         [86] = 'v', // V
352         [87] = 'w', // W
353         [88] = 'x', // X
354         [89] = 'y', // Y
355         [90] = 'z', // Z
356         [91] = '_', // [
357         [92] = '/', // backslash
358         [93] = '_', // ]
359         [94] = '_', // ^
360         [95] = '_', // _
361         [96] = '_', // `
362         [97] = 'a', // a
363         [98] = 'b', // b
364         [99] = 'c', // c
365         [100] = 'd', // d
366         [101] = 'e', // e
367         [102] = 'f', // f
368         [103] = 'g', // g
369         [104] = 'h', // h
370         [105] = 'i', // i
371         [106] = 'j', // j
372         [107] = 'k', // k
373         [108] = 'l', // l
374         [109] = 'm', // m
375         [110] = 'n', // n
376         [111] = 'o', // o
377         [112] = 'p', // p
378         [113] = 'q', // q
379         [114] = 'r', // r
380         [115] = 's', // s
381         [116] = 't', // t
382         [117] = 'u', // u
383         [118] = 'v', // v
384         [119] = 'w', // w
385         [120] = 'x', // x
386         [121] = 'y', // y
387         [122] = 'z', // z
388         [123] = '_', // {
389         [124] = '_', // |
390         [125] = '_', // }
391         [126] = '_', // ~
392         [127] = '_', //
393         [128] = '_', //
394         [129] = '_', //
395         [130] = '_', //
396         [131] = '_', //
397         [132] = '_', //
398         [133] = '_', //
399         [134] = '_', //
400         [135] = '_', //
401         [136] = '_', //
402         [137] = '_', //
403         [138] = '_', //
404         [139] = '_', //
405         [140] = '_', //
406         [141] = '_', //
407         [142] = '_', //
408         [143] = '_', //
409         [144] = '_', //
410         [145] = '_', //
411         [146] = '_', //
412         [147] = '_', //
413         [148] = '_', //
414         [149] = '_', //
415         [150] = '_', //
416         [151] = '_', //
417         [152] = '_', //
418         [153] = '_', //
419         [154] = '_', //
420         [155] = '_', //
421         [156] = '_', //
422         [157] = '_', //
423         [158] = '_', //
424         [159] = '_', //
425         [160] = '_', //
426         [161] = '_', //
427         [162] = '_', //
428         [163] = '_', //
429         [164] = '_', //
430         [165] = '_', //
431         [166] = '_', //
432         [167] = '_', //
433         [168] = '_', //
434         [169] = '_', //
435         [170] = '_', //
436         [171] = '_', //
437         [172] = '_', //
438         [173] = '_', //
439         [174] = '_', //
440         [175] = '_', //
441         [176] = '_', //
442         [177] = '_', //
443         [178] = '_', //
444         [179] = '_', //
445         [180] = '_', //
446         [181] = '_', //
447         [182] = '_', //
448         [183] = '_', //
449         [184] = '_', //
450         [185] = '_', //
451         [186] = '_', //
452         [187] = '_', //
453         [188] = '_', //
454         [189] = '_', //
455         [190] = '_', //
456         [191] = '_', //
457         [192] = '_', //
458         [193] = '_', //
459         [194] = '_', //
460         [195] = '_', //
461         [196] = '_', //
462         [197] = '_', //
463         [198] = '_', //
464         [199] = '_', //
465         [200] = '_', //
466         [201] = '_', //
467         [202] = '_', //
468         [203] = '_', //
469         [204] = '_', //
470         [205] = '_', //
471         [206] = '_', //
472         [207] = '_', //
473         [208] = '_', //
474         [209] = '_', //
475         [210] = '_', //
476         [211] = '_', //
477         [212] = '_', //
478         [213] = '_', //
479         [214] = '_', //
480         [215] = '_', //
481         [216] = '_', //
482         [217] = '_', //
483         [218] = '_', //
484         [219] = '_', //
485         [220] = '_', //
486         [221] = '_', //
487         [222] = '_', //
488         [223] = '_', //
489         [224] = '_', //
490         [225] = '_', //
491         [226] = '_', //
492         [227] = '_', //
493         [228] = '_', //
494         [229] = '_', //
495         [230] = '_', //
496         [231] = '_', //
497         [232] = '_', //
498         [233] = '_', //
499         [234] = '_', //
500         [235] = '_', //
501         [236] = '_', //
502         [237] = '_', //
503         [238] = '_', //
504         [239] = '_', //
505         [240] = '_', //
506         [241] = '_', //
507         [242] = '_', //
508         [243] = '_', //
509         [244] = '_', //
510         [245] = '_', //
511         [246] = '_', //
512         [247] = '_', //
513         [248] = '_', //
514         [249] = '_', //
515         [250] = '_', //
516         [251] = '_', //
517         [252] = '_', //
518         [253] = '_', //
519         [254] = '_', //
520         [255] = '_'  //
521 };
522
523 // make sure the supplied string
524 // is good for a netdata chart/dimension ID/NAME
525 void netdata_fix_chart_name(char *s) {
526     while ((*s = netdata_map_chart_names[(unsigned char) *s])) s++;
527 }
528
529 unsigned char netdata_map_chart_ids[256] = {
530         [0] = '\0', //
531         [1] = '_', //
532         [2] = '_', //
533         [3] = '_', //
534         [4] = '_', //
535         [5] = '_', //
536         [6] = '_', //
537         [7] = '_', //
538         [8] = '_', //
539         [9] = '_', //
540         [10] = '_', //
541         [11] = '_', //
542         [12] = '_', //
543         [13] = '_', //
544         [14] = '_', //
545         [15] = '_', //
546         [16] = '_', //
547         [17] = '_', //
548         [18] = '_', //
549         [19] = '_', //
550         [20] = '_', //
551         [21] = '_', //
552         [22] = '_', //
553         [23] = '_', //
554         [24] = '_', //
555         [25] = '_', //
556         [26] = '_', //
557         [27] = '_', //
558         [28] = '_', //
559         [29] = '_', //
560         [30] = '_', //
561         [31] = '_', //
562         [32] = '_', //
563         [33] = '_', // !
564         [34] = '_', // "
565         [35] = '_', // #
566         [36] = '_', // $
567         [37] = '_', // %
568         [38] = '_', // &
569         [39] = '_', // '
570         [40] = '_', // (
571         [41] = '_', // )
572         [42] = '_', // *
573         [43] = '_', // +
574         [44] = '.', // ,
575         [45] = '-', // -
576         [46] = '.', // .
577         [47] = '_', // /
578         [48] = '0', // 0
579         [49] = '1', // 1
580         [50] = '2', // 2
581         [51] = '3', // 3
582         [52] = '4', // 4
583         [53] = '5', // 5
584         [54] = '6', // 6
585         [55] = '7', // 7
586         [56] = '8', // 8
587         [57] = '9', // 9
588         [58] = '_', // :
589         [59] = '_', // ;
590         [60] = '_', // <
591         [61] = '_', // =
592         [62] = '_', // >
593         [63] = '_', // ?
594         [64] = '_', // @
595         [65] = 'a', // A
596         [66] = 'b', // B
597         [67] = 'c', // C
598         [68] = 'd', // D
599         [69] = 'e', // E
600         [70] = 'f', // F
601         [71] = 'g', // G
602         [72] = 'h', // H
603         [73] = 'i', // I
604         [74] = 'j', // J
605         [75] = 'k', // K
606         [76] = 'l', // L
607         [77] = 'm', // M
608         [78] = 'n', // N
609         [79] = 'o', // O
610         [80] = 'p', // P
611         [81] = 'q', // Q
612         [82] = 'r', // R
613         [83] = 's', // S
614         [84] = 't', // T
615         [85] = 'u', // U
616         [86] = 'v', // V
617         [87] = 'w', // W
618         [88] = 'x', // X
619         [89] = 'y', // Y
620         [90] = 'z', // Z
621         [91] = '_', // [
622         [92] = '/', // backslash
623         [93] = '_', // ]
624         [94] = '_', // ^
625         [95] = '_', // _
626         [96] = '_', // `
627         [97] = 'a', // a
628         [98] = 'b', // b
629         [99] = 'c', // c
630         [100] = 'd', // d
631         [101] = 'e', // e
632         [102] = 'f', // f
633         [103] = 'g', // g
634         [104] = 'h', // h
635         [105] = 'i', // i
636         [106] = 'j', // j
637         [107] = 'k', // k
638         [108] = 'l', // l
639         [109] = 'm', // m
640         [110] = 'n', // n
641         [111] = 'o', // o
642         [112] = 'p', // p
643         [113] = 'q', // q
644         [114] = 'r', // r
645         [115] = 's', // s
646         [116] = 't', // t
647         [117] = 'u', // u
648         [118] = 'v', // v
649         [119] = 'w', // w
650         [120] = 'x', // x
651         [121] = 'y', // y
652         [122] = 'z', // z
653         [123] = '_', // {
654         [124] = '_', // |
655         [125] = '_', // }
656         [126] = '_', // ~
657         [127] = '_', //
658         [128] = '_', //
659         [129] = '_', //
660         [130] = '_', //
661         [131] = '_', //
662         [132] = '_', //
663         [133] = '_', //
664         [134] = '_', //
665         [135] = '_', //
666         [136] = '_', //
667         [137] = '_', //
668         [138] = '_', //
669         [139] = '_', //
670         [140] = '_', //
671         [141] = '_', //
672         [142] = '_', //
673         [143] = '_', //
674         [144] = '_', //
675         [145] = '_', //
676         [146] = '_', //
677         [147] = '_', //
678         [148] = '_', //
679         [149] = '_', //
680         [150] = '_', //
681         [151] = '_', //
682         [152] = '_', //
683         [153] = '_', //
684         [154] = '_', //
685         [155] = '_', //
686         [156] = '_', //
687         [157] = '_', //
688         [158] = '_', //
689         [159] = '_', //
690         [160] = '_', //
691         [161] = '_', //
692         [162] = '_', //
693         [163] = '_', //
694         [164] = '_', //
695         [165] = '_', //
696         [166] = '_', //
697         [167] = '_', //
698         [168] = '_', //
699         [169] = '_', //
700         [170] = '_', //
701         [171] = '_', //
702         [172] = '_', //
703         [173] = '_', //
704         [174] = '_', //
705         [175] = '_', //
706         [176] = '_', //
707         [177] = '_', //
708         [178] = '_', //
709         [179] = '_', //
710         [180] = '_', //
711         [181] = '_', //
712         [182] = '_', //
713         [183] = '_', //
714         [184] = '_', //
715         [185] = '_', //
716         [186] = '_', //
717         [187] = '_', //
718         [188] = '_', //
719         [189] = '_', //
720         [190] = '_', //
721         [191] = '_', //
722         [192] = '_', //
723         [193] = '_', //
724         [194] = '_', //
725         [195] = '_', //
726         [196] = '_', //
727         [197] = '_', //
728         [198] = '_', //
729         [199] = '_', //
730         [200] = '_', //
731         [201] = '_', //
732         [202] = '_', //
733         [203] = '_', //
734         [204] = '_', //
735         [205] = '_', //
736         [206] = '_', //
737         [207] = '_', //
738         [208] = '_', //
739         [209] = '_', //
740         [210] = '_', //
741         [211] = '_', //
742         [212] = '_', //
743         [213] = '_', //
744         [214] = '_', //
745         [215] = '_', //
746         [216] = '_', //
747         [217] = '_', //
748         [218] = '_', //
749         [219] = '_', //
750         [220] = '_', //
751         [221] = '_', //
752         [222] = '_', //
753         [223] = '_', //
754         [224] = '_', //
755         [225] = '_', //
756         [226] = '_', //
757         [227] = '_', //
758         [228] = '_', //
759         [229] = '_', //
760         [230] = '_', //
761         [231] = '_', //
762         [232] = '_', //
763         [233] = '_', //
764         [234] = '_', //
765         [235] = '_', //
766         [236] = '_', //
767         [237] = '_', //
768         [238] = '_', //
769         [239] = '_', //
770         [240] = '_', //
771         [241] = '_', //
772         [242] = '_', //
773         [243] = '_', //
774         [244] = '_', //
775         [245] = '_', //
776         [246] = '_', //
777         [247] = '_', //
778         [248] = '_', //
779         [249] = '_', //
780         [250] = '_', //
781         [251] = '_', //
782         [252] = '_', //
783         [253] = '_', //
784         [254] = '_', //
785         [255] = '_'  //
786 };
787
788 // make sure the supplied string
789 // is good for a netdata chart/dimension ID/NAME
790 void netdata_fix_chart_id(char *s) {
791     while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
792 }
793
794 /*
795 // http://stackoverflow.com/questions/7666509/hash-function-for-string
796 uint32_t simple_hash(const char *name)
797 {
798     const char *s = name;
799     uint32_t hash = 5381;
800     int i;
801
802     while((i = *s++)) hash = ((hash << 5) + hash) + i;
803
804     // fprintf(stderr, "HASH: %lu %s\n", hash, name);
805
806     return hash;
807 }
808 */
809
810
811 // http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
812 uint32_t simple_hash(const char *name) {
813     unsigned char *s = (unsigned char *) name;
814     uint32_t hval = 0x811c9dc5;
815
816     // FNV-1a algorithm
817     while (*s) {
818         // multiply by the 32 bit FNV magic prime mod 2^32
819         // NOTE: No need to optimize with left shifts.
820         //       GCC will use imul instruction anyway.
821         //       Tested with 'gcc -O3 -S'
822         //hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
823         hval *= 16777619;
824
825         // xor the bottom with the current octet
826         hval ^= (uint32_t) *s++;
827     }
828
829     // fprintf(stderr, "HASH: %u = %s\n", hval, name);
830     return hval;
831 }
832
833 uint32_t simple_uhash(const char *name) {
834     unsigned char *s = (unsigned char *) name;
835     uint32_t hval = 0x811c9dc5, c;
836
837     // FNV-1a algorithm
838     while ((c = *s++)) {
839         if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
840         hval *= 16777619;
841         hval ^= c;
842     }
843     return hval;
844 }
845
846 /*
847 // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
848 // one at a time hash
849 uint32_t simple_hash(const char *name) {
850     unsigned char *s = (unsigned char *)name;
851     uint32_t h = 0;
852
853     while(*s) {
854         h += *s++;
855         h += (h << 10);
856         h ^= (h >> 6);
857     }
858
859     h += (h << 3);
860     h ^= (h >> 11);
861     h += (h << 15);
862
863     // fprintf(stderr, "HASH: %u = %s\n", h, name);
864
865     return h;
866 }
867 */
868
869 void strreverse(char *begin, char *end) {
870     while (end > begin) {
871         // clearer code.
872         char aux = *end;
873         *end-- = *begin;
874         *begin++ = aux;
875     }
876 }
877
878 char *mystrsep(char **ptr, char *s) {
879     char *p = "";
880     while (p && !p[0] && *ptr) p = strsep(ptr, s);
881     return (p);
882 }
883
884 char *trim(char *s) {
885     // skip leading spaces
886     // and 'comments' as well!?
887     while (*s && isspace(*s)) s++;
888     if (!*s || *s == '#') return NULL;
889
890     // skip tailing spaces
891     // this way is way faster. Writes only one NUL char.
892     ssize_t l = strlen(s);
893     if (--l >= 0) {
894         char *p = s + l;
895         while (p > s && isspace(*p)) p--;
896         *++p = '\0';
897     }
898
899     if (!*s) return NULL;
900
901     return s;
902 }
903
904 void *mymmap(const char *filename, size_t size, int flags, int ksm) {
905     static int log_madvise_1 = 1;
906 #ifdef MADV_MERGEABLE
907     static int log_madvise_2 = 1, log_madvise_3 = 1;
908 #endif
909     void *mem = NULL;
910
911     errno = 0;
912     int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
913     if (fd != -1) {
914         if (lseek(fd, size, SEEK_SET) == (off_t) size) {
915             if (write(fd, "", 1) == 1) {
916                 if (ftruncate(fd, size))
917                     error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
918
919 #ifdef MADV_MERGEABLE
920                 if (flags & MAP_SHARED || !enable_ksm || !ksm) {
921 #endif
922                     mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
923                     if (mem == MAP_FAILED) {
924                         error("Cannot allocate SHARED memory for file '%s'.", filename);
925                         mem = NULL;
926                     }
927                     else {
928 #ifdef NETDATA_LOG_ALLOCATIONS
929                         mmap_accounting(size);
930 #endif
931                         int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
932                         if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
933
934                         if (madvise(mem, size, advise) != 0 && log_madvise_1) {
935                             error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
936                             log_madvise_1--;
937                         }
938                     }
939 #ifdef MADV_MERGEABLE
940                 }
941                 else {
942 /*
943                     // test - load the file into memory
944                     mem = calloc(1, size);
945                     if(mem) {
946                         if(lseek(fd, 0, SEEK_SET) == 0) {
947                             if(read(fd, mem, size) != (ssize_t)size)
948                                 error("Cannot read from file '%s'", filename);
949                         }
950                         else
951                             error("Cannot seek to beginning of file '%s'.", filename);
952                     }
953 */
954                     mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
955                     if (mem == MAP_FAILED) {
956                         error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
957                         mem = NULL;
958                     }
959                     else {
960 #ifdef NETDATA_LOG_ALLOCATIONS
961                         mmap_accounting(size);
962 #endif
963                         if (lseek(fd, 0, SEEK_SET) == 0) {
964                             if (read(fd, mem, size) != (ssize_t) size)
965                                 error("Cannot read from file '%s'", filename);
966                         } else
967                             error("Cannot seek to beginning of file '%s'.", filename);
968
969                         // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
970                         if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
971                             error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.",
972                                   filename);
973                             log_madvise_2--;
974                         }
975
976                         if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
977                             error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.",
978                                   filename);
979                             log_madvise_3--;
980                         }
981                     }
982                 }
983 #endif
984             }
985             else
986                 error("Cannot write to file '%s' at position %zu.", filename, size);
987         }
988         else
989             error("Cannot seek file '%s' to size %zu.", filename, size);
990
991         close(fd);
992     }
993     else
994         error("Cannot create/open file '%s'.", filename);
995
996     return mem;
997 }
998
999 int savememory(const char *filename, void *mem, size_t size) {
1000     char tmpfilename[FILENAME_MAX + 1];
1001
1002     snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
1003
1004     int fd = open(tmpfilename, O_RDWR | O_CREAT | O_NOATIME, 0664);
1005     if (fd < 0) {
1006         error("Cannot create/open file '%s'.", filename);
1007         return -1;
1008     }
1009
1010     if (write(fd, mem, size) != (ssize_t) size) {
1011         error("Cannot write to file '%s' %ld bytes.", filename, (long) size);
1012         close(fd);
1013         return -1;
1014     }
1015
1016     close(fd);
1017
1018     if (rename(tmpfilename, filename)) {
1019         error("Cannot rename '%s' to '%s'", tmpfilename, filename);
1020         return -1;
1021     }
1022
1023     return 0;
1024 }
1025
1026 int fd_is_valid(int fd) {
1027     return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
1028 }
1029
1030 pid_t gettid(void) {
1031 #ifdef __FreeBSD__
1032     return (pid_t)pthread_getthreadid_np();
1033 #elif defined(__APPLE__)
1034     uint64_t curthreadid;
1035     pthread_threadid_np(NULL, &curthreadid);
1036     return (pid_t)curthreadid;
1037 #else
1038     return (pid_t)syscall(SYS_gettid);
1039 #endif /* __FreeBSD__, __APPLE__*/
1040 }
1041
1042 char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
1043     char *s = fgets(buf, (int)buf_size, fp);
1044     if (!s) return NULL;
1045
1046     char *t = s;
1047     if (*t != '\0') {
1048         // find the string end
1049         while (*++t != '\0');
1050
1051         // trim trailing spaces/newlines/tabs
1052         while (--t > s && *t == '\n')
1053             *t = '\0';
1054     }
1055
1056     if (len)
1057         *len = t - s + 1;
1058
1059     return s;
1060 }
1061
1062 char *strncpyz(char *dst, const char *src, size_t n) {
1063     char *p = dst;
1064
1065     while (*src && n--)
1066         *dst++ = *src++;
1067
1068     *dst = '\0';
1069
1070     return p;
1071 }
1072
1073 int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
1074     int size = vsnprintf(dst, n, fmt, args);
1075
1076     if (unlikely((size_t) size > n)) {
1077         // truncated
1078         size = (int)n;
1079     }
1080
1081     dst[size] = '\0';
1082     return size;
1083 }
1084
1085 int snprintfz(char *dst, size_t n, const char *fmt, ...) {
1086     va_list args;
1087
1088     va_start(args, fmt);
1089     int ret = vsnprintfz(dst, n, fmt, args);
1090     va_end(args);
1091
1092     return ret;
1093 }
1094
1095 // ----------------------------------------------------------------------------
1096 // system functions
1097 // to retrieve settings of the system
1098
1099 int processors = 1;
1100 long get_system_cpus(void) {
1101     processors = 1;
1102
1103     char filename[FILENAME_MAX + 1];
1104     snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
1105
1106     procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
1107     if(!ff) {
1108         error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
1109         return processors;
1110     }
1111
1112     ff = procfile_readall(ff);
1113     if(!ff) {
1114         error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
1115         return processors;
1116     }
1117
1118     processors = 0;
1119     unsigned int i;
1120     for(i = 0; i < procfile_lines(ff); i++) {
1121         if(!procfile_linewords(ff, i)) continue;
1122
1123         if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++;
1124     }
1125     processors--;
1126     if(processors < 1) processors = 1;
1127
1128     procfile_close(ff);
1129
1130     debug(D_SYSTEM, "System has %d processors.", processors);
1131     return processors;
1132 }
1133
1134 pid_t pid_max = 32768;
1135 pid_t get_system_pid_max(void) {
1136     char filename[FILENAME_MAX + 1];
1137     snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", global_host_prefix);
1138     procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
1139     if(!ff) {
1140         error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
1141         return pid_max;
1142     }
1143
1144     ff = procfile_readall(ff);
1145     if(!ff) {
1146         error("Cannot read file '%s'. Assuming system supports %d pids.", filename, pid_max);
1147         return pid_max;
1148     }
1149
1150     pid_max = (pid_t)atoi(procfile_lineword(ff, 0, 0));
1151     if(!pid_max) {
1152         procfile_close(ff);
1153         pid_max = 32768;
1154         error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max);
1155         return pid_max;
1156     }
1157
1158     procfile_close(ff);
1159     debug(D_SYSTEM, "System supports %d pids.", pid_max);
1160     return pid_max;
1161 }
1162
1163 unsigned int hz;
1164 void get_system_HZ(void) {
1165     long ticks;
1166
1167     if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
1168         perror("sysconf");
1169     }
1170
1171     hz = (unsigned int) ticks;
1172 }
1173
1174 int read_single_number_file(const char *filename, unsigned long long *result) {
1175     char buffer[1024 + 1];
1176
1177     int fd = open(filename, O_RDONLY, 0666);
1178     if(unlikely(fd == -1)) return 1;
1179
1180     ssize_t r = read(fd, buffer, 1024);
1181     if(unlikely(r == -1)) {
1182         close(fd);
1183         return 2;
1184     }
1185
1186     close(fd);
1187     *result = strtoull(buffer, NULL, 0);
1188     return 0;
1189 }
1190
1191 // ----------------------------------------------------------------------------
1192 // simple_pattern_match
1193
1194 struct simple_pattern {
1195     const char *match;
1196     size_t len;
1197     NETDATA_SIMPLE_PREFIX_MODE mode;
1198     struct simple_pattern *next;
1199 };
1200
1201 NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
1202     struct simple_pattern *root = NULL;
1203
1204     if(unlikely(!list || !*list)) return root;
1205
1206     char *a = strdupz(list);
1207     if(a && *a) {
1208         char *s = a;
1209
1210         while(s && *s) {
1211             // skip all spaces
1212             while(isspace(*s)) s++;
1213
1214             // empty string
1215             if(unlikely(!*s)) break;
1216
1217             // find the next space
1218             char *c = s;
1219             while(*c && !isspace(*c)) c++;
1220
1221             // find the next word
1222             char *n;
1223             if(likely(*c)) n = c + 1;
1224             else n = NULL;
1225
1226             // terminate our string
1227             *c = '\0';
1228
1229             char buf[100 + 1];
1230             strncpy(buf, s, 100);
1231             buf[100] = '\0';
1232             if(likely(n)) *c = ' ';
1233             s = buf;
1234
1235             NETDATA_SIMPLE_PREFIX_MODE mode;
1236             size_t len = strlen(s);
1237             if(len >= 2 && *s == '*' && s[len - 1] == '*') {
1238                 s[len - 1] = '\0';
1239                 s++;
1240                 len -= 2;
1241                 mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
1242             }
1243             else if(len >= 1 && *s == '*') {
1244                 s++;
1245                 len--;
1246                 mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
1247             }
1248             else if(len >= 1 && s[len - 1] == '*') {
1249                 s[len - 1] = '\0';
1250                 len--;
1251                 mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
1252             }
1253             else
1254                 mode = default_mode;
1255
1256             if(len) {
1257                 if(*s == '*')
1258                     error("simple pattern '%s' includes '%s' that is invalid", a, s);
1259
1260                 // allocate the structure
1261                 struct simple_pattern *m = mallocz(sizeof(struct simple_pattern));
1262                 m->match = strdup(s);
1263                 m->len = strlen(m->match);
1264                 m->mode = mode;
1265                 m->next = root;
1266                 root = m;
1267             }
1268             else
1269                 error("simple pattern '%s' includes invalid matches", a);
1270
1271             // prepare for next loop
1272             s = n;
1273         }
1274     }
1275
1276     free(a);
1277     return (NETDATA_SIMPLE_PATTERN *)root;
1278 }
1279
1280 int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
1281     struct simple_pattern *m, *root = (struct simple_pattern *)list;
1282
1283     if(unlikely(!root)) return 0;
1284
1285     size_t len = strlen(str);
1286     for(m = root; m ; m = m->next) {
1287         if(m->len <= len) {
1288             switch(m->mode) {
1289                 case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
1290                     if(unlikely(strstr(str, m->match)))
1291                         return 1;
1292                     break;
1293
1294                 case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
1295                     if(unlikely(strncmp(str, m->match, m->len) == 0))
1296                         return 1;
1297                     break;
1298
1299                 case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
1300                     if(unlikely(strcmp(&str[len - m->len], m->match) == 0))
1301                         return 1;
1302                     break;
1303
1304                 case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
1305                 default:
1306                     if(unlikely(strcmp(str, m->match) == 0))
1307                         return 1;
1308                     break;
1309             }
1310         }
1311     }
1312
1313     return 0;
1314 }