]> arthur.barton.de Git - netdata.git/blob - src/common.c
bf713195e1b1602a34e902d0cbc70b96b4561479
[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
19 char *global_host_prefix = "";
20 int enable_ksm = 1;
21
22 /*
23 // http://stackoverflow.com/questions/7666509/hash-function-for-string
24 uint32_t simple_hash(const char *name)
25 {
26         const char *s = name;
27         uint32_t hash = 5381;
28         int i;
29
30         while((i = *s++)) hash = ((hash << 5) + hash) + i;
31
32         // fprintf(stderr, "HASH: %lu %s\n", hash, name);
33
34         return hash;
35 }
36 */
37
38
39 // http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
40 uint32_t simple_hash(const char *name) {
41         unsigned char *s = (unsigned char *)name;
42         uint32_t hval = 0x811c9dc5;
43
44         // FNV-1a algorithm
45         while (*s) {
46                 // multiply by the 32 bit FNV magic prime mod 2^32
47                 // gcc optimized
48                 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
49
50                 // xor the bottom with the current octet
51                 hval ^= (uint32_t)*s++;
52         }
53
54         // fprintf(stderr, "HASH: %u = %s\n", hval, name);
55         return hval;
56 }
57
58 /*
59 // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
60 // one at a time hash
61 uint32_t simple_hash(const char *name) {
62         unsigned char *s = (unsigned char *)name;
63         uint32_t h = 0;
64
65         while(*s) {
66                 h += *s++;
67                 h += (h << 10);
68                 h ^= (h >> 6);
69         }
70
71         h += (h << 3);
72         h ^= (h >> 11);
73         h += (h << 15);
74
75         // fprintf(stderr, "HASH: %u = %s\n", h, name);
76
77         return h;
78 }
79 */
80
81 void strreverse(char* begin, char* end)
82 {
83     char aux;
84     while (end > begin)
85         aux = *end, *end-- = *begin, *begin++ = aux;
86 }
87
88 char *mystrsep(char **ptr, char *s)
89 {
90         char *p = "";
91         while ( p && !p[0] && *ptr ) p = strsep(ptr, s);
92         return(p);
93 }
94
95 char *trim(char *s)
96 {
97         // skip leading spaces
98         while(*s && isspace(*s)) s++;
99         if(!*s || *s == '#') return NULL;
100
101         // skip tailing spaces
102         int c = strlen(s) - 1;
103         while(c >= 0 && isspace(s[c])) {
104                 s[c] = '\0';
105                 c--;
106         }
107         if(c < 0) return NULL;
108         if(!*s) return NULL;
109         return s;
110 }
111
112 void *mymmap(const char *filename, unsigned long size, int flags, int ksm)
113 {
114         int fd;
115         void *mem = NULL;
116
117         errno = 0;
118         fd = open(filename, O_RDWR|O_CREAT|O_NOATIME, 0664);
119         if(fd != -1) {
120                 if(lseek(fd, size, SEEK_SET) == (long)size) {
121                         if(write(fd, "", 1) == 1) {
122                                 if(ftruncate(fd, size))
123                                         error("Cannot truncate file '%s' to size %ld. Will use the larger file.", filename, size);
124
125 #ifdef MADV_MERGEABLE
126                                 if(flags & MAP_SHARED || !enable_ksm || !ksm) {
127 #endif
128                                         mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
129                                         if(mem) {
130                                                 int advise = MADV_SEQUENTIAL|MADV_DONTFORK;
131                                                 if(flags & MAP_SHARED) advise |= MADV_WILLNEED;
132
133                                                 if(madvise(mem, size, advise) != 0)
134                                                         error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
135                                         }
136 #ifdef MADV_MERGEABLE
137                                 }
138                                 else {
139                                         mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags|MAP_ANONYMOUS, -1, 0);
140                                         if(mem) {
141                                                 if(lseek(fd, 0, SEEK_SET) == 0) {
142                                                         if(read(fd, mem, size) != size)
143                                                                 error("Cannot read from file '%s'", filename);
144                                                 }
145                                                 else
146                                                         error("Cannot seek to beginning of file '%s'.", filename);
147
148                                                 // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
149                                                 if(madvise(mem, size, MADV_MERGEABLE) != 0)
150                                                         error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
151                                         }
152                                         else
153                                                 error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
154                                 }
155 #endif
156                         }
157                         else error("Cannot write to file '%s' at position %ld.", filename, size);
158                 }
159                 else error("Cannot seek file '%s' to size %ld.", filename, size);
160
161                 close(fd);
162         }
163         else error("Cannot create/open file '%s'.", filename);
164
165         return mem;
166 }
167
168 int savememory(const char *filename, void *mem, unsigned long size)
169 {
170         char tmpfilename[FILENAME_MAX + 1];
171
172         snprintf(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long)getpid());
173
174         int fd = open(tmpfilename, O_RDWR|O_CREAT|O_NOATIME, 0664);
175         if(fd < 0) {
176                 error("Cannot create/open file '%s'.", filename);
177                 return -1;
178         }
179
180         if(write(fd, mem, size) != (long)size) {
181                 error("Cannot write to file '%s' %ld bytes.", filename, (long)size);
182                 close(fd);
183                 return -1;
184         }
185
186         close(fd);
187
188         int ret = 0;
189         if(rename(tmpfilename, filename)) {
190                 error("Cannot rename '%s' to '%s'", tmpfilename, filename);
191                 ret = -1;
192         }
193
194         return ret;
195 }
196
197 int fd_is_valid(int fd) {
198     return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
199 }
200
201 /*
202  ***************************************************************************
203  * Get number of clock ticks per second.
204  ***************************************************************************
205  */
206 unsigned int hz;
207
208 void get_HZ(void)
209 {
210         long ticks;
211
212         if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
213                 perror("sysconf");
214         }
215
216         hz = (unsigned int) ticks;
217 }
218
219 pid_t gettid(void)
220 {
221         return syscall(SYS_gettid);
222 }
223