]> arthur.barton.de Git - netdata.git/blobdiff - src/common.c
dns_query_time plugin: replace "." with "_" in dimensions
[netdata.git] / src / common.c
index 64d50f636e9ec756d8f3fdf4558af39e74bdc82e..88fcf85bc2a981ec35270db4f7281118d46052fc 100644 (file)
@@ -1,9 +1,28 @@
 #include "common.h"
 
-char *global_host_prefix = "";
+#ifdef __APPLE__
+#define INHERIT_NONE 0
+#endif /* __APPLE__ */
+#if defined(__FreeBSD__) || defined(__APPLE__)
+#    define O_NOATIME     0
+#    define MADV_DONTFORK INHERIT_NONE
+#endif /* __FreeBSD__ || __APPLE__*/
+
+char *netdata_configured_hostname    = NULL;
+char *netdata_configured_config_dir  = NULL;
+char *netdata_configured_log_dir     = NULL;
+char *netdata_configured_plugins_dir = NULL;
+char *netdata_configured_web_dir     = NULL;
+char *netdata_configured_cache_dir   = NULL;
+char *netdata_configured_varlib_dir  = NULL;
+char *netdata_configured_home_dir    = NULL;
+char *netdata_configured_host_prefix = NULL;
+
 int enable_ksm = 1;
 
 volatile sig_atomic_t netdata_exit = 0;
+const char *os_type = NETDATA_OS_TYPE;
+const char *program_version = VERSION;
 
 // ----------------------------------------------------------------------------
 // memory allocation functions that handle failures
@@ -16,17 +35,15 @@ volatile sig_atomic_t netdata_exit = 0;
 
 #ifdef NETDATA_LOG_ALLOCATIONS
 static struct memory_statistics {
-    size_t malloc_calls_made;
-    size_t calloc_calls_made;
-    size_t realloc_calls_made;
-    size_t strdup_calls_made;
-    size_t free_calls_made;
-    size_t memory_calls_made;
-    size_t allocated_memory;
-    size_t mmapped_memory;
-} memory_statistics = {
-        0, 0, 0, 0, 0, 0, 0, 0
-};
+    volatile size_t malloc_calls_made;
+    volatile size_t calloc_calls_made;
+    volatile size_t realloc_calls_made;
+    volatile size_t strdup_calls_made;
+    volatile size_t free_calls_made;
+    volatile size_t memory_calls_made;
+    volatile size_t allocated_memory;
+    volatile size_t mmapped_memory;
+} memory_statistics;
 
 static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
     static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -48,37 +65,73 @@ static inline void print_allocations(const char *file, const char *function, con
 }
 
 static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+    // this is for debugging - we don't care locking it
     memory_statistics.memory_calls_made++;
     memory_statistics.malloc_calls_made++;
     memory_statistics.allocated_memory += size;
+#endif
     print_allocations(file, function, line);
 }
 
 static inline void mmap_accounting(size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+    __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST);
+#else
+    // this is for debugging - we don't care locking it
     memory_statistics.memory_calls_made++;
     memory_statistics.mmapped_memory += size;
+#endif
 }
 
 static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+    // this is for debugging - we don't care locking it
     memory_statistics.memory_calls_made++;
     memory_statistics.calloc_calls_made++;
     memory_statistics.allocated_memory += size;
+#endif
     print_allocations(file, function, line);
 }
 
 static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
     (void)ptr;
 
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+    // this is for debugging - we don't care locking it
     memory_statistics.memory_calls_made++;
     memory_statistics.realloc_calls_made++;
     memory_statistics.allocated_memory += size;
+#endif
     print_allocations(file, function, line);
 }
 
 static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
+    size_t size = strlen(s) + 1;
+
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST);
+    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+    // this is for debugging - we don't care locking it
     memory_statistics.memory_calls_made++;
     memory_statistics.strdup_calls_made++;
-    memory_statistics.allocated_memory += strlen(s) + 1;
+    memory_statistics.allocated_memory += size;
+#endif
     print_allocations(file, function, line);
 }
 
