]> arthur.barton.de Git - netdata.git/blob - src/common.c
63fed585111b98e3a326cf417ccdf286aa473b73
[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                                 if(flags & MAP_SHARED || !enable_ksm || !ksm) {
126                                         mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
127                                         if(mem) {
128                                                 int advise = MADV_SEQUENTIAL|MADV_DONTFORK;
129                                                 if(flags & MAP_SHARED) advise |= MADV_WILLNEED;
130
131                                                 if(madvise(mem, size, advise) != 0)
132                                                         error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
133                                         }
134                                 }
135                                 else {
136                                         mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags|MAP_ANONYMOUS, -1, 0);
137                                         if(mem) {
138                                                 if(lseek(fd, 0, SEEK_SET) == 0) {
139                                                         if(read(fd, mem, size) != size)
140                                                                 error("Cannot read from file '%s'", filename);
141                                                 }
142                                                 else
143                                                         error("Cannot seek to beginning of file '%s'.", filename);
144
145                                                 // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
146                                                 if(madvise(mem, size, MADV_MERGEABLE) != 0)
147                                                         error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
148                                         }
149                                         else
150                                                 error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
151                                 }
152                         }
153                         else error("Cannot write to file '%s' at position %ld.", filename, size);
154                 }
155                 else error("Cannot seek file '%s' to size %ld.", filename, size);
156
157                 close(fd);
158         }
159         else error("Cannot create/open file '%s'.", filename);
160
161         return mem;
162 }
163
164 int savememory(const char *filename, void *mem, unsigned long size)
165 {
166         char tmpfilename[FILENAME_MAX + 1];
167
168         snprintf(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long)getpid());
169
170         int fd = open(tmpfilename, O_RDWR|O_CREAT|O_NOATIME, 0664);
171         if(fd < 0) {
172                 error("Cannot create/open file '%s'.", filename);
173                 return -1;
174         }
175
176         if(write(fd, mem, size) != (long)size) {
177                 error("Cannot write to file '%s' %ld bytes.", filename, (long)size);
178                 close(fd);
179                 return -1;
180         }
181
182         close(fd);
183
184         int ret = 0;
185         if(rename(tmpfilename, filename)) {
186                 error("Cannot rename '%s' to '%s'", tmpfilename, filename);
187                 ret = -1;
188         }
189
190         return ret;
191 }
192
193 int fd_is_valid(int fd) {
194     return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
195 }
196
197 /*
198  ***************************************************************************
199  * Get number of clock ticks per second.
200  ***************************************************************************
201  */
202 unsigned int hz;
203
204 void get_HZ(void)
205 {
206         long ticks;
207
208         if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
209                 perror("sysconf");
210         }
211
212         hz = (unsigned int) ticks;
213 }
214
215 pid_t gettid(void)
216 {
217         return syscall(SYS_gettid);
218 }
219