]> arthur.barton.de Git - netdata.git/blobdiff - src/common.c
handle usleep() on systems that do not accept more than 999999 usec; implement altern...
[netdata.git] / src / common.c
index 460c8d284f57f5819cd2a205871858cbeeb056fa..02d37ab675ccd8a8c7dba1a12e8f0bcfb9efeed2 100644 (file)
@@ -10,7 +10,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/mman.h>
-
+#include <time.h>
 
 #include "log.h"
 #include "common.h"
@@ -27,6 +27,51 @@ unsigned long long timems(void) {
        return now.tv_sec * 1000000ULL + now.tv_usec;
 }
 
+int usecsleep(unsigned long long usec) {
+
+#ifdef NETDATA_WITH_NANOSLEEP
+       // we expect microseconds (1.000.000 per second)
+       // but timespec is nanoseconds (1.000.000.000 per second)
+       struct timespec req = { .tv_sec = usec / 1000000, .tv_nsec = (usec % 1000000) * 1000 }, rem;
+
+       while(nanosleep(&req, &rem) == -1) {
+               error("nanosleep() failed for %llu microseconds.", usec);
+
+               if(likely(errno == EINTR)) {
+                       req.tv_sec = rem.tv_sec;
+                       req.tv_nsec = rem.tv_nsec;
+               }
+               else {
+                       error("Cannot nanosleep() for %llu microseconds.", usec);
+                       break;
+               }
+       }
+
+       return 0;
+#else
+       int ret = usleep(usec);
+       if(unlikely(ret == -1 && errno == EINVAL)) {
+               // on certain systems, usec has to be up to 999999
+               if(usec > 999999) {
+                       int counter = usec / 999999;
+                       while(counter--)
+                               usleep(999999);
+
+                       usleep(usec % 999999);
+               }
+               else {
+                       error("Cannot usleep() for %llu microseconds.", usec);
+                       return ret;
+               }
+       }
+
+       if(ret != 0)
+               error("usleep() failed for %llu microseconds.", usec);
+
+       return ret;
+#endif
+}
+
 unsigned char netdata_map_chart_names[256] = {
                [0] = '\0', //
                [1] = '_', //
@@ -596,6 +641,19 @@ uint32_t simple_hash(const char *name) {
        return hval;
 }
 
+uint32_t simple_uhash(const char *name) {
+       unsigned char *s = (unsigned char *)name;
+       uint32_t hval = 0x811c9dc5, c;
+
+       // FNV-1a algorithm
+       while((c = *s++)) {
+               if(unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
+               hval *= 16777619;
+               hval ^= c;
+       }
+       return hval;
+}
+
 /*
 // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
 // one at a time hash
@@ -669,16 +727,16 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm)
        errno = 0;
        fd = open(filename, O_RDWR|O_CREAT|O_NOATIME, 0664);
        if(fd != -1) {
-               if(lseek(fd, size, SEEK_SET) == (long)size) {
+               if(lseek(fd, size, SEEK_SET) == (off_t)size) {
                        if(write(fd, "", 1) == 1) {
                                if(ftruncate(fd, size))
-                                       error("Cannot truncate file '%s' to size %ld. Will use the larger file.", filename, size);
+                                       error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
 
 #ifdef MADV_MERGEABLE
                                if(flags & MAP_SHARED || !enable_ksm || !ksm) {
 #endif
                                        mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
-                                       if(mem) {
+                                       if(mem != MAP_FAILED) {
                                                int advise = MADV_SEQUENTIAL|MADV_DONTFORK;
                                                if(flags & MAP_SHARED) advise |= MADV_WILLNEED;
 
@@ -688,7 +746,9 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm)
 #ifdef MADV_MERGEABLE
                                }
                                else {
-                                       mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags|MAP_ANONYMOUS, -1, 0);
+/*
+                                       // test - load the file into memory
+                                       mem = calloc(1, size);
                                        if(mem) {
                                                if(lseek(fd, 0, SEEK_SET) == 0) {
                                                        if(read(fd, mem, size) != (ssize_t)size)
@@ -696,6 +756,16 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm)
                                                }
                                                else
                                                        error("Cannot seek to beginning of file '%s'.", filename);
+                                       }
+*/
+                                       mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags|MAP_ANONYMOUS, -1, 0);
+                                       if(mem != MAP_FAILED) {
+                                               if(lseek(fd, 0, SEEK_SET) == 0) {
+                                                       if(read(fd, mem, size) != (ssize_t)size)
+                                                               error("Cannot read from file '%s'", filename);
+                                               }
+                                               else
+                                                       error("Cannot seek to beginning of file '%s'.", filename);
 
                                                // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
                                                if(madvise(mem, size, MADV_SEQUENTIAL|MADV_DONTFORK) != 0)
@@ -709,9 +779,9 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm)
                                }
 #endif
                        }