@@ -88,8 +141,14 @@ static inline void free_accounting(const char *file, const char *function, const
     (void)line;
 
     if(likely(ptr)) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+        __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+        __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST);
+#else
+        // this is for debugging - we don't care locking it
         memory_statistics.memory_calls_made++;
         memory_statistics.free_calls_made++;
+#endif
     }
 }
 #endif
@@ -152,27 +211,22 @@ void freez(void *ptr) {
     free(ptr);
 }
 
-// ----------------------------------------------------------------------------
-// time functions
-
-inline unsigned long long timeval_usec(struct timeval *tv) {
-    return tv->tv_sec * 1000000ULL + tv->tv_usec;
-}
+void json_escape_string(char *dst, const char *src, size_t size) {
+    const char *t;
+    char *d = dst, *e = &dst[size - 1];
 
-// time(NULL) in nanoseconds
-inline unsigned long long time_usec(void) {
-    struct timeval now;
-    gettimeofday(&now, NULL);
-    return timeval_usec(&now);
-}
+    for(t = src; *t && d < e ;t++) {
+        if(unlikely(*t == '\\' || *t == '"')) {
+            if(unlikely(d + 1 >= e)) break;
+            *d++ = '\\';
+        }
+        *d++ = *t;
+    }
 
-inline unsigned long long usec_dt(struct timeval *now, struct timeval *old) {
-    unsigned long long tv1 = timeval_usec(now);
-    unsigned long long tv2 = timeval_usec(old);
-    return (tv1 > tv2) ? (tv1 - tv2) : (tv2 - tv1);
+    *d = '\0';
 }
 
-int sleep_usec(unsigned long long usec) {
+int sleep_usec(usec_t usec) {
 
 #ifndef NETDATA_WITH_USLEEP
     // we expect microseconds (1.000.000 per second)
@@ -184,7 +238,7 @@ int sleep_usec(unsigned long long usec) {
 
     while (nanosleep(&req, &rem) == -1) {
         if (likely(errno == EINTR)) {
-            info("nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
+            debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
             req.tv_sec = rem.tv_sec;
             req.tv_nsec = rem.tv_nsec;
         } else {
@@ -764,7 +818,7 @@ uint32_t simple_hash(const char *name)
 }
 */
 
-
+/*
 // http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
 uint32_t simple_hash(const char *name) {
     unsigned char *s = (unsigned char *) name;
@@ -799,6 +853,7 @@ uint32_t simple_uhash(const char *name) {
     }
     return hval;
 }
+*/
 
 /*
 // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
@@ -824,11 +879,9 @@ uint32_t simple_hash(const char *name) {
 */
 
 void strreverse(char *begin, char *end) {
-    char aux;
-
     while (end > begin) {
         // clearer code.
-        aux = *end;
+        char aux = *end;
         *end-- = *begin;
         *begin++ = aux;
     }
@@ -861,15 +914,17 @@ char *trim(char *s) {
 }
 
 void *mymmap(const char *filename, size_t size, int flags, int ksm) {
+#ifndef MADV_MERGEABLE
+    (void)ksm;
+#endif
     static int log_madvise_1 = 1;
 #ifdef MADV_MERGEABLE
     static int log_madvise_2 = 1, log_madvise_3 = 1;
 #endif
-    int fd;
     void *mem = NULL;
 
     errno = 0;
-    fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
+    int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
     if (fd != -1) {
         if (lseek(fd, size, SEEK_SET) == (off_t) size) {
             if (write(fd, "", 1) == 1) {
@@ -988,7 +1043,15 @@ int fd_is_valid(int fd) {
 }
 
 pid_t gettid(void) {
+#ifdef __FreeBSD__
+    return (pid_t)pthread_getthreadid_np();
+#elif defined(__APPLE__)
+    uint64_t curthreadid;
+    pthread_threadid_np(NULL, &curthreadid);
+    return (pid_t)curthreadid;
+#else
     return (pid_t)syscall(SYS_gettid);
+#endif /* __FreeBSD__, __APPLE__*/
 }
 
 char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
@@ -1011,17 +1074,6 @@ char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
     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 = vsnprintf(dst, n, fmt, args);
 
@@ -1050,14 +1102,34 @@ int snprintfz(char *dst, size_t n, const char *fmt, ...) {
 
 int processors = 1;
 long get_system_cpus(void) {
-    procfile *ff = NULL;
-
     processors = 1;
 
+    #ifdef __APPLE__
+        int32_t tmp_processors;
+
+        if (unlikely(GETSYSCTL_BY_NAME("hw.logicalcpu", tmp_processors))) {
+            error("Assuming system has %d processors.", processors);
+        } else {
+            processors = tmp_processors;
+        }
+
+        return processors;
+    #elif __FreeBSD__
+        int32_t tmp_processors;
+
+        if (unlikely(GETSYSCTL_BY_NAME("hw.ncpu", tmp_processors))) {
+            error("Assuming system has %d processors.", processors);
+        } else {
+            processors = tmp_processors;
+        }
+
+        return processors;
+    #else
+
     char filename[FILENAME_MAX + 1];
-    snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
+    snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix);
 
-    ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
+    procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
     if(!ff) {
         error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
         return processors;
@@ -1081,39 +1153,54 @@ long get_system_cpus(void) {
 
     procfile_close(ff);
 
-    info("System has %d processors.", processors);
+    debug(D_SYSTEM, "System has %d processors.", processors);
     return processors;
+
+    #endif /* __APPLE__, __FreeBSD__ */
 }
 
 pid_t pid_max = 32768;
 pid_t get_system_pid_max(void) {
-    procfile *ff = NULL;
+    #ifdef __APPLE__
+        // As we currently do not know a solution to query pid_max from the os
+        // we use the number defined in bsd/sys/proc_internal.h in XNU sources
+        pid_max = 99999;
+        return pid_max;
+    #elif __FreeBSD__
+        int32_t tmp_pid_max;
+
+        if (unlikely(GETSYSCTL_BY_NAME("kern.pid_max", tmp_pid_max))) {
+            pid_max = 99999;
+            error("Assuming system's maximum pid is %d.", pid_max);
+        } else {
+            pid_max = tmp_pid_max;
+        }
 
-    char filename[FILENAME_MAX + 1];
-    snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", global_host_prefix);
-    ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
-    if(!ff) {
-        error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
         return pid_max;
-    }
+    #else
 
-    ff = procfile_readall(ff);
-    if(!ff) {
-        error("Cannot read file '%s'. Assuming system supports %d pids.", filename, pid_max);
+    static char read = 0;
+    if(unlikely(read)) return pid_max;
+    read = 1;
+
+    char filename[FILENAME_MAX + 1];
+    snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", netdata_configured_host_prefix);
+
+    unsigned long long max = 0;
+    if(read_single_number_file(filename, &max) != 0) {
+        error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
         return pid_max;
     }
 
-    pid_max = (pid_t)atoi(procfile_lineword(ff, 0, 0));
-    if(!pid_max) {
-        procfile_close(ff);
-        pid_max = 32768;
+    if(!max) {
         error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max);
         return pid_max;
     }
 
-    procfile_close(ff);
-    info("System supports %d pids.", pid_max);
+    pid_max = (pid_t) max;
     return pid_max;
+
+    #endif /* __APPLE__, __FreeBSD__ */
 }
 
 unsigned int hz;
@@ -1121,8 +1208,23 @@ void get_system_HZ(void) {
     long ticks;
 
     if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
-        perror("sysconf");
+        error("Cannot get system clock ticks");
     }
 
     hz = (unsigned int) ticks;
 }
+
+/*
+// poor man cycle counting
+static unsigned long tsc;
+void begin_tsc(void) {
+    unsigned long a, d;
+    asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
+    tsc = ((unsigned long)d << 32) | (unsigned long)a;
+}
+unsigned long end_tsc(void) {
+    unsigned long a, d;
+    asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
+    return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
+}
+*/