]> arthur.barton.de Git - netdata.git/blob - src/common.c
cb74b6335c2d0dbd65d3af7dfea63b1cffb6e2a1
[netdata.git] / src / common.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 #include <sys/syscall.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <sys/mman.h>
13
14
15 #include "log.h"
16 #include "common.h"
17 #include "appconfig.h"
18 #include "../config.h"
19
20 char *global_host_prefix = "";
21 int enable_ksm = 1;
22
23 unsigned char netdata_keys_map[256] = {
24                 [0] = '\0', //
25                 [1] = '_', //
26                 [2] = '_', //
27                 [3] = '_', //
28                 [4] = '_', //
29                 [5] = '_', //
30                 [6] = '_', //
31                 [7] = '_', //
32                 [8] = '_', //
33                 [9] = '_', //
34                 [10] = '_', //
35                 [11] = '_', //
36                 [12] = '_', //
37                 [13] = '_', //
38                 [14] = '_', //
39                 [15] = '_', //
40                 [16] = '_', //
41                 [17] = '_', //
42                 [18] = '_', //
43                 [19] = '_', //
44                 [20] = '_', //
45                 [21] = '_', //
46                 [22] = '_', //
47                 [23] = '_', //
48                 [24] = '_', //
49                 [25] = '_', //
50                 [26] = '_', //
51                 [27] = '_', //
52                 [28] = '_', //
53                 [29] = '_', //
54                 [30] = '_', //
55                 [31] = '_', //
56                 [32] = '_', //
57                 [33] = '_', // !
58                 [34] = '_', // "
59                 [35] = '_', // #
60                 [36] = '_', // $
61                 [37] = '_', // %
62                 [38] = '_', // &
63                 [39] = '_', // '
64                 [40] = '_', // (
65                 [41] = '_', // )
66                 [42] = '_', // *
67                 [43] = '_', // +
68                 [44] = '.', // ,
69                 [45] = '-', // -
70                 [46] = '.', // .
71                 [47] = '/', // /
72                 [48] = '0', // 0
73                 [49] = '1', // 1
74                 [50] = '2', // 2
75                 [51] = '3', // 3
76                 [52] = '4', // 4
77                 [53] = '5', // 5
78                 [54] = '6', // 6
79                 [55] = '7', // 7
80                 [56] = '8', // 8
81                 [57] = '9', // 9
82                 [58] = '_', // :
83                 [59] = '_', // ;
84                 [60] = '_', // <
85                 [61] = '_', // =
86                 [62] = '_', // >
87                 [63] = '_', // ?
88                 [64] = '_', // @
89                 [65] = 'a', // A
90                 [66] = 'b', // B
91                 [67] = 'c', // C
92                 [68] = 'd', // D
93                 [69] = 'e', // E
94                 [70] = 'f', // F
95                 [71] = 'g', // G
96                 [72] = 'h', // H
97                 [73] = 'i', // I
98                 [74] = 'j', // J
99                 [75] = 'k', // K
100                 [76] = 'l', // L
101                 [77] = 'm', // M
102                 [78] = 'n', // N
103                 [79] = 'o', // O
104                 [80] = 'p', // P
105                 [81] = 'q', // Q
106                 [82] = 'r', // R
107                 [83] = 's', // S
108                 [84] = 't', // T
109                 [85] = 'u', // U
110                 [86] = 'v', // V
111                 [87] = 'w', // W
112                 [88] = 'x', // X
113                 [89] = 'y', // Y
114                 [90] = 'z', // Z
115                 [91] = '_', // [
116                 [92] = '/', // backslash
117                 [93] = '_', // ]
118                 [94] = '_', // ^
119                 [95] = '_', // _
120                 [96] = '_', // `
121                 [97] = 'a', // a
122                 [98] = 'b', // b
123                 [99] = 'c', // c
124                 [100] = 'd', // d
125                 [101] = 'e', // e
126                 [102] = 'f', // f
127                 [103] = 'g', // g
128                 [104] = 'h', // h
129                 [105] = 'i', // i
130                 [106] = 'j', // j
131                 [107] = 'k', // k
132                 [108] = 'l', // l
133                 [109] = 'm', // m
134                 [110] = 'n', // n
135                 [111] = 'o', // o
136                 [112] = 'p', // p
137                 [113] = 'q', // q
138                 [114] = 'r', // r
139                 [115] = 's', // s
140                 [116] = 't', // t
141                 [117] = 'u', // u
142                 [118] = 'v', // v
143                 [119] = 'w', // w
144                 [120] = 'x', // x
145                 [121] = 'y', // y
146                 [122] = 'z', // z
147                 [123] = '_', // {
148                 [124] = '_', // |
149                 [125] = '_', // }
150                 [126] = '_', // ~
151                 [127] = '_', //
152                 [128] = '_', //
153                 [129] = '_', //
154                 [130] = '_', //
155                 [131] = '_', //
156                 [132] = '_', //
157                 [133] = '_', //
158                 [134] = '_', //
159                 [135] = '_', //
160                 [136] = '_', //
161                 [137] = '_', //
162                 [138] = '_', //
163                 [139] = '_', //
164                 [140] = '_', //
165                 [141] = '_', //
166                 [142] = '_', //
167                 [143] = '_', //
168                 [144] = '_', //
169                 [145] = '_', //
170                 [146] = '_', //
171                 [147] = '_', //
172                 [148] = '_', //
173                 [149] = '_', //
174                 [150] = '_', //
175                 [151] = '_', //
176                 [152] = '_', //
177                 [153] = '_', //
178                 [154] = '_', //
179                 [155] = '_', //
180                 [156] = '_', //
181                 [157] = '_', //
182                 [158] = '_', //
183                 [159] = '_', //
184                 [160] = '_', //
185                 [161] = '_', //
186                 [162] = '_', //
187                 [163] = '_', //
188                 [164] = '_', //
189                 [165] = '_', //
190                 [166] = '_', //
191                 [167] = '_', //
192                 [168] = '_', //
193                 [169] = '_', //
194                 [170] = '_', //
195                 [171] = '_', //
196                 [172] = '_', //
197                 [173] = '_', //
198                 [174] = '_', //
199                 [175] = '_', //
200                 [176] = '_', //
201                 [177] = '_', //
202                 [178] = '_', //
203                 [179] = '_', //
204                 [180] = '_', //
205                 [181] = '_', //
206                 [182] = '_', //
207                 [183] = '_', //
208                 [184] = '_', //
209                 [185] = '_', //
210                 [186] = '_', //
211                 [187] = '_', //
212                 [188] = '_', //
213                 [189] = '_', //
214                 [190] = '_', //
215                 [191] = '_', //
216                 [192] = '_', //
217                 [193] = '_', //
218                 [194] = '_', //
219                 [195] = '_', //
220                 [196] = '_', //
221                 [197] = '_', //
222                 [198] = '_', //
223                 [199] = '_', //
224                 [200] = '_', //
225                 [201] = '_', //
226                 [202] = '_', //
227                 [203] = '_', //
228                 [204] = '_', //
229                 [205] = '_', //
230                 [206] = '_', //
231                 [207] = '_', //
232                 [208] = '_', //
233                 [209] = '_', //
234                 [210] = '_', //
235                 [211] = '_', //
236                 [212] = '_', //
237                 [213] = '_', //
238                 [214] = '_', //
239                 [215] = '_', //
240                 [216] = '_', //
241                 [217] = '_', //
242                 [218] = '_', //
243                 [219] = '_', //
244                 [220] = '_', //
245                 [221] = '_', //
246                 [222] = '_', //
247                 [223] = '_', //
248                 [224] = '_', //
249                 [225] = '_', //
250                 [226] = '_', //
251                 [227] = '_', //
252                 [228] = '_', //
253                 [229] = '_', //
254                 [230] = '_', //
255                 [231] = '_', //
256                 [232] = '_', //
257                 [233] = '_', //
258                 [234] = '_', //
259                 [235] = '_', //
260                 [236] = '_', //
261                 [237] = '_', //
262                 [238] = '_', //
263                 [239] = '_', //
264                 [240] = '_', //
265                 [241] = '_', //
266                 [242] = '_', //
267                 [243] = '_', //
268                 [244] = '_', //
269                 [245] = '_', //
270                 [246] = '_', //
271                 [247] = '_', //
272                 [248] = '_', //
273                 [249] = '_', //
274                 [250] = '_', //
275                 [251] = '_', //
276                 [252] = '_', //
277                 [253] = '_', //
278                 [254] = '_', //
279                 [255] = '_'  //
280 };
281
282 // make sure the supplied string
283 // is good for a netdata chart/dimension ID/NAME
284 void netdata_fix_id(char *s) {
285         while((*s = netdata_keys_map[(unsigned char)*s])) s++;
286 }
287
288 /*
289 // http://stackoverflow.com/questions/7666509/hash-function-for-string
290 uint32_t simple_hash(const char *name)
291 {
292         const char *s = name;
293         uint32_t hash = 5381;
294         int i;
295
296         while((i = *s++)) hash = ((hash << 5) + hash) + i;
297
298         // fprintf(stderr, "HASH: %lu %s\n", hash, name);
299
300         return hash;
301 }
302 */
303
304
305 // http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
306 uint32_t simple_hash(const char *name) {
307         unsigned char *s = (unsigned char *)name;
308         uint32_t hval = 0x811c9dc5;
309
310         // FNV-1a algorithm
311         while (*s) {
312                 // multiply by the 32 bit FNV magic prime mod 2^32
313                 // gcc optimized
314                 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
315
316                 // xor the bottom with the current octet
317                 hval ^= (uint32_t)*s++;
318         }
319
320         // fprintf(stderr, "HASH: %u = %s\n", hval, name);
321         return hval;
322 }
323
324 /*
325 // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
326 // one at a time hash
327 uint32_t simple_hash(const char *name) {
328         unsigned char *s = (unsigned char *)name;
329         uint32_t h = 0;
330
331         while(*s) {
332                 h += *s++;
333                 h += (h << 10);
334                 h ^= (h >> 6);
335         }
336
337         h += (h << 3);
338         h ^= (h >> 11);
339         h += (h << 15);
340
341         // fprintf(stderr, "HASH: %u = %s\n", h, name);
342
343         return h;
344 }
345 */
346
347 void strreverse(char* begin, char* end)
348 {
349     char aux;
350     while (end > begin)
351         aux = *end, *end-- = *begin, *begin++ = aux;
352 }
353
354 char *mystrsep(char **ptr, char *s)
355 {
356         char *p = "";
357         while ( p && !p[0] && *ptr ) p = strsep(ptr, s);
358         return(p);
359 }
360
361 char *trim(char *s)
362 {
363         // skip leading spaces
364         while(*s && isspace(*s)) s++;
365         if(!*s || *s == '#') return NULL;
366
367         // skip tailing spaces
368         long c = (long) strlen(s) - 1;
369         while(c >= 0 && isspace(s[c])) {
370                 s[c] = '\0';
371                 c--;
372         }
373         if(c < 0) return NULL;
374         if(!*s) return NULL;
375         return s;
376 }
377
378 void *mymmap(const char *filename, size_t size, int flags, int ksm)
379 {
380         int fd;
381         void *mem = NULL;
382
383         errno = 0;
384         fd = open(filename, O_RDWR|O_CREAT|O_NOATIME, 0664);
385         if(fd != -1) {
386                 if(lseek(fd, size, SEEK_SET) == (long)size) {
387                         if(write(fd, "", 1) == 1) {
388                                 if(ftruncate(fd, size))
389                                         error("Cannot truncate file '%s' to size %ld. Will use the larger file.", filename, size);
390
391 #ifdef MADV_MERGEABLE
392                                 if(flags & MAP_SHARED || !enable_ksm || !ksm) {
393 #endif
394                                         mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
395                                         if(mem) {
396                                                 int advise = MADV_SEQUENTIAL|MADV_DONTFORK;
397                                                 if(flags & MAP_SHARED) advise |= MADV_WILLNEED;
398
399                                                 if(madvise(mem, size, advise) != 0)
400                                                         error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
401                                         }
402 #ifdef MADV_MERGEABLE
403                                 }
404                                 else {
405                                         mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags|MAP_ANONYMOUS, -1, 0);
406                                         if(mem) {
407                                                 if(lseek(fd, 0, SEEK_SET) == 0) {
408                                                         if(read(fd, mem, size) != (ssize_t)size)
409                                                                 error("Cannot read from file '%s'", filename);
410                                                 }
411                                                 else
412                                                         error("Cannot seek to beginning of file '%s'.", filename);
413
414                                                 // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
415                                                 if(madvise(mem, size, MADV_SEQUENTIAL|MADV_DONTFORK) != 0)
416                                                         error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.", filename);
417
418                                                 if(madvise(mem, size, MADV_MERGEABLE) != 0)
419                                                         error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.", filename);
420                                         }
421                                         else
422                                                 error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
423                                 }
424 #endif
425                         }
426                         else error("Cannot write to file '%s' at position %ld.", filename, size);
427                 }
428                 else error("Cannot seek file '%s' to size %ld.", filename, size);
429
430                 close(fd);
431         }
432         else error("Cannot create/open file '%s'.", filename);
433
434         return mem;
435 }
436
437 int savememory(const char *filename, void *mem, unsigned long size)
438 {
439         char tmpfilename[FILENAME_MAX + 1];
440
441         snprintf(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long)getpid());
442
443         int fd = open(tmpfilename, O_RDWR|O_CREAT|O_NOATIME, 0664);
444         if(fd < 0) {
445                 error("Cannot create/open file '%s'.", filename);
446                 return -1;
447         }
448
449         if(write(fd, mem, size) != (long)size) {
450                 error("Cannot write to file '%s' %ld bytes.", filename, (long)size);
451                 close(fd);
452                 return -1;
453         }
454
455         close(fd);
456
457         int ret = 0;
458         if(rename(tmpfilename, filename)) {
459                 error("Cannot rename '%s' to '%s'", tmpfilename, filename);
460                 ret = -1;
461         }
462
463         return ret;
464 }
465
466 int fd_is_valid(int fd) {
467     return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
468 }
469
470 /*
471  ***************************************************************************
472  * Get number of clock ticks per second.
473  ***************************************************************************
474  */
475 unsigned int hz;
476
477 void get_HZ(void)
478 {
479         long ticks;
480
481         if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
482                 perror("sysconf");
483         }
484
485         hz = (unsigned int) ticks;
486 }
487
488 pid_t gettid(void)
489 {
490         return syscall(SYS_gettid);
491 }
492