-                       else error("Cannot write to file '%s' at position %ld.", filename, size);
+                       else error("Cannot write to file '%s' at position %zu.", filename, size);
                }
-               else error("Cannot seek file '%s' to size %ld.", filename, size);
+               else error("Cannot seek file '%s' to size %zu.", filename, size);
 
                close(fd);
        }
@@ -720,7 +790,7 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm)
        return mem;
 }
 
-int savememory(const char *filename, void *mem, unsigned long size)
+int savememory(const char *filename, void *mem, size_t size)
 {
        char tmpfilename[FILENAME_MAX + 1];
 
@@ -732,7 +802,7 @@ int savememory(const char *filename, void *mem, unsigned long size)
                return -1;
        }
 
-       if(write(fd, mem, size) != (long)size) {
+       if(write(fd, mem, size) != (ssize_t)size) {
                error("Cannot write to file '%s' %ld bytes.", filename, (long)size);
                close(fd);
                return -1;
@@ -740,13 +810,12 @@ int savememory(const char *filename, void *mem, unsigned long size)
 
        close(fd);
 
-       int ret = 0;
        if(rename(tmpfilename, filename)) {
                error("Cannot rename '%s' to '%s'", tmpfilename, filename);
-               ret = -1;
+               return -1;
        }
 
-       return ret;
+       return 0;
 }
 
 int fd_is_valid(int fd) {
@@ -776,31 +845,59 @@ pid_t gettid(void)
        return syscall(SYS_gettid);
 }
 
-char *strncpyz(char *dest, const char *src, size_t n)
-{
-  char *p = dest;
+char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
+       char *s = fgets(buf, buf_size, fp);
+       if(!s) return NULL;
+
+       char *t = s;
+       if(*t != '\0') {
+               // find the string end
+               while (*++t != '\0');
+
+               // trim trailing spaces/newlines/tabs
+               while (--t > s && *t == '\n')
+                       *t = '\0';
+       }
+
+       if(len)
+               *len = t - s + 1;
+
+       return s;
+}
+
+char *strncpyz(char *dst, const char *src, size_t n) {
+       char *p = dst;
+
+       while(*src && n--)
+               *dst++ = *src++;
 
-       while (*src && n--)
-               *dest++ = *src++;
-  *dest = '\0';
+       *dst = '\0';
 
        return p;
 }
 
-int vsnprintfz(char *sout, size_t n, const char *fmt, va_list args)
-{
+int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
        int size;
 
-  size = vsnprintf(sout, n, fmt, args);
-  sout[size] = '\0';
-  return size;
+       size = vsnprintf(dst, n, fmt, args);
+
+       if(unlikely((size_t)size > n)) {
+               // there is bug in vsnprintf() and it returns
+               // a number higher to len, but it does not
+               // overflow the buffer.
+               size = n;
+       }
+
+       dst[size] = '\0';
+       return size;
 }
 
-int snprintfz(char *sout, size_t n, const char *fmt, ...)
-{
+int snprintfz(char *dst, size_t n, const char *fmt, ...) {
        va_list args;
 
        va_start(args, fmt);
-       return vsnprintfz(sout, n, fmt, args);
-  // args will vanish!
+       int ret = vsnprintfz(dst, n, fmt, args);
+       va_end(args);
+
+       return ret;
 }