]> arthur.barton.de Git - netdata.git/blob - src/common.c
apps.plugin now allows to be compiled for 32bit kernels
[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 /*
848 // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
849 // one at a time hash
850 uint32_t simple_hash(const char *name) {
851     unsigned char *s = (unsigned char *)name;
852     uint32_t h = 0;
853
854     while(*s) {
855         h += *s++;
856         h += (h << 10);
857         h ^= (h >> 6);
858     }
859
860     h += (h << 3);
861     h ^= (h >> 11);
862     h += (h << 15);
863
864     // fprintf(stderr, "HASH: %u = %s\n", h, name);
865
866     return h;
867 }
868 */
869
870 void strreverse(char *begin, char *end) {
871     while (end > begin) {
872         // clearer code.
873         char aux = *end;
874         *end-- = *begin;
875         *begin++ = aux;
876     }
877 }
878
879 char *mystrsep(char **ptr, char *s) {
880     char *p = "";
881     while (p && !p[0] && *ptr) p = strsep(ptr, s);
882     return (p);
883 }
884
885 char *trim(char *s) {
886     // skip leading spaces
887     // and 'comments' as well!?
888     while (*s && isspace(*s)) s++;
889     if (!*s || *s == '#') return NULL;
890
891     // skip tailing spaces
892     // this way is way faster. Writes only one NUL char.
893     ssize_t l = strlen(s);
894     if (--l >= 0) {
895         char *p = s + l;
896         while (p > s && isspace(*p)) p--;
897         *++p = '\0';
898     }
899
900     if (!*s) return NULL;
901
902     return s;
903 }
904
905 void *mymmap(const char *filename, size_t size, int flags, int ksm) {
906     static int log_madvise_1 = 1;
907 #ifdef MADV_MERGEABLE
908     static int log_madvise_2 = 1, log_madvise_3 = 1;
909 #endif
910     void *mem = NULL;
911
912     errno = 0;
913     int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
914     if (fd != -1) {
915         if (lseek(fd, size, SEEK_SET) == (off_t) size) {
916             if (write(fd, "", 1) == 1) {
917                 if (ftruncate(fd, size))
918                     error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
919
920 #ifdef MADV_MERGEABLE
921                 if (flags & MAP_SHARED || !enable_ksm || !ksm) {
922 #endif
923                     mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
924                     if (mem == MAP_FAILED) {
925                         error("Cannot allocate SHARED memory for file '%s'.", filename);
926                         mem = NULL;
927                     }
928                     else {
929 #ifdef NETDATA_LOG_ALLOCATIONS
930                         mmap_accounting(size);
931 #endif
932                         int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
933                         if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
934
935                         if (madvise(mem, size, advise) != 0 && log_madvise_1) {
936                             error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
937                             log_madvise_1--;
938                         }
939                     }
940 #ifdef MADV_MERGEABLE
941                 }
942                 else {
943 /*
944                     // test - load the file into memory
945                     mem = calloc(1, size);
946                     if(mem) {
947                         if(lseek(fd, 0, SEEK_SET) == 0) {
948                             if(read(fd, mem, size) != (ssize_t)size)
949                                 error("Cannot read from file '%s'", filename);
950                         }
951                         else
952                             error("Cannot seek to beginning of file '%s'.", filename);
953                     }
954 */
955                     mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
956                     if (mem == MAP_FAILED) {
957                         error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
958                         mem = NULL;
959                     }
960                     else {
961 #ifdef NETDATA_LOG_ALLOCATIONS
962                         mmap_accounting(size);
963 #endif
964                         if (lseek(fd, 0, SEEK_SET) == 0) {
965                             if (read(fd, mem, size) != (ssize_t) size)
966                                 error("Cannot read from file '%s'", filename);
967                         } else
968                             error("Cannot seek to beginning of file '%s'.", filename);
969
970                         // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
971                         if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
972                             error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.",
973                                   filename);
974                             log_madvise_2--;
975                         }
976
977                         if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
978                             error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.",
979                                   filename);
980                             log_madvise_3--;
981                         }
982                     }
983                 }
984 #endif
985             }
986             else
987                 error("Cannot write to file '%s' at position %zu.", filename, size);
988         }
989         else
990             error("Cannot seek file '%s' to size %zu.", filename, size);
991
992         close(fd);
993     }
994     else
995         error("Cannot create/open file '%s'.", filename);
996
997     return mem;
998 }
999
1000 int savememory(const char *filename, void *mem, size_t size) {
1001     char tmpfilename[FILENAME_MAX + 1];
1002
1003     snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
1004
1005     int fd = open(tmpfilename, O_RDWR | O_CREAT | O_NOATIME, 0664);
1006     if (fd < 0) {
1007         error("Cannot create/open file '%s'.", filename);
1008         return -1;
1009     }
1010
1011     if (write(fd, mem, size) != (ssize_t) size) {
1012         error("Cannot write to file '%s' %ld bytes.", filename, (long) size);
1013         close(fd);
1014         return -1;
1015     }
1016
1017     close(fd);
1018
1019     if (rename(tmpfilename, filename)) {
1020         error("Cannot rename '%s' to '%s'", tmpfilename, filename);
1021         return -1;
1022     }
1023
1024     return 0;
1025 }
1026
1027 int fd_is_valid(int fd) {
1028     return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
1029 }
1030
1031 pid_t gettid(void) {
1032 #ifdef __FreeBSD__
1033     return (pid_t)pthread_getthreadid_np();
1034 #elif defined(__APPLE__)
1035     uint64_t curthreadid;
1036     pthread_threadid_np(NULL, &curthreadid);
1037     return (pid_t)curthreadid;
1038 #else
1039     return (pid_t)syscall(SYS_gettid);
1040 #endif /* __FreeBSD__, __APPLE__*/
1041 }
1042
1043 char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
1044     char *s = fgets(buf, (int)buf_size, fp);
1045     if (!s) return NULL;
1046
1047     char *t = s;
1048     if (*t != '\0') {
1049         // find the string end
1050         while (*++t != '\0');
1051
1052         // trim trailing spaces/newlines/tabs
1053         while (--t > s && *t == '\n')
1054             *t = '\0';
1055     }
1056
1057     if (len)
1058         *len = t - s + 1;
1059
1060     return s;
1061 }
1062
1063 char *strncpyz(char *dst, const char *src, size_t n) {
1064     char *p = dst;
1065
1066     while (*src && n--)
1067         *dst++ = *src++;
1068
1069     *dst = '\0';
1070
1071     return p;
1072 }
1073
1074 int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
1075     int size = vsnprintf(dst, n, fmt, args);
1076
1077     if (unlikely((size_t) size > n)) {
1078         // truncated
1079         size = (int)n;
1080     }
1081
1082     dst[size] = '\0';
1083     return size;
1084 }
1085
1086 int snprintfz(char *dst, size_t n, const char *fmt, ...) {
1087     va_list args;
1088
1089     va_start(args, fmt);
1090     int ret = vsnprintfz(dst, n, fmt, args);
1091     va_end(args);
1092
1093     return ret;
1094 }
1095
1096 // ----------------------------------------------------------------------------
1097 // system functions
1098 // to retrieve settings of the system
1099
1100 int processors = 1;
1101 long get_system_cpus(void) {
1102     processors = 1;
1103
1104     #ifdef __APPLE__
1105         int32_t tmp_processors;
1106
1107         if (unlikely(GETSYSCTL("hw.logicalcpu", tmp_processors))) {
1108             error("Assuming system has %d processors.", processors);
1109         } else {
1110             processors = tmp_processors;
1111         }
1112
1113         return processors;
1114     #else
1115
1116     char filename[FILENAME_MAX + 1];
1117     snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
1118
1119     procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
1120     if(!ff) {
1121         error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
1122         return processors;
1123     }
1124
1125     ff = procfile_readall(ff);
1126     if(!ff) {
1127         error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
1128         return processors;
1129     }
1130
1131     processors = 0;
1132     unsigned int i;
1133     for(i = 0; i < procfile_lines(ff); i++) {
1134         if(!procfile_linewords(ff, i)) continue;
1135
1136         if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++;
1137     }
1138     processors--;
1139     if(processors < 1) processors = 1;
1140
1141     procfile_close(ff);
1142
1143     debug(D_SYSTEM, "System has %d processors.", processors);
1144     return processors;
1145
1146     #endif /* __APPLE__ */
1147 }
1148
1149 pid_t pid_max = 32768;
1150 pid_t get_system_pid_max(void) {
1151     #ifdef __APPLE__
1152         // As we currently do not know a solution to query pid_max from the os
1153         // we use the number defined in bsd/sys/proc_internal.h in XNU sources
1154         pid_max = 99999;
1155         return pid_max;
1156     #else
1157
1158     static char read = 0;
1159     if(unlikely(read)) return pid_max;
1160     read = 1;
1161
1162     char filename[FILENAME_MAX + 1];
1163     snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", global_host_prefix);
1164
1165     unsigned long long max = 0;
1166     if(read_single_number_file(filename, &max) != 0) {
1167         error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
1168         return pid_max;
1169     }
1170
1171     if(!max) {
1172         error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max);
1173         return pid_max;
1174     }
1175
1176     pid_max = (pid_t) max;
1177     return pid_max;
1178
1179     #endif /* __APPLE__ */
1180 }
1181
1182 unsigned int hz;
1183 void get_system_HZ(void) {
1184     long ticks;
1185
1186     if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
1187         error("Cannot get system clock ticks");
1188     }
1189
1190     hz = (unsigned int) ticks;
1191 }
1192
1193 /*
1194 // poor man cycle counting
1195 static unsigned long tsc;
1196 void begin_tsc(void) {
1197     unsigned long a, d;
1198     asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
1199     tsc = ((unsigned long)d << 32) | (unsigned long)a;
1200 }
1201 unsigned long end_tsc(void) {
1202     unsigned long a, d;
1203     asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
1204     return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
1205 }
1206 */