#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
-
+#include <time.h>
#include "log.h"
#include "common.h"
char *global_host_prefix = "";
int enable_ksm = 1;
+// time(NULL) in milliseconds
+unsigned long long timems(void) {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ 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] = '_', //
// FNV-1a algorithm
while (*s) {
// multiply by the 32 bit FNV magic prime mod 2^32
- // gcc optimized
- hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+ // NOTE: No need to optimize with left shifts.
+ // GCC will use imul instruction anyway.
+ // Tested with 'gcc -O3 -S'
+ //hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+ hval *= 16777619;
// xor the bottom with the current octet
hval ^= (uint32_t)*s++;
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
void strreverse(char* begin, char* end)
{
- char aux;
- while (end > begin)
- aux = *end, *end-- = *begin, *begin++ = aux;
+ char aux;
+
+ while (end > begin)
+ {
+ // clearer code.
+ aux = *end;
+ *end-- = *begin;
+ *begin++ = aux;
+ }
}
char *mystrsep(char **ptr, char *s)
char *trim(char *s)
{
// skip leading spaces
+ // and 'comments' as well!?
while(*s && isspace(*s)) s++;
if(!*s || *s == '#') return NULL;
// skip tailing spaces
- long c = (long) strlen(s) - 1;
- while(c >= 0 && isspace(s[c])) {
- s[c] = '\0';
- c--;
+ // this way is way faster. Writes only one NUL char.
+ ssize_t l = strlen(s);
+ if (--l >= 0)
+ {
+ char *p = s + l;
+ while (p > s && isspace(*p)) p--;
+ *++p = '\0';
}
- if(c < 0) return NULL;
+
if(!*s) return NULL;
+
return s;
}
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;
#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)
}
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)
}
#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);
}
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];
- snprintf(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long)getpid());
+ snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long)getpid());
int fd = open(tmpfilename, O_RDWR|O_CREAT|O_NOATIME, 0664);
if(fd < 0) {
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;
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) {
return syscall(SYS_gettid);
}
+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++;
+
+ *dst = '\0';
+
+ return p;
+}
+
+int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
+ int 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 *dst, size_t n, const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ int ret = vsnprintfz(dst, n, fmt, args);
+ va_end(args);
+
+ return ret;
+}