]> arthur.barton.de Git - netdata.git/commitdiff
Merge pull request #1362 from deltaskelta/master
authorCosta Tsaousis <costa@tsaousis.gr>
Tue, 13 Dec 2016 20:00:32 +0000 (22:00 +0200)
committerGitHub <noreply@github.com>
Tue, 13 Dec 2016 20:00:32 +0000 (22:00 +0200)
Changed ExecutableService check() to split properly

59 files changed:
CMakeLists.txt
conf.d/health_alarm_notify.conf
conf.d/python.d/mysql.conf
configs.signatures
configure.ac
plugins.d/alarm-notify.sh
src/Makefile.am
src/apps_plugin.c
src/backends.c
src/clocks.c [new file with mode: 0644]
src/clocks.h [new file with mode: 0644]
src/common.c
src/common.h
src/eval.c
src/freebsd_sysctl.c
src/health.c
src/ipc.c
src/ipc.h
src/log.c
src/plugin_checks.c
src/plugin_freebsd.c
src/plugin_freebsd.h
src/plugin_idlejitter.c
src/plugin_nfacct.c
src/plugin_proc.c
src/plugin_proc.h
src/plugins_d.c
src/proc_diskstats.c
src/proc_interrupts.c
src/proc_loadavg.c
src/proc_meminfo.c
src/proc_net_dev.c
src/proc_net_ip_vs_stats.c
src/proc_net_netstat.c
src/proc_net_rpc_nfs.c
src/proc_net_rpc_nfsd.c
src/proc_net_snmp.c
src/proc_net_snmp6.c
src/proc_net_softnet_stat.c
src/proc_net_stat_conntrack.c
src/proc_net_stat_synproxy.c
src/proc_self_mountinfo.c
src/proc_self_mountinfo.h
src/proc_softirqs.c
src/proc_stat.c
src/proc_sys_kernel_random_entropy_avail.c
src/proc_vmstat.c
src/registry.c
src/rrd.c
src/rrd.h
src/rrd2json.c
src/sys_fs_cgroup.c
src/sys_kernel_mm_ksm.c
src/unit_test.c
src/web_buffer.c
src/web_buffer.h
src/web_client.c
web/demosites.html
web/index.html

index 79a3cc3f17061beee76e5521456627374aff1c75..d58e66cbe0ee67dde922cb18f750fb6d4a0d8195 100755 (executable)
@@ -16,6 +16,8 @@ set(NETDATA_SOURCE_FILES
         src/avl.h
         src/backends.c
         src/backends.h
+        src/clocks.c
+        src/clocks.h
         src/common.c
         src/common.h
         src/daemon.c
index 33a752f9ed31f6e663b55246e69c3088faf94635..aa73c948a1b56957d021274eeb7f3345d6bbd0a2 100644 (file)
@@ -16,7 +16,7 @@
 # This file is a BASH script itself.
 #
 #
-###############################################################################
+#------------------------------------------------------------------------------
 # proxy configuration
 #
 # If you need to send curl based notifications (pushover, pushbullet, slack,
@@ -25,7 +25,7 @@
 #export https_proxy="http://10.0.0.1:3128/"
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # notifications images
 #
 # Images in notifications need to be downloaded from an Internet facing site.
@@ -37,7 +37,7 @@
 #images_base_url="http://my.public.netdata.server:19999"
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # external commands
 
 # The full path to the sendmail command.
@@ -52,7 +52,7 @@ sendmail=""
 curl=""
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # NOTE ABOUT RECIPIENTS
 #
 # When you define recipients (all types):
@@ -80,7 +80,7 @@ curl=""
 # This works for all notification methods (including the default recipients).
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # email global notification options
 
 # multiple recipients can be given like this:
@@ -94,7 +94,7 @@ DEFAULT_RECIPIENT_EMAIL="root"
 # to receive only critical alarms, set it to "root|critical"
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # pushover (pushover.net) global notification options
 
 # multiple recipients can be given like this:
@@ -115,7 +115,7 @@ PUSHOVER_APP_TOKEN=""
 DEFAULT_RECIPIENT_PUSHOVER=""
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # pushbullet (pushbullet.com) push notification options
 
 # multiple recipients can be given like this:
@@ -136,7 +136,7 @@ SEND_PUSHBULLET="YES"
 PUSHBULLET_ACCESS_TOKEN=""
 DEFAULT_RECIPIENT_PUSHBULLET=""
 
-###############################################################################
+#------------------------------------------------------------------------------
 # Twilio (twilio.com) SMS options
 
 # multiple recipients can be given like this:
@@ -157,7 +157,7 @@ TWILIO_ACCOUNT_TOKEN=""
 TWILIO_NUMBER=""
 DEFAULT_RECIPIENT_TWILIO=""
 
-###############################################################################
+#------------------------------------------------------------------------------
 # telegram (telegram.org) global notification options
 
 # To get your chat ID send the command /my_id to telegram bot @get_id.
@@ -178,7 +178,7 @@ TELEGRAM_BOT_TOKEN=""
 DEFAULT_RECIPIENT_TELEGRAM=""
 
 
-###############################################################################
+#------------------------------------------------------------------------------
 # slack (slack.com) global notification options
 
 # multiple recipients can be given like this:
@@ -199,6 +199,19 @@ SLACK_WEBHOOK_URL=""
 DEFAULT_RECIPIENT_SLACK=""
 
 
+#------------------------------------------------------------------------------
+# kafka notification options
+
+# enable/disable sending kafka notifications
+SEND_KAFKA="YES"
+
+# The URL to POST kafka alarm data to. It should be the full URL.
+KAFKA_URL=""
+
+# The IP to be used in the kafka message as the sender.
+KAFKA_SENDER_IP=""
+
+
 ###############################################################################
 # RECIPIENTS PER ROLE
 
index d7e760f9bfaccac54fad8ed5cdf6326a09bcd0d0..3842f5bdd695497d1fb1db7cf85c80b48cc55deb 100644 (file)
@@ -111,9 +111,15 @@ socket2:
   name     : 'local'
   # user     : ''
   # pass     : ''
-  socket   : '/var/lib/mysql/mysql.sock'
+  socket   : '/var/run/mysqld/mysql.sock'
 
 socket3:
+  name     : 'local'
+  # user     : ''
+  # pass     : ''
+  socket   : '/var/lib/mysql/mysql.sock'
+
+socket4:
   name     : 'local'
   # user     : ''
   # pass     : ''
@@ -167,9 +173,15 @@ socket2_root:
   name     : 'local'
   user     : 'root'
   # pass     : ''
-  socket   : '/var/lib/mysql/mysql.sock'
+  socket   : '/var/run/mysqld/mysql.sock'
 
 socket3_root:
+  name     : 'local'
+  user     : 'root'
+  # pass     : ''
+  socket   : '/var/lib/mysql/mysql.sock'
+
+socket4_root:
   name     : 'local'
   user     : 'root'
   # pass     : ''
index cec5699559c73d4fa5f57297be4261a89cdafe53..268168f97873afad37a8e9f429e0cd582100df06 100644 (file)
@@ -49,6 +49,7 @@ declare -A configs_signatures=(
   ['2ad55a5d1e885cf142849a78d4b00401']='health.d/net.conf'
   ['2bbbebf52f84fd27fbefecd2a8a8076f']='health.d/memcached.conf'
   ['2d1d7498c72f4245cf32902c2b7e71e0']='health.d/entropy.conf'
+  ['2f3a8e33df83f14e0af8ca2465697215']='python.d/exim.conf'
   ['2f4a85fedecce1bf425fa1039f6b021e']='apps_groups.conf'
   ['2fa8fb929fd597f2ab97b6efc540a043']='health_alarm_notify.conf'
   ['312b4b8e2805e19cf9be554b319567d6']='health.d/softnet.conf'
@@ -156,6 +157,7 @@ declare -A configs_signatures=(
   ['7a21ccc76be2968ce5d0b52ec1166788']='python.d.conf'
   ['7a985528cc9176564640001aa73e3492']='health.d/nginx.conf'
   ['7aa209fa287c95b3ca04c23681b40770']='health.d/disks.conf'
+  ['7bac18d8d5ff8f117be8d489a21c0c65']='python.d/mysql.conf'
   ['7cf6402b51e5070f2be3ad6fe059ff89']='charts.d.conf'
   ['7d8bd884ec26cb35d16c4fc05f969799']='python.d/squid.conf'
   ['7deb236ec68a512b9bdd18e6a51d76f7']='python.d/mysql.conf'
@@ -293,6 +295,7 @@ declare -A configs_signatures=(
   ['eb5168f0b516bc982aac45e59da6e52e']='health.d/nginx.conf'
   ['eb748d6fb69d11b0d29c5794657e206c']='health.d/qos.conf'
   ['ebd0612ccc5807524ebb2b647e3e56c9']='apps_groups.conf'
+  ['ec490e037c1e53daa44a55a941381d6d']='python.d/gunicorn_log.conf'
   ['ecd3aa97e2581f88eb466d6612690ef2']='charts.d/nginx.conf'
   ['ee5343881744e6a97e6ee5cdd329cfb8']='health.d/retroshare.conf'
   ['ef9916ea144878a9f37cbb6b1b29da10']='health.d/squid.conf'
index 9b26fcddcc584bcb7f788e6a63672206fd45af6a..f5dcf4dfdc5f85f7e22a4cb45b1742b6ce5359b0 100644 (file)
@@ -35,6 +35,9 @@ AC_PROG_INSTALL
 PKG_PROG_PKG_CONFIG
 AC_USE_SYSTEM_EXTENSIONS
 AC_CHECK_FUNCS_ONCE(accept4)
+AC_CHECK_TYPES([struct timespec, clockid_t], [], [], [[#include <time.h>]])
+AC_SEARCH_LIBS([clock_gettime], [rt posix4])
+AC_CHECK_FUNCS([clock_gettime])
 
 # Check system type
 case "$host_os" in
index 0136257524be8a619a71efebd206b22ccae1509f..17b009c965a0c7ad46d0b9993a96d7307786dd67 100755 (executable)
@@ -19,7 +19,8 @@
 #  - pushover.net notifications
 #  - pushbullet.com push notifications by Tiago Peralta @tperalta82 PR #1070
 #  - telegram.org notifications by @hashworks PR #1002
-#
+#  - twilio.com notifications by Levi Blaney @shadycuz PR #1211
+#  - kafka notifications
 
 # -----------------------------------------------------------------------------
 # testing notifications
@@ -173,6 +174,7 @@ SEND_TWILIO="YES"
 SEND_TELEGRAM="YES"
 SEND_EMAIL="YES"
 SEND_PUSHBULLET="YES"
+SEND_KAFKA="YES"
 
 # slack configs
 SLACK_WEBHOOK_URL=
@@ -201,6 +203,10 @@ TELEGRAM_BOT_TOKEN=
 DEFAULT_RECIPIENT_TELEGRAM=
 declare -A role_recipients_telegram=()
 
+# kafka configs
+KAFKA_URL=
+KAFKA_SENDER_IP=
+
 # email configs
 DEFAULT_RECIPIENT_EMAIL="root"
 declare -A role_recipients_email=()
@@ -359,27 +365,35 @@ done
 [ -z "${PUSHOVER_APP_TOKEN}" ] && SEND_PUSHOVER="NO"
 
 # check pushbullet
-[ -z "${DEFAULT_RECIPIENT_PUSHBULLET}" ] && SEND_PUSHBULLET="NO"
+[ -z "${PUSHBULLET_ACCESS_TOKEN}" ] && SEND_PUSHBULLET="NO"
 
 # check twilio
-[ -z "${DEFAULT_RECIPIENT_TWILIO}" ] && SEND_TWILIO="NO"
+[ -z "${TWILIO_ACCOUNT_TOKEN}" -o -z "${TWILIO_ACCOUNT_SID}" -o -z "${TWILIO_NUMBER}" ] && SEND_TWILIO="NO"
 
 # check telegram
 [ -z "${TELEGRAM_BOT_TOKEN}" ] && SEND_TELEGRAM="NO"
 
-if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" \) -a -z "${curl}" ]
+# check kafka
+[ -z "${KAFKA_URL}" -o -z "${KAFKA_SENDER_IP}" ] && SEND_KAFKA="NO"
+
+# if we need curl, check for the curl command
+if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" -o "${SEND_KAFKA}" = "YES" \) -a -z "${curl}" ]
     then
     curl="$(which curl 2>/dev/null || command -v curl 2>/dev/null)"
     if [ -z "${curl}" ]
         then
+        # no curl available
+        # disable all curl based methods
         SEND_PUSHOVER="NO"
         SEND_PUSHBULLET="NO"
         SEND_TELEGRAM="NO"
         SEND_SLACK="NO"
         SEND_TWILIO="NO"
+        SEND_KAFKA="NO"
     fi
 fi
 
+# if we need sendmail, check for the sendmail command
 if [ "${SEND_EMAIL}" = "YES" -a -z "${sendmail}" ]
     then
     sendmail="$(which sendmail 2>/dev/null || command -v sendmail 2>/dev/null)"
@@ -387,13 +401,20 @@ if [ "${SEND_EMAIL}" = "YES" -a -z "${sendmail}" ]
 fi
 
 # check that we have at least a method enabled
-if [ "${SEND_EMAIL}" != "YES" -a "${SEND_PUSHOVER}" != "YES" -a "${SEND_TELEGRAM}" != "YES" -a "${SEND_SLACK}" != "YES" -a "${SEND_TWILIO}" != "YES" -a  "${SEND_PUSHBULLET}" != "YES" ]
+if [   "${SEND_EMAIL}"      != "YES" \
+    -a "${SEND_PUSHOVER}"   != "YES" \
+    -a "${SEND_TELEGRAM}"   != "YES" \
+    -a "${SEND_SLACK}"      != "YES" \
+    -a "${SEND_TWILIO}"     != "YES" \
+    -a "${SEND_PUSHBULLET}" != "YES" \
+    -a "${SEND_KAFKA}"      != "YES" \
+    ]
     then
     fatal "All notification methods are disabled. Not sending notification to '${role}' for '${name}' = '${value}' of chart '${chart}' for status '${status}'."
 fi
 
 # -----------------------------------------------------------------------------
-# get the system hostname
+# find a suitable hostname to use, if netdata did not supply a hostname
 
 [ -z "${host}" ] && host="${NETDATA_HOSTNAME}"
 [ -z "${host}" ] && host="${NETDATA_REGISTRY_HOSTNAME}"
@@ -406,7 +427,7 @@ date="$(date --date=@${when} 2>/dev/null)"
 [ -z "${date}" ] && date="$(date 2>/dev/null)"
 
 # -----------------------------------------------------------------------------
-# URL encode a string
+# function to URL encode a string
 
 urlencode() {
     local string="${1}" strlen encoded pos c o
@@ -432,7 +453,7 @@ urlencode() {
 }
 
 # -----------------------------------------------------------------------------
-# convert a duration in seconds, to a human readable duration
+# function to convert a duration in seconds, to a human readable duration
 # using DAYS, MINUTES, SECONDS
 
 duration4human() {
@@ -592,6 +613,31 @@ EOF
     return 1
 }
 
+# -----------------------------------------------------------------------------
+# kafka sender
+
+send_kafka() {
+    local httpcode sent=0 
+    if [ "${SEND_KAFKA}" = "YES" ]
+        then
+            httpcode=$(${curl} -X POST --write-out %{http_code} --silent --output /dev/null \
+                --data "{host_ip:\"${KAFKA_SENDER_IP}\",when:${when},name:\"${name}\",chart:\"${chart}\",family:\"${family}\",status:\"${status}\",old_status:\"${old_status}\",value:${value},old_value:${old_value},duration:${duration},non_clear_duration:${non_clear_duration},units:\"${units}\",info:\"${info}\"}" \
+                "${KAFKA_URL}")
+
+            if [ "${httpcode}" == "204" ]
+            then
+                info "sent kafka data for: ${host} ${chart}.${name} is ${status} and ip '${KAFKA_SENDER_IP}'"
+                sent=$((sent + 1))
+            else
+                error "failed to send kafka data for: ${host} ${chart}.${name} is ${status} and ip '${KAFKA_SENDER_IP}' with HTTP error code ${httpcode}."
+            fi
+
+        [ ${sent} -gt 0 ] && return 0
+    fi
+
+    return 1
+}
+
 # -----------------------------------------------------------------------------
 # twilio sender
 
@@ -874,6 +920,14 @@ ${chart} (${family})
 
 SENT_TELEGRAM=$?
 
+
+# -----------------------------------------------------------------------------
+# send the kafka message
+
+send_kafka
+SENT_KAFKA=$?
+
+
 # -----------------------------------------------------------------------------
 # send the email
 
@@ -972,8 +1026,18 @@ SENT_EMAIL=$?
 # -----------------------------------------------------------------------------
 # let netdata know
 
-# we did send something
-[ ${SENT_EMAIL} -eq 0 -o ${SENT_PUSHOVER} -eq 0 -o ${SENT_TELEGRAM} -eq 0 -o ${SENT_SLACK} -eq 0 -o ${SENT_TWILIO} -eq 0 -o  ${SENT_PUSHBULLET} -eq 0 ] && exit 0
+if [   ${SENT_EMAIL}      -eq 0 \
+    -o ${SENT_PUSHOVER}   -eq 0 \
+    -o ${SENT_TELEGRAM}   -eq 0 \
+    -o ${SENT_SLACK}      -eq 0 \
+    -o ${SENT_TWILIO}     -eq 0 \
+    -o ${SENT_PUSHBULLET} -eq 0 \
+    -o ${SENT_KAFKA}      -eq 0 \
+    ]
+    then
+    # we did send something
+    exit 0
+fi
 
 # we did not send anything
 exit 1
index 466c699354313764e396b7367955df0b7c475aba..f2ddef3d11081e2253675dcc0a8c37b6f709595a 100644 (file)
@@ -30,6 +30,7 @@ netdata_SOURCES = \
        appconfig.c appconfig.h \
        avl.c avl.h \
        backends.c backends.h \
+       clocks.c clocks.h \
        common.c common.h \
        daemon.c daemon.h \
        dictionary.c dictionary.h \
@@ -100,6 +101,7 @@ netdata_LDADD = \
 apps_plugin_SOURCES = \
        apps_plugin.c \
        avl.c avl.h \
+       clocks.c clocks.h \
        common.c common.h \
        log.c log.h \
        procfile.c procfile.h \
index c126791d4c6a3afdd8b8f7e6e534c8152ed9673a..6431897f455a6965e9384f9f11fe33e8ad029751 100644 (file)
@@ -592,7 +592,7 @@ int read_proc_pid_stat(struct pid_stat *p) {
     if(unlikely(!ff)) goto cleanup;
 
     p->last_stat_collected_usec = p->stat_collected_usec;
-    p->stat_collected_usec = time_usec();
+    p->stat_collected_usec = now_realtime_usec();
     file_counter++;
 
     // p->pid           = atol(procfile_lineword(ff, 0, 0+i));
@@ -611,35 +611,35 @@ int read_proc_pid_stat(struct pid_stat *p) {
 
     last = p->minflt_raw;
     p->minflt_raw       = strtoull(procfile_lineword(ff, 0, 9), NULL, 10);
-    p->minflt = (p->minflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->minflt = (p->minflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->cminflt_raw;
     p->cminflt_raw      = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
-    p->cminflt = (p->cminflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->cminflt = (p->cminflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->majflt_raw;
     p->majflt_raw       = strtoull(procfile_lineword(ff, 0, 11), NULL, 10);
-    p->majflt = (p->majflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->majflt = (p->majflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->cmajflt_raw;
     p->cmajflt_raw      = strtoull(procfile_lineword(ff, 0, 12), NULL, 10);
-    p->cmajflt = (p->cmajflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->cmajflt = (p->cmajflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->utime_raw;
     p->utime_raw        = strtoull(procfile_lineword(ff, 0, 13), NULL, 10);
-    p->utime = (p->utime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->utime = (p->utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->stime_raw;
     p->stime_raw        = strtoull(procfile_lineword(ff, 0, 14), NULL, 10);
-    p->stime = (p->stime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->stime = (p->stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->cutime_raw;
     p->cutime_raw       = strtoull(procfile_lineword(ff, 0, 15), NULL, 10);
-    p->cutime = (p->cutime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->cutime = (p->cutime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     last = p->cstime_raw;
     p->cstime_raw       = strtoull(procfile_lineword(ff, 0, 16), NULL, 10);
-    p->cstime = (p->cstime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+    p->cstime = (p->cstime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
     // p->priority      = strtoull(procfile_lineword(ff, 0, 17), NULL, 10);
     // p->nice          = strtoull(procfile_lineword(ff, 0, 18), NULL, 10);
@@ -670,11 +670,11 @@ int read_proc_pid_stat(struct pid_stat *p) {
     if(enable_guest_charts) {
         last = p->gtime_raw;
         p->gtime_raw        = strtoull(procfile_lineword(ff, 0, 42), NULL, 10);
-        p->gtime = (p->gtime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+        p->gtime = (p->gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
         last = p->cgtime_raw;
         p->cgtime_raw       = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
-        p->cgtime = (p->cgtime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+        p->cgtime = (p->cgtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
 
         if (show_guest_time || p->gtime || p->cgtime) {
             p->utime -= (p->utime >= p->gtime) ? p->gtime : p->utime;
@@ -774,37 +774,37 @@ int read_proc_pid_io(struct pid_stat *p) {
     file_counter++;
 
     p->last_io_collected_usec = p->io_collected_usec;
-    p->io_collected_usec = time_usec();
+    p->io_collected_usec = now_realtime_usec();
 
     unsigned long long last;
 
     last = p->io_logical_bytes_read_raw;
     p->io_logical_bytes_read_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
-    p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     last = p->io_logical_bytes_written_raw;
     p->io_logical_bytes_written_raw = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
-    p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     // last = p->io_read_calls_raw;
     // p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
-    // p->io_read_calls = (p->io_read_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    // p->io_read_calls = (p->io_read_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     // last = p->io_write_calls_raw;
     // p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
-    // p->io_write_calls = (p->io_write_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    // p->io_write_calls = (p->io_write_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     last = p->io_storage_bytes_read_raw;
     p->io_storage_bytes_read_raw = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
-    p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     last = p->io_storage_bytes_written_raw;
     p->io_storage_bytes_written_raw = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
-    p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     // last = p->io_cancelled_write_bytes_raw;
     // p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
-    // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+    // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
 
     if(unlikely(global_iterations_counter == 1)) {
         p->io_logical_bytes_read        = 0;
@@ -836,7 +836,8 @@ unsigned long long global_gtime = 0;
 int read_proc_stat() {
     static char filename[FILENAME_MAX + 1] = "";
     static procfile *ff = NULL;
-    static unsigned long long utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0, collected_usec = 0, last_collected_usec = 0;
+    static unsigned long long utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0;
+    static usec_t collected_usec = 0, last_collected_usec = 0;
 
     if(unlikely(!ff)) {
         snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
@@ -848,7 +849,7 @@ int read_proc_stat() {
     if(unlikely(!ff)) goto cleanup;
 
     last_collected_usec = collected_usec;
-    collected_usec = time_usec();
+    collected_usec = now_realtime_usec();
 
     file_counter++;
 
@@ -856,26 +857,26 @@ int read_proc_stat() {
 
     last = utime_raw;
     utime_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
-    global_utime = (utime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+    global_utime = (utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
 
     // nice time, on user time
     last = ntime_raw;
     ntime_raw = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
-    global_utime += (ntime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+    global_utime += (ntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
 
     last = stime_raw;
     stime_raw = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
-    global_stime = (stime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+    global_stime = (stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
 
     last = gtime_raw;
     gtime_raw = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
-    global_gtime = (gtime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+    global_gtime = (gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
 
     if(enable_guest_charts) {
         // guest nice time, on guest time
         last = gntime_raw;
         gntime_raw = strtoull(procfile_lineword(ff, 0, 11), NULL, 10);
-        global_gtime += (gntime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+        global_gtime += (gntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
 
         // remove guest time from user time
         global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
@@ -1441,11 +1442,11 @@ void process_exited_processes() {
                         );
             }
 
-            p->utime_raw   = utime  * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
-            p->stime_raw   = stime  * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
-            p->gtime_raw   = gtime  * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
-            p->minflt_raw  = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
-            p->majflt_raw  = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
+            p->utime_raw   = utime  * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+            p->stime_raw   = stime  * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+            p->gtime_raw   = gtime  * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+            p->minflt_raw  = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+            p->majflt_raw  = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
             p->cutime_raw = p->cstime_raw = p->cgtime_raw = p->cminflt_raw = p->cmajflt_raw = 0;
 
             if(unlikely(debug))
@@ -2147,35 +2148,35 @@ static inline void send_END(void) {
 double utime_fix_ratio = 1.0, stime_fix_ratio = 1.0, gtime_fix_ratio = 1.0, cutime_fix_ratio = 1.0, cstime_fix_ratio = 1.0, cgtime_fix_ratio = 1.0;
 double minflt_fix_ratio = 1.0, majflt_fix_ratio = 1.0, cminflt_fix_ratio = 1.0, cmajflt_fix_ratio = 1.0;
 
-unsigned long long send_resource_usage_to_netdata() {
+usec_t send_resource_usage_to_netdata() {
     static struct timeval last = { 0, 0 };
     static struct rusage me_last;
 
     struct timeval now;
     struct rusage me;
 
-    unsigned long long usec;
-    unsigned long long cpuuser;
-    unsigned long long cpusyst;
+    usec_t usec;
+    usec_t cpuuser;
+    usec_t cpusyst;
 
     if(!last.tv_sec) {
-        gettimeofday(&last, NULL);
+        now_realtime_timeval(&last);
         getrusage(RUSAGE_SELF, &me_last);
 
         // the first time, give a zero to allow
         // netdata calibrate to the current time
-        // usec = update_every * 1000000ULL;
+        // usec = update_every * USEC_PER_SEC;
         usec = 0ULL;
         cpuuser = 0;
         cpusyst = 0;
     }
     else {
-        gettimeofday(&now, NULL);
+        now_realtime_timeval(&now);
         getrusage(RUSAGE_SELF, &me);
 
-        usec = usec_dt(&now, &last);
-        cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
-        cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
+        usec = dt_usec(&now, &last);
+        cpuuser = me.ru_utime.tv_sec * USEC_PER_SEC + me.ru_utime.tv_usec;
+        cpusyst = me.ru_stime.tv_sec * USEC_PER_SEC + me.ru_stime.tv_usec;
 
         memmove(&last, &now, sizeof(struct timeval));
         memmove(&me_last, &me, sizeof(struct rusage));
@@ -2381,7 +2382,7 @@ void normalize_data(struct target *root) {
     }
 }
 
-void send_collected_data_to_netdata(struct target *root, const char *type, unsigned long long usec) {
+void send_collected_data_to_netdata(struct target *root, const char *type, usec_t usec) {
     struct target *w;
 
     send_BEGIN(type, "cpu", usec);
@@ -2798,7 +2799,7 @@ int main(int argc, char **argv)
 
     procfile_adaptive_initial_allocation = 1;
 
-    time_t started_t = time(NULL);
+    time_t started_t = now_realtime_sec();
     get_system_HZ();
     get_system_pid_max();
     get_system_cpus();
@@ -2840,15 +2841,15 @@ int main(int argc, char **argv)
             , RATES_DETAIL
             );
 
-    unsigned long long step = update_every * 1000000ULL;
+    usec_t step = update_every * USEC_PER_SEC;
     global_iterations_counter = 1;
     for(;1; global_iterations_counter++) {
-        unsigned long long now = time_usec();
-        unsigned long long next = now - (now % step) + step;
+        usec_t now = now_realtime_usec();
+        usec_t next = now - (now % step) + step;
 
         while(now < next) {
             sleep_usec(next - now);
-            now = time_usec();
+            now = now_realtime_usec();
         }
 
         if(!collect_data_for_all_processes_from_proc()) {
@@ -2860,7 +2861,7 @@ int main(int argc, char **argv)
         calculate_netdata_statistics();
         normalize_data(apps_groups_root_target);
 
-        unsigned long long dt = send_resource_usage_to_netdata();
+        usec_t dt = send_resource_usage_to_netdata();
 
         // this is smart enough to show only newly added apps, when needed
         send_charts_updates_to_netdata(apps_groups_root_target, "apps", "Apps");
@@ -2890,7 +2891,7 @@ int main(int argc, char **argv)
         if(unlikely(debug))
             fprintf(stderr, "apps.plugin: done Loop No %llu\n", global_iterations_counter);
 
-        time_t current_t = time(NULL);
+        time_t current_t = now_realtime_sec();
 
         // restart check (14400 seconds)
         if(current_t - started_t > 14400) exit(0);
index f7c51eaf8a93e7d7513f632de0935efe2e956f34..34e032fa9ed3f046ea1c0e0e8f1cc918f2688d66 100644 (file)
@@ -395,9 +395,9 @@ void *backends_main(void *ptr) {
 
     info("BACKEND configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, frequency, hostname, prefix);
 
-    unsigned long long step_ut = frequency * 1000000ULL;
-    unsigned long long random_ut = time_usec() % (step_ut / 2);
-    time_t before = (time_t)((time_usec() - step_ut) / 10000000ULL);
+    usec_t step_ut = frequency * USEC_PER_SEC;
+    usec_t random_ut = now_realtime_usec() % (step_ut / 2);
+    time_t before = (time_t)((now_realtime_usec() - step_ut) / USEC_PER_SEC);
     time_t after = before;
     int failures = 0;
 
@@ -405,16 +405,16 @@ void *backends_main(void *ptr) {
         // ------------------------------------------------------------------------
         // wait for the next iteration point
 
-        unsigned long long now_ut = time_usec();
-        unsigned long long next_ut = now_ut - (now_ut % step_ut) + step_ut;
-        before = (time_t)(next_ut / 1000000ULL);
+        usec_t now_ut = now_realtime_usec();
+        usec_t next_ut = now_ut - (now_ut % step_ut) + step_ut;
+        before = (time_t)(next_ut / USEC_PER_SEC);
 
         // add a little delay (1/4 of the step) plus some randomness
         next_ut += (step_ut / 4) + random_ut;
 
         while(now_ut < next_ut) {
             sleep_usec(next_ut - now_ut);
-            now_ut = time_usec();
+            now_ut = now_realtime_usec();
         }
 
         // ------------------------------------------------------------------------
@@ -465,7 +465,7 @@ void *backends_main(void *ptr) {
         // connect to a backend server
 
         if(unlikely(sock == -1)) {
-            unsigned long long start_ut = time_usec();
+            usec_t start_ut = now_realtime_usec();
             const char *s = destination;
             while(*s) {
                 const char *e = s;
@@ -486,7 +486,7 @@ void *backends_main(void *ptr) {
                 if(sock != -1) break;
                 s = e;
             }
-            chart_backend_latency += time_usec() - start_ut;
+            chart_backend_latency += now_realtime_usec() - start_ut;
         }
 
         if(unlikely(netdata_exit)) break;
@@ -496,13 +496,13 @@ void *backends_main(void *ptr) {
 
         if(likely(sock != -1)) {
             size_t len = buffer_strlen(b);
-            unsigned long long start_ut = time_usec();
+            usec_t start_ut = now_realtime_usec();
             int flags = 0;
 #ifdef MSG_NOSIGNAL
             flags += MSG_NOSIGNAL;
 #endif
             ssize_t written = send(sock, buffer_tostring(b), len, flags);
-            chart_backend_latency += time_usec() - start_ut;
+            chart_backend_latency += now_realtime_usec() - start_ut;
             if(written != -1 && (size_t)written == len) {
                 // we sent the data successfully
                 chart_transmission_successes++;
diff --git a/src/clocks.c b/src/clocks.c
new file mode 100644 (file)
index 0000000..c90a07c
--- /dev/null
@@ -0,0 +1,73 @@
+#include "common.h"
+
+#ifndef HAVE_CLOCK_GETTIME
+inline int clock_gettime(clockid_t clk_id, struct timespec *ts) {
+    struct timeval tv;
+    if(unlikely(gettimeofday(&tv, NULL) == -1))
+        return -1;
+    ts->tv_sec = tv.tv_sec;
+    ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
+    return 0;
+}
+#endif
+
+inline time_t now_realtime_sec(void) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_REALTIME, &ts) == -1))
+        return 0;
+    return ts.tv_sec;
+}
+
+inline int now_realtime_timeval(struct timeval *tv) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_REALTIME, &ts) == -1))
+        return -1;
+    tv->tv_sec = ts.tv_sec;
+    tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+    return 0;
+}
+
+inline usec_t now_realtime_usec(void) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_REALTIME, &ts) == -1))
+        return 0;
+    return (usec_t)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
+}
+
+inline time_t now_monotonic_sec(void) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_MONOTONIC, &ts) == -1))
+        return 0;
+    return ts.tv_sec;
+}
+
+inline usec_t now_monotonic_usec(void) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_MONOTONIC, &ts) == -1))
+        return 0;
+    return (usec_t)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
+}
+
+inline time_t now_boottime_sec(void) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_BOOTTIME, &ts) == -1))
+        return 0;
+    return ts.tv_sec;
+}
+
+inline usec_t now_boottime_usec(void) {
+    struct timespec ts;
+    if(unlikely(clock_gettime(CLOCK_BOOTTIME, &ts) == -1))
+        return 0;
+    return (usec_t)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
+}
+
+inline usec_t timeval_usec(struct timeval *tv) {
+    return (usec_t)tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
+}
+
+inline usec_t dt_usec(struct timeval *now, struct timeval *old) {
+    usec_t ts1 = timeval_usec(now);
+    usec_t ts2 = timeval_usec(old);
+    return (ts1 > ts2) ? (ts1 - ts2) : (ts2 - ts1);
+}
diff --git a/src/clocks.h b/src/clocks.h
new file mode 100644 (file)
index 0000000..9634ac6
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef NETDATA_CLOCKS_H
+#define NETDATA_CLOCKS_H 1
+
+#ifndef HAVE_STRUCT_TIMESPEC
+struct timespec {
+    time_t tv_sec;  /* seconds */
+    long   tv_nsec; /* nanoseconds */
+};
+#endif
+
+#ifndef HAVE_CLOCKID_T
+typedef int clockid_t;
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+int clock_gettime(clockid_t clk_id, struct timespec *ts);
+#endif
+
+/* Linux value is as good as any other */
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME  0
+#endif
+
+#ifndef CLOCK_MONOTONIC
+/* fallback to CLOCK_REALTIME if not available */
+#define CLOCK_MONOTONIC CLOCK_REALTIME
+#endif
+
+#ifndef CLOCK_BOOTTIME
+/* fallback to CLOCK_MONOTONIC if not available */
+#define CLOCK_BOOTTIME  CLOCK_MONOTONIC
+#endif
+
+typedef unsigned long long usec_t;
+
+#define NSEC_PER_SEC    1000000000ULL
+#define NSEC_PER_MSEC   1000000ULL
+#define NSEC_PER_USEC   1000ULL
+#define USEC_PER_SEC    1000000ULL
+
+#ifndef HAVE_CLOCK_GETTIME
+/* Fallback function for POSIX.1-2001 clock_gettime() function.
+ *
+ * We use a realtime clock from gettimeofday(), this will
+ * make systems without clock_gettime() support sensitive
+ * to time jumps or hibernation/suspend side effects.
+ */
+extern int clock_gettime(clockid_t clk_id, struct timespec *ts);
+#endif
+
+/* Fills struct timeval with time since EPOCH from real-time clock (i.e. wall-clock).
+ * - Hibernation/suspend time is included
+ * - adjtime()/NTP adjustments affect this clock
+ * Return 0 on succes, -1 else with errno set appropriately.
+ */
+extern int now_realtime_timeval(struct timeval *tv);
+
+/* Returns time since EPOCH from real-time clock (i.e. wall-clock).
+ * - Hibernation/suspend time is included
+ * - adjtime()/NTP adjustments affect this clock
+ */
+extern time_t now_realtime_sec(void);
+extern usec_t now_realtime_usec(void);
+
+/* Returns time from monotonic clock if available, real-time clock else.
+ * If monotonic clock is available:
+ * - hibernation/suspend time is not included
+ * - adjtime()/NTP adjusments affect this clock
+ * If monotonic clock is not available, this fallbacks to now_realtime().
+ */
+extern time_t now_monotonic_sec(void);
+extern usec_t now_monotonic_usec(void);
+
+/* Returns time from boottime clock if available,
+ * monotonic clock else if available, real-time clock else.
+ * If boottime clock is available:
+ * - hibernation/suspend time is included
+ * - adjtime()/NTP adjusments affect this clock
+ * If boottime clock is not available, this fallbacks to now_monotonic().
+ * If monotonic clock is not available, this fallbacks to now_realtime().
+ */
+extern time_t now_boottime_sec(void);
+extern usec_t now_boottime_usec(void);
+
+extern usec_t timeval_usec(struct timeval *ts);
+extern usec_t dt_usec(struct timeval *now, struct timeval *old);
+
+#endif /* NETDATA_CLOCKS_H */
index 98093b965cd4e70a8a62eb28a44abe4f473b20ee..24aa4af60a47ab6b8180bf62793a0a4c51fc1bc2 100644 (file)
@@ -197,27 +197,7 @@ 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;
-}
-
-// time(NULL) in nanoseconds
-inline unsigned long long time_usec(void) {
-    struct timeval now;
-    gettimeofday(&now, NULL);
-    return timeval_usec(&now);
-}
-
-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);
-}
-
-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)
index a6f185bc0da80949584f20c8c49c32c66f2cd82c..5efb788aebbb65f641328b756eba6833bd676329 100644 (file)
 #endif // __GNUC__
 
 #include "avl.h"
+#include "clocks.h"
 #include "log.h"
 #include "global_statistics.h"
 #include "storage_number.h"
 #endif
 #define abs(x) ((x < 0)? -x : x)
 
-extern unsigned long long usec_dt(struct timeval *now, struct timeval *old);
-extern unsigned long long timeval_usec(struct timeval *tv);
-
-// #define usec_dt(now, last) (((((now)->tv_sec * 1000000ULL) + (now)->tv_usec) - (((last)->tv_sec * 1000000ULL) + (last)->tv_usec)))
-
 extern void netdata_fix_chart_id(char *s);
 extern void netdata_fix_chart_name(char *s);
 
@@ -195,8 +191,7 @@ extern int enable_ksm;
 
 extern pid_t gettid(void);
 
-extern unsigned long long time_usec(void);
-extern int sleep_usec(unsigned long long usec);
+extern int sleep_usec(usec_t usec);
 
 extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
 
index a4450f92c7c586d9e57353f6d32c40b900d5d3ff..122959ce4edb06d6ea99999838e53ec320d1046a 100644 (file)
@@ -102,7 +102,7 @@ static inline calculated_number eval_variable(EVAL_EXPRESSION *exp, EVAL_VARIABL
     }
 
     if(unlikely(v->hash == now_hash && !strcmp(v->name, "now"))) {
-        n = time(NULL);
+        n = now_realtime_sec();
         buffer_strcat(exp->error_msg, "[ $now = ");
         print_parsed_as_constant(exp->error_msg, n);
         buffer_strcat(exp->error_msg, " ] ");
index 73cc29b35b50abd6928e1f8fa192ed297ce0a798..78a705a8d18a3c6ce7915d27ddf7ec829a611b1c 100644 (file)
@@ -1,18 +1,31 @@
 #include "common.h"
 
-// NEEDED BY: struct vmstat
+// NEEDED BY: struct vmtotal, struct vmmeter
 #include <sys/vmmeter.h>
+// NEEDED BY: struct devstat
+#include <sys/devicestat.h>
+// NEEDED BY: struct xswdev
+#include <vm/vm_param.h>
+// NEEDED BY: struct semid_kernel, struct shmid_kernel, struct msqid_kernel
+#define _KERNEL
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+#undef _KERNEL
+// NEEDED BY: do_disk_io
+#define RRD_TYPE_DISK "disk"
 
 // FreeBSD calculates load averages once every 5 seconds
 #define MIN_LOADAVG_UPDATE_EVERY 5
 
-int do_freebsd_sysctl(int update_every, unsigned long long dt) {
+int do_freebsd_sysctl(int update_every, usec_t dt) {
     (void)dt;
 
     static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1,
-        do_loadavg = -1, do_all_processes = -1;
+        do_loadavg = -1, do_all_processes = -1, do_disk_io = -1, do_swap = -1, do_ram = -1, do_swapio = -1,
+        do_pgfaults = -1, do_committed = -1, do_ipc_semaphores = -1, do_ipc_shared_mem = -1, do_ipc_msg_queues = -1;
 
-    if(unlikely(do_cpu == -1)) {
+    if (unlikely(do_cpu == -1)) {
         do_cpu                  = config_get_boolean("plugin:freebsd:sysctl", "cpu utilization", 1);
         do_cpu_cores            = config_get_boolean("plugin:freebsd:sysctl", "per cpu core utilization", 1);
         do_interrupts           = config_get_boolean("plugin:freebsd:sysctl", "cpu interrupts", 1);
@@ -21,14 +34,24 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
         do_processes            = config_get_boolean("plugin:freebsd:sysctl", "processes running", 1);
         do_loadavg              = config_get_boolean("plugin:freebsd:sysctl", "enable load average", 1);
         do_all_processes        = config_get_boolean("plugin:freebsd:sysctl", "enable total processes", 1);
+        do_disk_io              = config_get_boolean("plugin:freebsd:sysctl", "stats for all disks", 1);
+        do_swap                 = config_get_boolean("plugin:freebsd:sysctl", "system swap", 1);
+        do_ram                  = config_get_boolean("plugin:freebsd:sysctl", "system ram", 1);
+        do_swapio               = config_get_boolean("plugin:freebsd:sysctl", "swap i/o", 1);
+        do_pgfaults             = config_get_boolean("plugin:freebsd:sysctl", "memory page faults", 1);
+        do_committed            = config_get_boolean("plugin:freebsd:sysctl", "committed memory", 1);
+        do_ipc_semaphores       = config_get_boolean("plugin:freebsd:sysctl", "ipc semaphores", 1);
+        do_ipc_shared_mem       = config_get_boolean("plugin:freebsd:sysctl", "ipc shared memory", 1);
+        do_ipc_msg_queues       = config_get_boolean("plugin:freebsd:sysctl", "ipc message queues", 1);
     }
 
     RRDSET *st;
 
+    int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
     int i;
 
 // NEEDED BY: do_loadavg
-    static unsigned long long last_loadavg_usec = 0;
+    static usec_t last_loadavg_usec = 0;
     struct loadavg sysload;
 
 // NEEDED BY: do_cpu, do_cpu_cores
@@ -51,17 +74,78 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
     static unsigned long *intrcnt = NULL;
     unsigned long long totalintr = 0;
 
+// NEEDED BY: do_disk_io
+    #define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
+    int numdevs;
+    static void *devstat_data = NULL;
+    struct devstat *dstat;
+    struct cur_dstat {
+        collected_number duration_read_ms;
+        collected_number duration_write_ms;
+        collected_number busy_time_ms;
+    } cur_dstat;
+    struct prev_dstat {
+        collected_number bytes_read;
+        collected_number bytes_write;
+        collected_number operations_read;
+        collected_number operations_write;
+        collected_number duration_read_ms;
+        collected_number duration_write_ms;
+        collected_number busy_time_ms;
+    } prev_dstat;
+
+    // NEEDED BY: do_swap
+    size_t mibsize, size;
+    int mib[3]; // CTL_MAXNAME = 24 maximum mib components (sysctl.h)
+    struct xswdev xsw;
+    struct total_xsw {
+        collected_number bytes_used;
+        collected_number bytes_total;
+    } total_xsw = {0, 0};
+
+    // NEEDED BY: do_swapio, do_ram
+    struct vmmeter vmmeter_data;
+
+    // NEEDED BY: do_ram
+    int vfs_bufspace_count;
+
+    // NEEDED BY: do_ipc_semaphores
+    struct ipc_sem {
+        int semmni;
+        collected_number sets;
+        collected_number semaphores;
+    } ipc_sem = {0, 0, 0};
+    static struct semid_kernel *ipc_sem_data = NULL;
+
+    // NEEDED BY: do_ipc_shared_mem
+    struct ipc_shm {
+        u_long shmmni;
+        collected_number segs;
+        collected_number segsize;
+    } ipc_shm = {0, 0, 0};
+    static struct shmid_kernel *ipc_shm_data = NULL;
+
+    // NEEDED BY: do_ipc_msg_queues
+    struct ipc_msq {
+        int msgmni;
+        collected_number queues;
+        collected_number messages;
+        collected_number usedsize;
+        collected_number allocsize;
+    } ipc_msq = {0, 0, 0, 0, 0};
+    static struct msqid_kernel *ipc_msq_data = NULL;
+
     // --------------------------------------------------------------------
 
-    if(last_loadavg_usec <= dt) {
-        if(likely(do_loadavg)) {
+    if (last_loadavg_usec <= dt) {
+        if (likely(do_loadavg)) {
             if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
                 do_loadavg = 0;
                 error("DISABLED: system.load");
             } else {
 
                 st = rrdset_find_bytype("system", "load");
-                if(unlikely(!st)) {
+                if (unlikely(!st)) {
                     st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE);
                     rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
                     rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
@@ -76,23 +160,25 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
             }
         }
 
-        last_loadavg_usec = st->update_every * 1000000ULL;
+        last_loadavg_usec = st->update_every * USEC_PER_SEC;
     }
     else last_loadavg_usec -= dt;
 
     // --------------------------------------------------------------------
 
-    if(likely(do_all_processes | do_processes)) {
+    if (likely(do_all_processes | do_processes | do_committed)) {
         if (unlikely(GETSYSCTL("vm.vmtotal", vmtotal_data))) {
             do_all_processes = 0;
             error("DISABLED: system.active_processes");
             do_processes = 0;
             error("DISABLED: system.processes");
+            do_committed = 0;
+            error("DISABLED: mem.committed");
         } else {
-            if(likely(do_processes)) {
+            if (likely(do_all_processes)) {
 
                 st = rrdset_find_bytype("system", "active_processes");
-                if(unlikely(!st)) {
+                if (unlikely(!st)) {
                     st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
                     rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
                 }
@@ -101,10 +187,13 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
                 rrddim_set(st, "active", (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw));
                 rrdset_done(st);
             }
-            if(likely(do_processes)) {
+
+            // --------------------------------------------------------------------
+
+            if (likely(do_processes)) {
 
                 st = rrdset_find_bytype("system", "processes");
-                if(unlikely(!st)) {
+                if (unlikely(!st)) {
                     st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
 
                     rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
@@ -117,30 +206,27 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
                 rrdset_done(st);
             }
 
-        }
-    }
+            // --------------------------------------------------------------------
 
-    // --------------------------------------------------------------------
-
-    if(likely(do_processes)) {
+            if (likely(do_committed)) {
+                st = rrdset_find("mem.committed");
+                if (unlikely(!st)) {
+                    st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA);
+                    st->isdetail = 1;
 
-            st = rrdset_find_bytype("system", "processes");
-            if(unlikely(!st)) {
-                st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
+                    rrddim_add(st, "Committed_AS", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
 
-                rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
-                rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE);
+                rrddim_set(st, "Committed_AS", vmtotal_data.t_rm);
+                rrdset_done(st);
             }
-            else rrdset_next(st);
-
-            rrddim_set(st, "running", vmtotal_data.t_rq);
-            rrddim_set(st, "blocked", (vmtotal_data.t_dw + vmtotal_data.t_pw));
-            rrdset_done(st);
         }
+    }
 
     // --------------------------------------------------------------------
 
-    if(likely(do_cpu)) {
+    if (likely(do_cpu)) {
         if (unlikely(CPUSTATES != 5)) {
             error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
             do_cpu = 0;
@@ -152,7 +238,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
             } else {
 
                 st = rrdset_find_bytype("system", "cpu");
-                if(unlikely(!st)) {
+                if (unlikely(!st)) {
                     st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED);
 
                     rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
@@ -176,7 +262,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
 
     // --------------------------------------------------------------------
 
-    if(likely(do_cpu_cores)) {
+    if (likely(do_cpu_cores)) {
         if (unlikely(CPUSTATES != 5)) {
             error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
             do_cpu_cores = 0;
@@ -203,7 +289,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
                     snprintfz(cpuid, 8, "cpu%d", i);
 
                     st = rrdset_find_bytype("cpu", cpuid);
-                    if(unlikely(!st)) {
+                    if (unlikely(!st)) {
                         st = rrdset_create("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", "percentage", 1000, update_every, RRDSET_TYPE_STACKED);
 
                         rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
@@ -228,7 +314,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
 
     // --------------------------------------------------------------------
 
-    if(likely(do_interrupts)) {
+    if (likely(do_interrupts)) {
         if (unlikely(sysctlbyname("hw.intrcnt", NULL, &intrcnt_size, NULL, 0) == -1)) {
             error("FREEBSD: sysctl(hw.intrcnt...) failed: %s", strerror(errno));
             do_interrupts = 0;
@@ -244,7 +330,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
                     totalintr += intrcnt[i];
 
                 st = rrdset_find_bytype("system", "intr");
-                if(unlikely(!st)) {
+                if (unlikely(!st)) {
                     st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Total Device Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
                     st->isdetail = 1;
 
@@ -260,14 +346,14 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
 
     // --------------------------------------------------------------------
 
-    if(likely(do_context)) {
+    if (likely(do_context)) {
         if (unlikely(GETSYSCTL("vm.stats.sys.v_swtch", u_int_data))) {
             do_context = 0;
             error("DISABLED: system.ctxt");
         } else {
 
             st = rrdset_find_bytype("system", "ctxt");
-            if(unlikely(!st)) {
+            if (unlikely(!st)) {
                 st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
 
                 rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -281,14 +367,14 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
 
     // --------------------------------------------------------------------
 
-    if(likely(do_forks)) {
+    if (likely(do_forks)) {
         if (unlikely(GETSYSCTL("vm.stats.vm.v_forks", u_int_data))) {
             do_forks = 0;
             error("DISABLED: system.forks");
         } else {
 
             st = rrdset_find_bytype("system", "forks");
-            if(unlikely(!st)) {
+            if (unlikely(!st)) {
                 st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
                 st->isdetail = 1;
 
@@ -301,5 +387,494 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
         }
     }
 
+    // --------------------------------------------------------------------
+
+    if (likely(do_disk_io)) {
+        if (unlikely(GETSYSCTL("kern.devstat.numdevs", numdevs))) {
+            do_disk_io = 0;
+            error("DISABLED: disk.io");
+        } else {
+            devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs); // there is generation number before devstat structures
+            if (unlikely(getsysctl("kern.devstat.all", devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs))) {
+                do_disk_io = 0;
+                error("DISABLED: disk.io");
+            } else {
+                dstat = devstat_data + sizeof(long); // skip generation number
+                collected_number total_disk_reads = 0;
+                collected_number total_disk_writes = 0;
+
+                for (i = 0; i < numdevs; i++) {
+                    if ((dstat[i].device_type == (DEVSTAT_TYPE_IF_SCSI | DEVSTAT_TYPE_DIRECT)) || (dstat[i].device_type == (DEVSTAT_TYPE_IF_IDE | DEVSTAT_TYPE_DIRECT))) {
+
+                        // --------------------------------------------------------------------
+
+                        st = rrdset_find_bytype(RRD_TYPE_DISK, dstat[i].device_name);
+                        if (unlikely(!st)) {
+                            st = rrdset_create(RRD_TYPE_DISK, dstat[i].device_name, NULL, dstat[i].device_name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
+
+                            rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL);
+                            rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL);
+                        }
+                        else rrdset_next(st);
+
+                        total_disk_reads += dstat[i].bytes[DEVSTAT_READ];
+                        total_disk_writes += dstat[i].bytes[DEVSTAT_WRITE];
+                        prev_dstat.bytes_read = rrddim_set(st, "reads", dstat[i].bytes[DEVSTAT_READ]);
+                        prev_dstat.bytes_write = rrddim_set(st, "writes", dstat[i].bytes[DEVSTAT_WRITE]);
+                        rrdset_done(st);
+
+                        // --------------------------------------------------------------------
+
+                        st = rrdset_find_bytype("disk_ops", dstat[i].device_name);
+                        if (unlikely(!st)) {
+                            st = rrdset_create("disk_ops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
+                            st->isdetail = 1;
+
+                            rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
+                            rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
+                        }
+                        else rrdset_next(st);
+
+                        prev_dstat.operations_read = rrddim_set(st, "reads", dstat[i].operations[DEVSTAT_READ]);
+                        prev_dstat.operations_write = rrddim_set(st, "writes", dstat[i].operations[DEVSTAT_WRITE]);
+                        rrdset_done(st);
+
+                        // --------------------------------------------------------------------
+
+                        st = rrdset_find_bytype("disk_qops", dstat[i].device_name);
+                        if (unlikely(!st)) {
+                            st = rrdset_create("disk_qops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
+                            st->isdetail = 1;
+
+                            rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                        }
+                        else rrdset_next(st);
+
+                        rrddim_set(st, "operations", dstat[i].start_count - dstat[i].end_count);
+                        rrdset_done(st);
+
+                        // --------------------------------------------------------------------
+
+                        st = rrdset_find_bytype("disk_util", dstat[i].device_name);
+                        if (unlikely(!st)) {
+                            st = rrdset_create("disk_util", dstat[i].device_name, NULL, dstat[i].device_name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
+                            st->isdetail = 1;
+
+                            rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
+                        }
+                        else rrdset_next(st);
+
+                        cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
+                        prev_dstat.busy_time_ms = rrddim_set(st, "utilization", cur_dstat.busy_time_ms);
+                        rrdset_done(st);
+
+                        // --------------------------------------------------------------------
+
+                        st = rrdset_find_bytype("disk_iotime", dstat[i].device_name);
+                        if (unlikely(!st)) {
+                            st = rrdset_create("disk_iotime", dstat[i].device_name, NULL, dstat[i].device_name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
+                            st->isdetail = 1;
+
+                            rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
+                            rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
+                        }
+                        else rrdset_next(st);
+
+                        cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
+                        cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
+                        prev_dstat.duration_read_ms = rrddim_set(st, "reads", cur_dstat.duration_read_ms);
+                        prev_dstat.duration_write_ms = rrddim_set(st, "writes", cur_dstat.duration_write_ms);
+                        rrdset_done(st);
+
+                        // --------------------------------------------------------------------
+                        // calculate differential charts
+                        // only if this is not the first time we run
+
+                        if (likely(dt)) {
+
+                            // --------------------------------------------------------------------
+
+                            st = rrdset_find_bytype("disk_await", dstat[i].device_name);
+                            if (unlikely(!st)) {
+                                st = rrdset_create("disk_await", dstat[i].device_name, NULL, dstat[i].device_name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
+                                st->isdetail = 1;
+
+                                rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                                rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
+                            }
+                            else rrdset_next(st);
+
+                            rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ? 
+                                (cur_dstat.duration_read_ms - prev_dstat.duration_read_ms) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
+                            rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
+                                (cur_dstat.duration_write_ms - prev_dstat.duration_write_ms) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
+                            rrdset_done(st);
+
+                            // --------------------------------------------------------------------
+
+                            st = rrdset_find_bytype("disk_avgsz", dstat[i].device_name);
+                            if (unlikely(!st)) {
+                                st = rrdset_create("disk_avgsz", dstat[i].device_name, NULL, dstat[i].device_name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
+                                st->isdetail = 1;
+
+                                rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE);
+                                rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE);
+                            }
+                            else rrdset_next(st);
+
+                            rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
+                                (dstat[i].bytes[DEVSTAT_READ] - prev_dstat.bytes_read) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
+                            rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
+                                (dstat[i].bytes[DEVSTAT_WRITE] - prev_dstat.bytes_write) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
+                            rrdset_done(st);
+
+                            // --------------------------------------------------------------------
+
+                            st = rrdset_find_bytype("disk_svctm", dstat[i].device_name);
+                            if (unlikely(!st)) {
+                                st = rrdset_create("disk_svctm", dstat[i].device_name, NULL, dstat[i].device_name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
+                                st->isdetail = 1;
+
+                                rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                            }
+                            else rrdset_next(st);
+
+                            rrddim_set(st, "svctm", ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) ?
+                                (cur_dstat.busy_time_ms - prev_dstat.busy_time_ms) / ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) : 0);
+                            rrdset_done(st);
+                        }
+                    }
+
+                    // --------------------------------------------------------------------
+
+                    st = rrdset_find_bytype("system", "io");
+                    if (unlikely(!st)) {
+                        st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
+                        rrddim_add(st, "in",  NULL,  1, 1024, RRDDIM_INCREMENTAL);
+                        rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL);
+                    }
+                    else rrdset_next(st);
+
+                    rrddim_set(st, "in", total_disk_reads);
+                    rrddim_set(st, "out", total_disk_writes);
+                    rrdset_done(st);
+                }
+            }
+        }
+    }
+
+    // --------------------------------------------------------------------
+
+
+    if (likely(do_swap)) {
+        mibsize = sizeof mib / sizeof mib[0];
+        if (unlikely(sysctlnametomib("vm.swap_info", mib, &mibsize) == -1)) {
+            error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
+            do_swap = 0;
+            error("DISABLED: disk.io");
+        } else {
+            for (i = 0; ; i++) {
+                mib[mibsize] = i;
+                size = sizeof(xsw);
+                if (unlikely(sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1 )) {
+                    if (unlikely(errno != ENOENT)) {
+                        error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
+                        do_swap = 0;
+                        error("DISABLED: disk.io");
+                    } else {
+                        if (unlikely(size != sizeof(xsw))) {
+                            error("FREEBSD: sysctl(%s...) expected %lu, got %lu", "vm.swap_info", (unsigned long)sizeof(xsw), (unsigned long)size);
+                            do_swap = 0;
+                            error("DISABLED: disk.io");
+                        } else break;
+                    }
+                }
+                total_xsw.bytes_used += xsw.xsw_used * system_pagesize;
+                total_xsw.bytes_total += xsw.xsw_nblks * system_pagesize;
+            }
+
+            if (likely(do_swap)) {
+                st = rrdset_find("system.swap");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
+                    st->isdetail = 1;
+
+                    rrddim_add(st, "free",    NULL, 1, 1048576, RRDDIM_ABSOLUTE);
+                    rrddim_add(st, "used",    NULL, 1, 1048576, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "used", total_xsw.bytes_used);
+                rrddim_set(st, "free", total_xsw.bytes_total - total_xsw.bytes_used);
+                rrdset_done(st);
+            }
+        }
+    }
+
+    // --------------------------------------------------------------------
+
+    if (likely(do_ram)) {
+        if (unlikely(GETSYSCTL("vm.stats.vm.v_active_count",    vmmeter_data.v_active_count) ||
+                     GETSYSCTL("vm.stats.vm.v_inactive_count",  vmmeter_data.v_inactive_count) ||
+                     GETSYSCTL("vm.stats.vm.v_wire_count",      vmmeter_data.v_wire_count) ||
+                     GETSYSCTL("vm.stats.vm.v_cache_count",     vmmeter_data.v_cache_count) ||
+                     GETSYSCTL("vfs.bufspace",                  vfs_bufspace_count) ||
+                     GETSYSCTL("vm.stats.vm.v_free_count",      vmmeter_data.v_free_count))) {
+            do_swapio = 0;
+            error("DISABLED: system.swapio");
+        } else {
+            st = rrdset_find("system.ram");
+            if (unlikely(!st)) {
+                st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);
+
+                rrddim_add(st, "active",    NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+                rrddim_add(st, "inactive",  NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+                rrddim_add(st, "wired",     NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+                rrddim_add(st, "cache",     NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+                rrddim_add(st, "buffers",   NULL, 1, 1024, RRDDIM_ABSOLUTE);
+                rrddim_add(st, "free",      NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+            }
+            else rrdset_next(st);
+
+            rrddim_set(st, "active",    vmmeter_data.v_active_count);
+            rrddim_set(st, "inactive",  vmmeter_data.v_inactive_count);
+            rrddim_set(st, "wired",     vmmeter_data.v_wire_count);
+            rrddim_set(st, "cache",     vmmeter_data.v_cache_count);
+            rrddim_set(st, "buffers",   vfs_bufspace_count);
+            rrddim_set(st, "free",      vmmeter_data.v_free_count);
+            rrdset_done(st);
+        }
+    }
+
+    // --------------------------------------------------------------------
+
+    if (likely(do_swapio)) {
+        if (unlikely(GETSYSCTL("vm.stats.vm.v_swappgsin", vmmeter_data.v_swappgsin) || GETSYSCTL("vm.stats.vm.v_vnodepgsout", vmmeter_data.v_swappgsout))) {
+            do_swapio = 0;
+            error("DISABLED: system.swapio");
+        } else {
+            st = rrdset_find("system.swapio");
+            if (unlikely(!st)) {
+                st = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);
+
+                rrddim_add(st, "in",  NULL, system_pagesize, 1024, RRDDIM_INCREMENTAL);
+                rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRDDIM_INCREMENTAL);
+            }
+            else rrdset_next(st);
+
+            rrddim_set(st, "in", vmmeter_data.v_swappgsin);
+            rrddim_set(st, "out", vmmeter_data.v_swappgsout);
+            rrdset_done(st);
+        }
+    }
+
+    // --------------------------------------------------------------------
+
+    if (likely(do_pgfaults)) {
+        if (unlikely(GETSYSCTL("vm.stats.vm.v_vm_faults",   vmmeter_data.v_vm_faults) ||
+                     GETSYSCTL("vm.stats.vm.v_io_faults",   vmmeter_data.v_io_faults) ||
+                     GETSYSCTL("vm.stats.vm.v_cow_faults",  vmmeter_data.v_cow_faults) ||
+                     GETSYSCTL("vm.stats.vm.v_cow_optim",   vmmeter_data.v_cow_optim) ||
+                     GETSYSCTL("vm.stats.vm.v_intrans",     vmmeter_data.v_intrans))) {
+            do_pgfaults = 0;
+            error("DISABLED: mem.pgfaults");
+        } else {
+            st = rrdset_find("mem.pgfaults");
+            if (unlikely(!st)) {
+                st = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
+                st->isdetail = 1;
+
+                rrddim_add(st, "memory", NULL, 1, 1, RRDDIM_INCREMENTAL);
+                rrddim_add(st, "io_requiring", NULL, 1, 1, RRDDIM_INCREMENTAL);
+                rrddim_add(st, "cow", NULL, 1, 1, RRDDIM_INCREMENTAL);
+                rrddim_add(st, "cow_optimized", NULL, 1, 1, RRDDIM_INCREMENTAL);
+                rrddim_add(st, "in_transit", NULL, 1, 1, RRDDIM_INCREMENTAL);
+            }
+            else rrdset_next(st);
+
+            rrddim_set(st, "memory", vmmeter_data.v_vm_faults);
+            rrddim_set(st, "io_requiring", vmmeter_data.v_io_faults);
+            rrddim_set(st, "cow", vmmeter_data.v_cow_faults);
+            rrddim_set(st, "cow_optimized", vmmeter_data.v_cow_optim);
+            rrddim_set(st, "in_transit", vmmeter_data.v_intrans);
+            rrdset_done(st);
+        }
+    }
+
+    // --------------------------------------------------------------------
+
+    if (likely(do_ipc_semaphores)) {
+        if (unlikely(GETSYSCTL("kern.ipc.semmni", ipc_sem.semmni))) {
+            do_ipc_semaphores = 0;
+            error("DISABLED: system.ipc_semaphores");
+            error("DISABLED: system.ipc_semaphore_arrays");
+        } else {
+            ipc_sem_data = reallocz(ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni);
+            if (unlikely(getsysctl("kern.ipc.sema", ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni))) {
+                do_ipc_semaphores = 0;
+                error("DISABLED: system.ipc_semaphores");
+                error("DISABLED: system.ipc_semaphore_arrays");
+            } else {
+                for (i = 0; i < ipc_sem.semmni; i++) {
+                    if (unlikely(ipc_sem_data[i].u.sem_perm.mode & SEM_ALLOC)) {
+                        ipc_sem.sets += 1;
+                        ipc_sem.semaphores += ipc_sem_data[i].u.sem_nsems;
+                    }
+                }
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_semaphores");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "semaphores", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "semaphores", ipc_sem.semaphores);
+                rrdset_done(st);
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_semaphore_arrays");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "arrays", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "arrays", ipc_sem.sets);
+                rrdset_done(st);
+            }
+        }
+    }
+
+    // --------------------------------------------------------------------
+
+    if (likely(do_ipc_shared_mem)) {
+        if (unlikely(GETSYSCTL("kern.ipc.shmmni", ipc_shm.shmmni))) {
+            do_ipc_shared_mem = 0;
+            error("DISABLED: system.ipc_shared_mem_segs");
+            error("DISABLED: system.ipc_shared_mem_size");
+        } else {
+            ipc_shm_data = reallocz(ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni);
+            if (unlikely(getsysctl("kern.ipc.shmsegs", ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni))) {
+                do_ipc_shared_mem = 0;
+                error("DISABLED: system.ipc_shared_mem_segs");
+                error("DISABLED: system.ipc_shared_mem_size");
+            } else {
+                for (i = 0; i < ipc_shm.shmmni; i++) {
+                    if (unlikely(ipc_shm_data[i].u.shm_perm.mode & 0x0800)) {
+                        ipc_shm.segs += 1;
+                        ipc_shm.segsize += ipc_shm_data[i].u.shm_segsz;
+                    }
+                }
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_shared_mem_segs");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_shared_mem_segs", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments", "segments", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "segments", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "segments", ipc_shm.segs);
+                rrdset_done(st);
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_shared_mem_size");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_shared_mem_size", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments Size", "kilobytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "allocated", NULL, 1, 1024, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "allocated", ipc_shm.segsize);
+                rrdset_done(st);
+            }
+        }
+    }
+
+       // --------------------------------------------------------------------
+
+    if (likely(do_ipc_msg_queues)) {
+        if (unlikely(GETSYSCTL("kern.ipc.msgmni", ipc_msq.msgmni))) {
+            do_ipc_msg_queues = 0;
+            error("DISABLED: system.ipc_msq_queues");
+            error("DISABLED: system.ipc_msq_messages");
+            error("DISABLED: system.ipc_msq_used_size");
+            error("DISABLED: system.ipc_msq_allocated_size");
+        } else {
+            ipc_msq_data = reallocz(ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni);
+            if (unlikely(getsysctl("kern.ipc.msqids", ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni))) {
+                do_ipc_msg_queues = 0;
+                error("DISABLED: system.ipc_msq_queues");
+                error("DISABLED: system.ipc_msq_messages");
+                error("DISABLED: system.ipc_msq_used_size");
+                error("DISABLED: system.ipc_msq_allocated_size");
+            } else {
+                for (i = 0; i < ipc_msq.msgmni; i++) {
+                    if (unlikely(ipc_msq_data[i].u.msg_qbytes != 0)) {
+                        ipc_msq.queues += 1;
+                        ipc_msq.messages += ipc_msq_data[i].u.msg_qnum;
+                        ipc_msq.usedsize += ipc_msq_data[i].u.msg_cbytes;
+                        ipc_msq.allocsize += ipc_msq_data[i].u.msg_qbytes;
+                    }
+                }
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_msq_queues");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "queues", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "queues", ipc_msq.queues);
+                rrdset_done(st);
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_msq_messages");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_msq_messages", NULL, "ipc message queues", NULL, "Number of Messages in IPC Message Queues", "messages", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "messages", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "messages", ipc_msq.messages);
+                rrdset_done(st);
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_msq_used_size");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_msq_used_size", NULL, "ipc message queues", NULL, "Number of used bytes in IPC Message Queues", "bytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "used", ipc_msq.usedsize);
+                rrdset_done(st);
+
+
+                // --------------------------------------------------------------------
+
+                st = rrdset_find("system.ipc_msq_allocated_size");
+                if (unlikely(!st)) {
+                    st = rrdset_create("system", "ipc_msq_allocated_size", NULL, "ipc message queues", NULL, "Maximum size of IPC Message Queues", "bytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+                    rrddim_add(st, "allocated", NULL, 1, 1, RRDDIM_ABSOLUTE);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "allocated", ipc_msq.allocsize);
+                rrdset_done(st);
+            }
+        }
+    }
+
     return 0;
 }
index 27dcc8075825cf660a23c00960696af82462d1dc..849a3faf9646a07ca997d8393f747ad8c51bb133 100755 (executable)
@@ -314,8 +314,8 @@ static inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char
 
     freez(buf);
 
-    if(!max_unique_id) max_unique_id = (uint32_t)time(NULL);
-    if(!max_alarm_id)  max_alarm_id  = (uint32_t)time(NULL);
+    if(!max_unique_id) max_unique_id = (uint32_t)now_realtime_sec();
+    if(!max_alarm_id)  max_alarm_id  = (uint32_t)now_realtime_sec();
 
     host->health_log.next_log_id = max_unique_id + 1;
     host->health_log.next_alarm_id = max_alarm_id + 1;
@@ -1053,7 +1053,7 @@ static inline const char *rrdcalc_status2string(int status) {
 static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
     debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, st->rrdhost->hostname);
 
-    rc->last_status_change = time(NULL);
+    rc->last_status_change = now_realtime_sec();
     rc->rrdset = st;
 
     rc->rrdset_next = st->alarms;
@@ -1092,7 +1092,7 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
        if(!rc->units) rc->units = strdupz(st->units);
 
     {
-        time_t now = time(NULL);
+        time_t now = now_realtime_sec();
         health_alarm_log(st->rrdhost, rc->id, rc->next_event_id++, now, rc->name, rc->rrdset->id, rc->rrdset->family, rc->exec, rc->recipient, now - rc->last_status_change, rc->old_value, rc->value, rc->status, RRDCALC_STATUS_UNINITIALIZED, rc->source, rc->units, rc->info, 0);
     }
 }
@@ -1130,7 +1130,7 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) {
     }
 
     {
-        time_t now = time(NULL);
+        time_t now = now_realtime_sec();
         health_alarm_log(st->rrdhost, rc->id, rc->next_event_id++, now, rc->name, rc->rrdset->id, rc->rrdset->family, rc->exec, rc->recipient, now - rc->last_status_change, rc->old_value, rc->value, rc->status, RRDCALC_STATUS_REMOVED, rc->source, rc->units, rc->info, 0);
     }
 
@@ -2492,7 +2492,7 @@ void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) {
                         host->hostname,
                         (host->health_log.next_log_id > 0)?(host->health_log.next_log_id - 1):0,
                         health_enabled?"true":"false",
-                        (unsigned long)time(NULL));
+                        (unsigned long)now_realtime_sec());
 
     RRDCALC *rc;
     for(i = 0, rc = host->alarms; rc ; rc = rc->next) {
@@ -2652,7 +2652,7 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) {
     );
 
     ae->flags |= HEALTH_ENTRY_FLAG_EXEC_RUN;
-    ae->exec_run_timestamp = time(NULL);
+    ae->exec_run_timestamp = now_realtime_sec();
 
     debug(D_HEALTH, "executing command '%s'", command_to_run);
     FILE *fp = mypopen(command_to_run, &command_pid);
@@ -2688,7 +2688,7 @@ static inline void health_process_notifications(RRDHOST *host, ALARM_ENTRY *ae)
 static inline void health_alarm_log_process(RRDHOST *host) {
     static uint32_t stop_at_id = 0;
     uint32_t first_waiting = (host->health_log.alarms)?host->health_log.alarms->unique_id:0;
-    time_t now = time(NULL);
+    time_t now = now_realtime_sec();
 
     pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
 
@@ -2825,7 +2825,7 @@ void *health_main(void *ptr) {
         debug(D_HEALTH, "Health monitoring iteration no %u started", loop);
 
         int oldstate, runnable = 0;
-        time_t now = time(NULL);
+        time_t now = now_realtime_sec();
         time_t next_run = now + min_run_every;
         RRDCALC *rc;
 
@@ -3097,11 +3097,11 @@ void *health_main(void *ptr) {
         if(unlikely(netdata_exit))
             break;
         
-        now = time(NULL);
+        now = now_realtime_sec();
         if(now < next_run) {
             debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration in %d secs",
                   loop, (int) (next_run - now));
-            sleep_usec(1000000 * (unsigned long long) (next_run - now));
+            sleep_usec(USEC_PER_SEC * (usec_t) (next_run - now));
         }
         else {
             debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration now", loop);
index 3cf76513dce8b27bbf46367fce5d9f54a7451adf..6a261c5c20a9bb9e2355bdcc63d47003550b491b 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -160,7 +160,7 @@ static inline int ipc_sem_get_status(struct ipc_status *st) {
     return 0;
 }
 
-int do_ipc(int update_every, unsigned long long dt) {
+int do_ipc(int update_every, usec_t dt) {
     (void)dt;
 
     static int initialized = 0, read_limits_next = 0;
index 3762a69d76bdcc21e7ef7d1844ea041324d6c65a..04f9df5cdf046f98b8bc2ba9d51d9e4d3f12fd5c 100644 (file)
--- a/src/ipc.h
+++ b/src/ipc.h
@@ -1,7 +1,7 @@
 #ifndef NETDATA_PLUGIN_IPC_H
 #define NETDATA_PLUGIN_IPC_H 1
 
-extern int do_ipc(int update_every, unsigned long long dt);
+extern int do_ipc(int update_every, usec_t dt);
 
 #endif /* NETDATA_PLUGIN_IPC_H */
 
index dc00834236bf982dac79a5232614fa36260a5505..d4c7fa14d904a6ee9007863e03f6ef73418ae0b9 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -131,7 +131,7 @@ int error_log_limit(int reset) {
         return 1;
 #endif
 
-    time_t now = time(NULL);
+    time_t now = now_monotonic_sec();
     if(!start) start = now;
 
     if(reset) {
@@ -212,7 +212,7 @@ void log_date(FILE *out)
         time_t t;
         struct tm *tmp, tmbuf;
 
-        t = time(NULL);
+        t = now_realtime_sec();
         tmp = localtime_r(&t, &tmbuf);
 
         if (tmp == NULL) return;
index 007d6565fa30b6d5cd1563c66d3b759ea47b18cb..12f48ff85556bedd9e3b7e6d1156e6f02c2e7dd2 100644 (file)
@@ -12,7 +12,7 @@ void *checks_main(void *ptr)
     if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
         error("Cannot set pthread cancel state to ENABLE.");
 
-    unsigned long long usec = 0, susec = rrd_update_every * 1000000ULL, loop_usec = 0, total_susec = 0;
+    usec_t usec = 0, susec = rrd_update_every * USEC_PER_SEC, loop_usec = 0, total_susec = 0;
     struct timeval now, last, loop;
 
     RRDSET *check1, *check2, *check3, *apps_cpu = NULL;
@@ -30,18 +30,18 @@ void *checks_main(void *ptr)
     rrddim_add(check3, "netdata", NULL, 1, 1, RRDDIM_ABSOLUTE);
     rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRDDIM_ABSOLUTE);
 
-    gettimeofday(&last, NULL);
+    now_realtime_timeval(&last);
     while(1) {
         usleep(susec);
 
         // find the time to sleep in order to wait exactly update_every seconds
-        gettimeofday(&now, NULL);
-        loop_usec = usec_dt(&now, &last);
+        now_realtime_timeval(&now);
+        loop_usec = dt_usec(&now, &last);
         usec = loop_usec - susec;
         debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec);
 
-        if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
-        else susec = rrd_update_every * 1000000ULL / 2ULL;
+        if(usec < (rrd_update_every * USEC_PER_SEC / 2ULL)) susec = (rrd_update_every * USEC_PER_SEC) - usec;
+        else susec = rrd_update_every * USEC_PER_SEC / 2ULL;
 
         // --------------------------------------------------------------------
         // Calculate loop time
@@ -71,10 +71,10 @@ void *checks_main(void *ptr)
 
         if(!apps_cpu) apps_cpu = rrdset_find("apps.cpu");
         if(check3->counter_done) rrdset_next_usec(check3, loop_usec);
-        gettimeofday(&loop, NULL);
-        rrddim_set(check3, "caller", (long long) usec_dt(&loop, &check1->last_collected_time));
-        rrddim_set(check3, "netdata", (long long) usec_dt(&loop, &check2->last_collected_time));
-        if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) usec_dt(&loop, &apps_cpu->last_collected_time));
+        now_realtime_timeval(&loop);
+        rrddim_set(check3, "caller", (long long) dt_usec(&loop, &check1->last_collected_time));
+        rrddim_set(check3, "netdata", (long long) dt_usec(&loop, &check2->last_collected_time));
+        if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) dt_usec(&loop, &apps_cpu->last_collected_time));
         rrdset_done(check3);
     }
 
index 47a18613727bffc4b37d876deb79b2d3b82ef876..9231b538294e01c329e85486c30559c370624448 100644 (file)
@@ -25,14 +25,14 @@ void *freebsd_main(void *ptr)
     // keep track of the time each module was called
     unsigned long long sutime_freebsd_sysctl = 0ULL;
 
-    unsigned long long step = rrd_update_every * 1000000ULL;
+    usec_t step = rrd_update_every * USEC_PER_SEC;
     for(;;) {
-        unsigned long long now = time_usec();
-        unsigned long long next = now - (now % step) + step;
+        usec_t now = now_realtime_usec();
+        usec_t next = now - (now % step) + step;
 
         while(now < next) {
             sleep_usec(next - now);
-            now = time_usec();
+            now = now_realtime_usec();
         }
 
         if(unlikely(netdata_exit)) break;
@@ -41,7 +41,7 @@ void *freebsd_main(void *ptr)
 
         if(!vdo_freebsd_sysctl) {
             debug(D_PROCNETDEV_LOOP, "FREEBSD: calling do_freebsd_sysctl().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_freebsd_sysctl = do_freebsd_sysctl(rrd_update_every, (sutime_freebsd_sysctl > 0)?now - sutime_freebsd_sysctl:0ULL);
             sutime_freebsd_sysctl = now;
         }
index ee432bfc6d1af78f36c57f8eff2bf4665f0b4488..4ae1a4c21831e7b8ba7f291c6794dbb2190d8d5a 100644 (file)
@@ -7,6 +7,6 @@ void *freebsd_main(void *ptr);
 
 int getsysctl(const char *name, void *ptr, size_t len);
 
-extern int do_freebsd_sysctl(int update_every, unsigned long long dt);
+extern int do_freebsd_sysctl(int update_every, usec_t dt);
 
 #endif /* NETDATA_PLUGIN_FREEBSD_H */
index a9b340ab00897637b7f047f1c3e3c832b55f4059..77fab3fa8b605f3dc371a74079830ad09a3cda3c 100644 (file)
@@ -29,16 +29,16 @@ void *cpuidlejitter_main(void *ptr)
     struct timeval before, after;
     unsigned long long counter;
     for(counter = 0; 1 ;counter++) {
-        unsigned long long usec = 0, susec = 0;
+        usec_t usec = 0, susec = 0;
 
-        while(susec < (rrd_update_every * 1000000ULL)) {
+        while(susec < (rrd_update_every * USEC_PER_SEC)) {
 
-            gettimeofday(&before, NULL);
+            now_realtime_timeval(&before);
             sleep_usec(sleep_ms * 1000);
-            gettimeofday(&after, NULL);
+            now_realtime_timeval(&after);
 
             // calculate the time it took for a full loop
-            usec = usec_dt(&after, &before);
+            usec = dt_usec(&after, &before);
             susec += usec;
         }
         usec -= (sleep_ms * 1000);
index 7843161d32bf86e3bce565cf742e2dd3bfbfce97..03de379170f4f8847def30e8d6ffcd674a1f868c 100644 (file)
@@ -70,7 +70,7 @@ void *nfacct_main(void *ptr) {
     struct nlmsghdr *nlh = NULL;
     unsigned int seq = 0, portid = 0;
 
-    seq = time(NULL) - 1;
+    seq = now_realtime_sec() - 1;
 
     nl  = mnl_socket_open(NETLINK_NETFILTER);
     if(!nl) {
@@ -90,10 +90,10 @@ void *nfacct_main(void *ptr) {
     // ------------------------------------------------------------------------
 
     struct timeval last, now;
-    unsigned long long usec = 0, susec = 0;
+    usec_t usec = 0, susec = 0;
     RRDSET *st = NULL;
 
-    gettimeofday(&last, NULL);
+    now_realtime_timeval(&last);
 
     // ------------------------------------------------------------------------
 
@@ -131,8 +131,8 @@ void *nfacct_main(void *ptr) {
 
         // --------------------------------------------------------------------
 
-        gettimeofday(&now, NULL);
-        usec = usec_dt(&now, &last) - susec;
+        now_realtime_timeval(&now);
+        usec = dt_usec(&now, &last) - susec;
         debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
 
         if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
index 1aa2fb58818979e0d2a4cc25a75078d5cd3dc2f6..4188c9a2b617334d2b3eec2b630ebc4e7a09bc89 100644 (file)
@@ -40,35 +40,35 @@ void *proc_main(void *ptr)
     int vdo_cpu_netdata             = !config_get_boolean("plugin:proc", "netdata server resources", 1);
 
     // keep track of the time each module was called
-    unsigned long long sutime_proc_net_dev = 0ULL;
-    unsigned long long sutime_proc_diskstats = 0ULL;
-    unsigned long long sutime_proc_net_snmp = 0ULL;
-    unsigned long long sutime_proc_net_snmp6 = 0ULL;
-    unsigned long long sutime_proc_net_netstat = 0ULL;
-    unsigned long long sutime_proc_net_stat_conntrack = 0ULL;
-    unsigned long long sutime_proc_net_ip_vs_stats = 0ULL;
-    unsigned long long sutime_proc_net_stat_synproxy = 0ULL;
-    unsigned long long sutime_proc_stat = 0ULL;
-    unsigned long long sutime_proc_meminfo = 0ULL;
-    unsigned long long sutime_proc_vmstat = 0ULL;
-    unsigned long long sutime_proc_net_rpc_nfs = 0ULL;
-    unsigned long long sutime_proc_net_rpc_nfsd = 0ULL;
-    unsigned long long sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
-    unsigned long long sutime_proc_interrupts = 0ULL;
-    unsigned long long sutime_proc_softirqs = 0ULL;
-    unsigned long long sutime_proc_net_softnet_stat = 0ULL;
-    unsigned long long sutime_proc_loadavg = 0ULL;
-    unsigned long long sutime_ipc = 0ULL;
-    unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
-
-    unsigned long long step = rrd_update_every * 1000000ULL;
+    usec_t sutime_proc_net_dev = 0ULL;
+    usec_t sutime_proc_diskstats = 0ULL;
+    usec_t sutime_proc_net_snmp = 0ULL;
+    usec_t sutime_proc_net_snmp6 = 0ULL;
+    usec_t sutime_proc_net_netstat = 0ULL;
+    usec_t sutime_proc_net_stat_conntrack = 0ULL;
+    usec_t sutime_proc_net_ip_vs_stats = 0ULL;
+    usec_t sutime_proc_net_stat_synproxy = 0ULL;
+    usec_t sutime_proc_stat = 0ULL;
+    usec_t sutime_proc_meminfo = 0ULL;
+    usec_t sutime_proc_vmstat = 0ULL;
+    usec_t sutime_proc_net_rpc_nfs = 0ULL;
+    usec_t sutime_proc_net_rpc_nfsd = 0ULL;
+    usec_t sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
+    usec_t sutime_proc_interrupts = 0ULL;
+    usec_t sutime_proc_softirqs = 0ULL;
+    usec_t sutime_proc_net_softnet_stat = 0ULL;
+    usec_t sutime_proc_loadavg = 0ULL;
+    usec_t sutime_ipc = 0ULL;
+    usec_t sutime_sys_kernel_mm_ksm = 0ULL;
+
+    usec_t step = rrd_update_every * USEC_PER_SEC;
     for(;;) {
-        unsigned long long now = time_usec();
-        unsigned long long next = now - (now % step) + step;
+        usec_t now = now_realtime_usec();
+        usec_t next = now - (now % step) + step;
 
         while(now < next) {
             sleep_usec(next - now);
-            now = time_usec();
+            now = now_realtime_usec();
         }
 
         if(unlikely(netdata_exit)) break;
@@ -78,7 +78,7 @@ void *proc_main(void *ptr)
         if(!vdo_sys_kernel_mm_ksm) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm().");
 
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?now - sutime_sys_kernel_mm_ksm:0ULL);
             sutime_sys_kernel_mm_ksm = now;
         }
@@ -86,7 +86,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_loadavg) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?now - sutime_proc_loadavg:0ULL);
             sutime_proc_loadavg = now;
         }
@@ -94,7 +94,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_ipc) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_ipc().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_ipc = do_ipc(rrd_update_every, (sutime_ipc > 0)?now - sutime_ipc:0ULL);
             sutime_ipc = now;
         }
@@ -102,7 +102,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_interrupts) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?now - sutime_proc_interrupts:0ULL);
             sutime_proc_interrupts = now;
         }
@@ -110,7 +110,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_softirqs) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?now - sutime_proc_softirqs:0ULL);
             sutime_proc_softirqs = now;
         }
@@ -118,7 +118,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_softnet_stat) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_softnet_stat().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?now - sutime_proc_net_softnet_stat:0ULL);
             sutime_proc_net_softnet_stat = now;
         }
@@ -126,7 +126,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_sys_kernel_random_entropy_avail) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?now - sutime_proc_sys_kernel_random_entropy_avail:0ULL);
             sutime_proc_sys_kernel_random_entropy_avail = now;
         }
@@ -134,7 +134,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_dev) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?now - sutime_proc_net_dev:0ULL);
             sutime_proc_net_dev = now;
         }
@@ -142,7 +142,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_diskstats) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?now - sutime_proc_diskstats:0ULL);
             sutime_proc_diskstats = now;
         }
@@ -150,7 +150,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_snmp) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?now - sutime_proc_net_snmp:0ULL);
             sutime_proc_net_snmp = now;
         }
@@ -158,7 +158,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_snmp6) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?now - sutime_proc_net_snmp6:0ULL);
             sutime_proc_net_snmp6 = now;
         }
@@ -166,7 +166,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_netstat) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?now - sutime_proc_net_netstat:0ULL);
             sutime_proc_net_netstat = now;
         }
@@ -174,7 +174,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_stat_conntrack) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?now - sutime_proc_net_stat_conntrack:0ULL);
             sutime_proc_net_stat_conntrack = now;
         }
@@ -182,7 +182,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_ip_vs_stats) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?now - sutime_proc_net_ip_vs_stats:0ULL);
             sutime_proc_net_ip_vs_stats = now;
         }
@@ -190,7 +190,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_stat_synproxy) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?now - sutime_proc_net_stat_synproxy:0ULL);
             sutime_proc_net_stat_synproxy = now;
         }
@@ -198,7 +198,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_stat) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?now - sutime_proc_stat:0ULL);
             sutime_proc_stat = now;
         }
@@ -206,7 +206,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_meminfo) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?now - sutime_proc_meminfo:0ULL);
             sutime_proc_meminfo = now;
         }
@@ -214,7 +214,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_vmstat) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?now - sutime_proc_vmstat:0ULL);
             sutime_proc_vmstat = now;
         }
@@ -222,7 +222,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_rpc_nfsd) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?now - sutime_proc_net_rpc_nfsd:0ULL);
             sutime_proc_net_rpc_nfsd = now;
         }
@@ -230,7 +230,7 @@ void *proc_main(void *ptr)
 
         if(!vdo_proc_net_rpc_nfs) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfs().");
-            now = time_usec();
+            now = now_realtime_usec();
             vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?now - sutime_proc_net_rpc_nfs:0ULL);
             sutime_proc_net_rpc_nfs = now;
         }
index f72a9970f38cb1c19c8a7d20f62802e338cec5d8..4e0cbc3ceed0c1c73c9598d0d0073f1ef1aae483 100644 (file)
@@ -3,24 +3,24 @@
 
 void *proc_main(void *ptr);
 
-extern int do_proc_net_dev(int update_every, unsigned long long dt);
-extern int do_proc_diskstats(int update_every, unsigned long long dt);
-extern int do_proc_net_snmp(int update_every, unsigned long long dt);
-extern int do_proc_net_snmp6(int update_every, unsigned long long dt);
-extern int do_proc_net_netstat(int update_every, unsigned long long dt);
-extern int do_proc_net_stat_conntrack(int update_every, unsigned long long dt);
-extern int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt);
-extern int do_proc_stat(int update_every, unsigned long long dt);
-extern int do_proc_meminfo(int update_every, unsigned long long dt);
-extern int do_proc_vmstat(int update_every, unsigned long long dt);
-extern int do_proc_net_rpc_nfs(int update_every, unsigned long long dt);
-extern int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt);
-extern int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt);
-extern int do_proc_interrupts(int update_every, unsigned long long dt);
-extern int do_proc_softirqs(int update_every, unsigned long long dt);
-extern int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt);
-extern int do_proc_loadavg(int update_every, unsigned long long dt);
-extern int do_proc_net_stat_synproxy(int update_every, unsigned long long dt);
-extern int do_proc_net_softnet_stat(int update_every, unsigned long long dt);
+extern int do_proc_net_dev(int update_every, usec_t dt);
+extern int do_proc_diskstats(int update_every, usec_t dt);
+extern int do_proc_net_snmp(int update_every, usec_t dt);
+extern int do_proc_net_snmp6(int update_every, usec_t dt);
+extern int do_proc_net_netstat(int update_every, usec_t dt);
+extern int do_proc_net_stat_conntrack(int update_every, usec_t dt);
+extern int do_proc_net_ip_vs_stats(int update_every, usec_t dt);
+extern int do_proc_stat(int update_every, usec_t dt);
+extern int do_proc_meminfo(int update_every, usec_t dt);
+extern int do_proc_vmstat(int update_every, usec_t dt);
+extern int do_proc_net_rpc_nfs(int update_every, usec_t dt);
+extern int do_proc_net_rpc_nfsd(int update_every, usec_t dt);
+extern int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt);
+extern int do_proc_interrupts(int update_every, usec_t dt);
+extern int do_proc_softirqs(int update_every, usec_t dt);
+extern int do_sys_kernel_mm_ksm(int update_every, usec_t dt);
+extern int do_proc_loadavg(int update_every, usec_t dt);
+extern int do_proc_net_stat_synproxy(int update_every, usec_t dt);
+extern int do_proc_net_softnet_stat(int update_every, usec_t dt);
 
 #endif /* NETDATA_PLUGIN_PROC_H */
index 4053653233bb0f181e5723075999e1c8227a5b57..8036b632dc8fbf1ea00e390122bca6447e0fa397 100644 (file)
@@ -90,7 +90,7 @@ void *pluginsd_worker_thread(void *arg)
     char line[PLUGINSD_LINE_MAX + 1];
 
 #ifdef DETACH_PLUGINS_FROM_NETDATA
-    unsigned long long usec = 0, susec = 0;
+    usec_t usec = 0, susec = 0;
     struct timeval last = {0, 0} , now = {0, 0};
 #endif
 
@@ -185,7 +185,7 @@ void *pluginsd_worker_thread(void *arg)
                 }
 
                 if(likely(st->counter_done)) {
-                    unsigned long long microseconds = 0;
+                    usec_t microseconds = 0;
                     if(microseconds_txt && *microseconds_txt) microseconds = strtoull(microseconds_txt, NULL, 10);
                     if(microseconds) rrdset_next_usec(st, microseconds);
                     else rrdset_next(st);
@@ -341,17 +341,17 @@ void *pluginsd_worker_thread(void *arg)
             else if(likely(hash == STOPPING_WAKE_ME_UP_PLEASE_HASH && !strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE"))) {
                 error("PLUGINSD: '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);
 
-                gettimeofday(&now, NULL);
+                now_realtime_timeval(&now);
                 if(unlikely(!usec && !susec)) {
                     // our first run
-                    susec = cd->rrd_update_every * 1000000ULL;
+                    susec = cd->rrd_update_every * USEC_PER_SEC;
                 }
                 else {
                     // second+ run
-                    usec = usec_dt(&now, &last) - susec;
+                    usec = dt_usec(&now, &last) - susec;
                     error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec);
-                    if(unlikely(usec < (rrd_update_every * 1000000ULL / 2ULL))) susec = (rrd_update_every * 1000000ULL) - usec;
-                    else susec = rrd_update_every * 1000000ULL / 2ULL;
+                    if(unlikely(usec < (rrd_update_every * USEC_PER_SEC / 2ULL))) susec = (rrd_update_every * USEC_PER_SEC) - usec;
+                    else susec = rrd_update_every * USEC_PER_SEC / 2ULL;
                 }
 
                 error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
@@ -509,7 +509,7 @@ void *pluginsd_main(void *ptr) {
 
                 cd->enabled = enabled;
                 cd->update_every = (int) config_get_number(cd->id, "update every", rrd_update_every);
-                cd->started_t = time(NULL);
+                cd->started_t = now_realtime_sec();
 
                 char *def = "";
                 snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
index c359d1cfaffaa0fa220ec339032e909cf3944e0f..fe5b0556fa5dffff8c395bf9ee2ee4460464ab38 100644 (file)
@@ -39,7 +39,7 @@ static struct mountinfo *disk_mountinfo_root = NULL;
 
 static inline void mountinfo_reload(int force) {
     static time_t last_loaded = 0;
-    time_t now = time(NULL);
+    time_t now = now_realtime_sec();
 
     if(force || now - last_loaded >= NETDATA_RELOAD_MOUNTINFO_EVERY) {
 //#ifdef NETDATA_INTERNAL_CHECKS
@@ -129,9 +129,12 @@ struct mount_point_metadata {
     int do_inodes;
 };
 
-static inline void do_disk_space_stats(struct disk *d, const char *mount_point, const char *mount_source, const char *disk, const char *family, int update_every, unsigned long long dt) {
+static inline void do_disk_space_stats(struct mountinfo *mi, int update_every, usec_t dt) {
     (void)dt;
 
+    const char *family = mi->mount_point;
+    const char *disk = mi->persistent_id;
+
     static DICTIONARY *mount_points = NULL;
     int do_space, do_inodes;
 
@@ -139,62 +142,40 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
         mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
     }
 
-    if(unlikely(d)) {
-        // verify we collected the metrics for the right disk.
-        // if not the mountpoint has changed.
-
-        struct stat buff_stat;
-        if(unlikely(stat(mount_point, &buff_stat) == -1)) {
-            error("Failed to stat() for '%s' (disk '%s')", mount_point, disk);
-            return;
-        }
-        else if(unlikely(major(buff_stat.st_dev) != d->major || minor(buff_stat.st_dev) != d->minor)) {
-            error("Disk '%s' (disk '%s') switched major:minor", mount_point, disk);
-            freez(d->mount_point);
-            d->mount_point = NULL;
-            d->mount_point_hash = 0;
-            return;
-        }
-
-        do_space = d->do_space;
-        do_inodes = d->do_inodes;
-    }
-    else {
-        struct mount_point_metadata *m = dictionary_get(mount_points, mount_point);
-        if(unlikely(!m)) {
-            char var_name[4096 + 1];
-            snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", mount_point);
+    struct mount_point_metadata *m = dictionary_get(mount_points, mi->mount_point);
+    if(unlikely(!m)) {
+        char var_name[4096 + 1];
+        snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", mi->mount_point);
 
-            int def_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
-            int def_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
+        int def_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
+        int def_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
 
-            if(unlikely(is_mount_point_excluded(mount_point))) {
-                def_space = CONFIG_ONDEMAND_NO;
-                def_inodes = CONFIG_ONDEMAND_NO;
-            }
+        if(unlikely(is_mount_point_excluded(mi->mount_point))) {
+            def_space = CONFIG_ONDEMAND_NO;
+            def_inodes = CONFIG_ONDEMAND_NO;
+        }
 
-            do_space = config_get_boolean_ondemand(var_name, "space usage", def_space);
-            do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
+        do_space = config_get_boolean_ondemand(var_name, "space usage", def_space);
+        do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
 
-            struct mount_point_metadata mp = {
-                .do_space = do_space,
-                .do_inodes = do_inodes
-            };
+        struct mount_point_metadata mp = {
+            .do_space = do_space,
+            .do_inodes = do_inodes
+        };
 
-            dictionary_set(mount_points, mount_point, &mp, sizeof(struct mount_point_metadata));
-        }
-        else {
-            do_space = m->do_space;
-            do_inodes = m->do_inodes;
-        }
+        dictionary_set(mount_points, mi->mount_point, &mp, sizeof(struct mount_point_metadata));
+    }
+    else {
+        do_space = m->do_space;
+        do_inodes = m->do_inodes;
     }
 
     if(unlikely(do_space == CONFIG_ONDEMAND_NO && do_inodes == CONFIG_ONDEMAND_NO))
         return;
 
     struct statvfs buff_statvfs;
-    if (statvfs(mount_point, &buff_statvfs) < 0) {
-        error("Failed statvfs() for '%s' (disk '%s')", mount_point, disk);
+    if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
+        error("Failed statvfs() for '%s' (disk '%s')", mi->mount_point, disk);
         return;
     }
 
@@ -213,7 +194,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
 
 #ifdef NETDATA_INTERNAL_CHECKS
     if(unlikely(btotal != bavail + breserved_root + bused))
-        error("Disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mount_point, disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused);
+        error("Disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused);
 #endif
 
     // --------------------------------------------------------------------------
@@ -226,7 +207,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
 
 #ifdef NETDATA_INTERNAL_CHECKS
     if(unlikely(btotal != bavail + breserved_root + bused))
-        error("Disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused);
+        error("Disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused);
 #endif
 
     // --------------------------------------------------------------------------
@@ -237,7 +218,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
         st = rrdset_find_bytype("disk_space", disk);
         if(unlikely(!st)) {
             char title[4096 + 1];
-            snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mount_source);
+            snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mi->mount_source);
             st = rrdset_create("disk_space", disk, NULL, family, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED);
 
             rrddim_add(st, "avail", NULL, bsize, 1024*1024*1024, RRDDIM_ABSOLUTE);
@@ -246,9 +227,9 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
         }
         else rrdset_next(st);
 
-        rrddim_set(st, "avail", bavail);
-        rrddim_set(st, "used", bused);
-        rrddim_set(st, "reserved_for_root", breserved_root);
+        rrddim_set(st, "avail", (collected_number)bavail);
+        rrddim_set(st, "used", (collected_number)bused);
+        rrddim_set(st, "reserved_for_root", (collected_number)breserved_root);
         rrdset_done(st);
     }
 
@@ -258,7 +239,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
         st = rrdset_find_bytype("disk_inodes", disk);
         if(unlikely(!st)) {
             char title[4096 + 1];
-            snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mount_source);
+            snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mi->mount_source);
             st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED);
 
             rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
@@ -267,9 +248,9 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point,
         }
         else rrdset_next(st);
 
-        rrddim_set(st, "avail", favail);
-        rrddim_set(st, "used", fused);
-        rrddim_set(st, "reserved_for_root", freserved_root);
+        rrddim_set(st, "avail", (collected_number)favail);
+        rrddim_set(st, "used", (collected_number)fused);
+        rrddim_set(st, "reserved_for_root", (collected_number)freserved_root);
         rrdset_done(st);
     }
 }
@@ -430,7 +411,7 @@ static inline int select_positive_option(int option1, int option2) {
     return CONFIG_ONDEMAND_NO;
 }
 
-int do_proc_diskstats(int update_every, unsigned long long dt) {
+int do_proc_diskstats(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
@@ -862,15 +843,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
                 rrdset_done(st);
             }
         }
-
-/*
-        // --------------------------------------------------------------------------
-        // space metrics
-
-        if(unlikely( d->mount_point && (d->do_space || d->do_inodes) )) {
-            do_disk_space_stats(d, d->mount_point, disk, disk, family, update_every, dt);
-        }
-*/
     }
 
     // --------------------------------------------------------------------------
@@ -878,27 +850,10 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
 
     struct mountinfo *mi;
     for(mi = disk_mountinfo_root; mi ;mi = mi->next) {
-        if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY|MOUNTINFO_IS_BIND|MOUNTINFO_IS_SAME_DEV|MOUNTINFO_NO_STAT|MOUNTINFO_NO_SIZE)))
+        if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY|MOUNTINFO_IS_BIND|MOUNTINFO_IS_SAME_DEV|MOUNTINFO_NO_STAT|MOUNTINFO_NO_SIZE|MOUNTINFO_READONLY)))
             continue;
 
-/*
-        // skip the ones with block devices
-        int skip = 0;
-        struct disk *d;
-        for(d = disk_root; d ;d = d->next) {
-            if(unlikely(d->mount_point && mi->mount_point_hash == d->mount_point_hash && strcmp(mi->mount_point, d->mount_point))) {
-                skip = 1;
-                break;
-            }
-        }
-
-        if(unlikely(skip))
-            continue;
-
-        // fprintf(stderr, "Will process mount point '%s', source '%s', filesystem '%s'\n", mi->mount_point, mi->mount_source, mi->filesystem);
-*/
-
-        do_disk_space_stats(NULL, mi->mount_point, mi->mount_source, mi->persistent_id, mi->mount_point , update_every, dt);
+        do_disk_space_stats(mi, update_every, dt);
     }
 
     return 0;
index 14215de68a24f497f208f72694ddffb60fe692cf..46f534c518e0cf60dc8be8d183e62983b7748044 100644 (file)
@@ -2,36 +2,54 @@
 
 #define MAX_INTERRUPT_NAME 50
 
+struct cpu_interrupt {
+    unsigned long long value;
+    RRDDIM *rd;
+};
+
 struct interrupt {
     int used;
     char *id;
     char name[MAX_INTERRUPT_NAME + 1];
+    RRDDIM *rd;
     unsigned long long total;
-    unsigned long long value[];
+    struct cpu_interrupt cpu[];
 };
 
 // since each interrupt is variable in size
 // we use this to calculate its record size
-#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(unsigned long long)))
+#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(struct cpu_interrupt)))
 
 // given a base, get a pointer to each record
 #define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[line * recordsize(cpus)])
 
-static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
+static inline struct interrupt *get_interrupts_array(uint32_t lines, int cpus) {
     static struct interrupt *irrs = NULL;
-    static int allocated = 0;
+    static uint32_t allocated = 0;
+
+    if(unlikely(lines != allocated)) {
+        uint32_t l;
+        int c;
 
-    if(unlikely(lines > allocated)) {
         irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
+
+        // reset all interrupt RRDDIM pointers as any line could have shifted
+        for(l = 0; l < lines ;l++) {
+            struct interrupt *irr = irrindex(irrs, l, cpus);
+            irr->rd = NULL;
+            irr->name[0] = '\0';
+            for(c = 0; c < cpus ;c++)
+                irr->cpu[c].rd = NULL;
+        }
+
         allocated = lines;
     }
 
     return irrs;
 }
 
-int do_proc_interrupts(int update_every, unsigned long long dt) {
+int do_proc_interrupts(int update_every, usec_t dt) {
     (void)dt;
-
     static procfile *ff = NULL;
     static int cpus = -1, do_per_core = -1;
     struct interrupt *irrs = NULL;
@@ -64,7 +82,7 @@ int do_proc_interrupts(int update_every, unsigned long long dt) {
         uint32_t w;
         cpus = 0;
         for(w = 0; w < words ; w++) {
-            if(unlikely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
+            if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
                 cpus++;
         }
     }
@@ -96,20 +114,25 @@ int do_proc_interrupts(int update_every, unsigned long long dt) {
 
         int c;
         for(c = 0; c < cpus ;c++) {
-            if(unlikely((c + 1) < (int)words))
-                irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
+            if(likely((c + 1) < (int)words))
+                irr->cpu[c].value = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
             else
-                irr->value[c] = 0;
+                irr->cpu[c].value = 0;
 
-            irr->total += irr->value[c];
+            irr->total += irr->cpu[c].value;
         }
 
         if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) {
             strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME);
             int nlen = strlen(irr->name);
-            if(unlikely(nlen < (MAX_INTERRUPT_NAME-1))) {
+            int idlen = strlen(irr->id);
+            if(likely(nlen + 1 + idlen <= MAX_INTERRUPT_NAME)) {
                 irr->name[nlen] = '_';
-                strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen);
+                strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen - 1);
+            }
+            else {
+                irr->name[MAX_INTERRUPT_NAME - idlen - 1] = '_';
+                strncpyz(&irr->name[MAX_INTERRUPT_NAME - idlen], irr->id, idlen);
             }
         }
         else {
@@ -124,28 +147,37 @@ int do_proc_interrupts(int update_every, unsigned long long dt) {
     // --------------------------------------------------------------------
 
     st = rrdset_find_bytype("system", "interrupts");
-    if(unlikely(!st)) {
-        st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED);
-
-        for(l = 0; l < lines ;l++) {
-            struct interrupt *irr = irrindex(irrs, l, cpus);
-            if(unlikely(!irr->used)) continue;
-            rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
-        }
-    }
+    if(unlikely(!st)) st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED);
     else rrdset_next(st);
 
     for(l = 0; l < lines ;l++) {
         struct interrupt *irr = irrindex(irrs, l, cpus);
         if(unlikely(!irr->used)) continue;
-        rrddim_set(st, irr->id, irr->total);
+        // some interrupt may have changed without changing the total number of lines
+        // if the same number of interrupts have been added and removed between two
+        // calls of this function.
+        if(unlikely(!irr->rd || strncmp(irr->rd->name, irr->name, MAX_INTERRUPT_NAME) != 0)) {
+            irr->rd = rrddim_find(st, irr->id);
+            if(unlikely(!irr->rd))
+                irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+            else
+                rrddim_set_name(st, irr->rd, irr->name);
+
+            // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
+            if(likely(do_per_core)) {
+                int c;
+                for (c = 0; c < cpus ;c++)
+                    irr->cpu[c].rd = NULL;
+            }
+        }
+        rrddim_set_by_pointer(st, irr->rd, irr->total);
     }
     rrdset_done(st);
 
     if(likely(do_per_core)) {
         int c;
 
-        for(c = 0; c < cpus ; c++) {
+        for(c = 0; c < cpus ;c++) {
             char id[50+1];
             snprintfz(id, 50, "cpu%d_interrupts", c);
 
@@ -154,19 +186,20 @@ int do_proc_interrupts(int update_every, unsigned long long dt) {
                 char title[100+1];
                 snprintfz(title, 100, "CPU%d Interrupts", c);
                 st = rrdset_create("cpu", id, NULL, "interrupts", "cpu.interrupts", title, "interrupts/s", 1100 + c, update_every, RRDSET_TYPE_STACKED);
-
-                for(l = 0; l < lines ;l++) {
-                    struct interrupt *irr = irrindex(irrs, l, cpus);
-                    if(unlikely(!irr->used)) continue;
-                    rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
-                }
             }
             else rrdset_next(st);
 
             for(l = 0; l < lines ;l++) {
                 struct interrupt *irr = irrindex(irrs, l, cpus);
                 if(unlikely(!irr->used)) continue;
-                rrddim_set(st, irr->id, irr->value[c]);
+                if(unlikely(!irr->cpu[c].rd)) {
+                    irr->cpu[c].rd = rrddim_find(st, irr->id);
+                    if(unlikely(!irr->cpu[c].rd))
+                        irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+                    else
+                        rrddim_set_name(st, irr->cpu[c].rd, irr->name);
+                }
+                rrddim_set_by_pointer(st, irr->cpu[c].rd, irr->cpu[c].value);
             }
             rrdset_done(st);
         }
index a3d75ac53b9b717bb05a1f556912c0a814d5f070..c0f3902c8555cdefbda7755afc3906cc8eee7a1f 100644 (file)
@@ -3,12 +3,12 @@
 // linux calculates this once every 5 seconds
 #define MIN_LOADAVG_UPDATE_EVERY 5
 
-int do_proc_loadavg(int update_every, unsigned long long dt) {
+int do_proc_loadavg(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
     static int do_loadavg = -1, do_all_processes = -1;
-    static unsigned long long last_loadavg_usec = 0;
+    static usec_t last_loadavg_usec = 0;
     static RRDSET *load_chart = NULL, *processes_chart = NULL;
 
     if(unlikely(!ff)) {
@@ -68,7 +68,7 @@ int do_proc_loadavg(int update_every, unsigned long long dt) {
             rrdset_done(load_chart);
         }
 
-        last_loadavg_usec = load_chart->update_every * 1000000ULL;
+        last_loadavg_usec = load_chart->update_every * USEC_PER_SEC;
     }
     else last_loadavg_usec -= dt;
 
index 11b41be7bd3dc7ce9d178ce5a4fa3541fe6bfcc3..feed5d88d99036fe2a665af707bd5b3736196c76 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-int do_proc_meminfo(int update_every, unsigned long long dt) {
+int do_proc_meminfo(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index 33d140c471f1c97254b4793b769639b2ee8cdd64..06182d44ff9559f8a15673f7c9cbee853d6ec859 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-int do_proc_net_dev(int update_every, unsigned long long dt) {
+int do_proc_net_dev(int update_every, usec_t dt) {
     static procfile *ff = NULL;
     static int enable_new_interfaces = -1, enable_ifb_interfaces = -1;
     static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
index de3e0e460cdd1b750d72e0f5e04a4c56b9213bef..3513a25f1d3d7279736238f2a292942f2c5c7509 100644 (file)
@@ -3,7 +3,7 @@
 #define RRD_TYPE_NET_IPVS           "ipvs"
 #define RRD_TYPE_NET_IPVS_LEN       strlen(RRD_TYPE_NET_IPVS)
 
-int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt) {
+int do_proc_net_ip_vs_stats(int update_every, usec_t dt) {
     static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
     static procfile *ff = NULL;
 
index 00d26635f90c7e9e00e3b1cc1aa447a4636bdb98..14ac4ebb6d9842fa974136146394b326ea5aa8e4 100644 (file)
@@ -191,7 +191,7 @@ static void parse_line_pair(procfile *ff, struct netstat_columns *nc, uint32_t h
 }
 
 
-int do_proc_net_netstat(int update_every, unsigned long long dt) {
+int do_proc_net_netstat(int update_every, usec_t dt) {
     (void)dt;
 
     static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
index 86e2f70c0d23a74f8f1e1a9edf2ab2281ef93663..b1c500f2b53f0050ec456db9821f4965f4012195 100644 (file)
@@ -127,7 +127,7 @@ struct nfs_procs nfs_proc4_values[] = {
     { "", 0ULL, 0 }
 };
 
-int do_proc_net_rpc_nfs(int update_every, unsigned long long dt) {
+int do_proc_net_rpc_nfs(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index e0092c722d6ac15e8556303df8b411990c718978..863552056a2807e2348c5da8e9423108a4f04332 100644 (file)
@@ -209,7 +209,7 @@ struct nfsd_procs nfsd4_ops_values[] = {
 };
 
 
-int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt) {
+int do_proc_net_rpc_nfsd(int update_every, usec_t dt) {
     static procfile *ff = NULL;
     static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1;
     static int ra_warning = 0, th_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0;
index 3ef111ba89e398471b68d0018f2c859f88dc0276..d7318fc817f8dda94a4a447430e1cc7c4ee59772 100644 (file)
@@ -197,7 +197,7 @@ static void parse_line_pair(procfile *ff, struct netstat_columns *nc, uint32_t h
     }
 }
 
-int do_proc_net_snmp(int update_every, unsigned long long dt) {
+int do_proc_net_snmp(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index b7ec65c08cb9e967bac8e0db6a4c9d2759b02ec8..512943bd73e761bda7d652c4175e7f74bc04b1dc 100644 (file)
@@ -3,7 +3,7 @@
 #define RRD_TYPE_NET_SNMP6          "ipv6"
 #define RRD_TYPE_NET_SNMP6_LEN      strlen(RRD_TYPE_NET_SNMP6)
 
-int do_proc_net_snmp6(int update_every, unsigned long long dt) {
+int do_proc_net_snmp6(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index 0187dbbc3f50a2936529f409aa716c4e4fa90497..7fe5b7d5dcd47cc3aea20e8f677ec6c8620f1e18 100644 (file)
@@ -12,7 +12,7 @@ static inline char *softnet_column_name(uint32_t column) {
     }
 }
 
-int do_proc_net_softnet_stat(int update_every, unsigned long long dt) {
+int do_proc_net_softnet_stat(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index c61a4f3582a3c275d8150051d2eae3b5bc392ac2..3ccc96260886d0e41dad30c7c37bf2cdd8189349 100644 (file)
@@ -3,10 +3,10 @@
 #define RRD_TYPE_NET_STAT_NETFILTER     "netfilter"
 #define RRD_TYPE_NET_STAT_CONNTRACK     "conntrack"
 
-int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
+int do_proc_net_stat_conntrack(int update_every, usec_t dt) {
     static procfile *ff = NULL;
     static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
-    static unsigned long long get_max_every = 10 * 1000000ULL, usec_since_last_max = 0;
+    static usec_t get_max_every = 10 * USEC_PER_SEC, usec_since_last_max = 0;
     static int read_full = 1;
     static char *nf_conntrack_filename, *nf_conntrack_count_filename, *nf_conntrack_max_filename;
     static RRDVAR *rrdvar_max = NULL;
@@ -21,7 +21,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
 
         snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/net/netfilter/nf_conntrack_max");
         nf_conntrack_max_filename = config_get("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "filename to monitor", filename);
-        usec_since_last_max = get_max_every = config_get_number("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "read every seconds", 10) * 1000000ULL;
+        usec_since_last_max = get_max_every = config_get_number("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "read every seconds", 10) * USEC_PER_SEC;
 
         read_full = 1;
         ff = procfile_open(nf_conntrack_filename, " \t:", PROCFILE_FLAG_DEFAULT);
index 01c91978b50d31424080548935522da806d1f304..c3ac00b5d7037d7938f8a1caab099113127bd4b9 100644 (file)
@@ -3,7 +3,7 @@
 #define RRD_TYPE_NET_STAT_NETFILTER         "netfilter"
 #define RRD_TYPE_NET_STAT_SYNPROXY          "synproxy"
 
-int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) {
+int do_proc_net_stat_synproxy(int update_every, usec_t dt) {
     (void)dt;
 
     static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
index a63f046604ed2eb6702a165f6b11c6f7c72ed0e8..7c1d315585cffa87fa4aa07849e8591500da3b2f 100644 (file)
@@ -157,6 +157,21 @@ static char *strdupz_decoding_octal(const char *string) {
     return buffer;
 }
 
+static inline int is_read_only(const char *s) {
+    if(!s) return 0;
+
+    size_t len = strlen(s);
+    if(len < 2) return 0;
+    if(len == 2) {
+        if(!strcmp(s, "ro")) return 1;
+        return 0;
+    }
+    if(!strncmp(s, "ro,", 3)) return 1;
+    if(!strncmp(&s[len - 3], ",ro", 3)) return 1;
+    if(strstr(s, ",ro,")) return 1;
+    return 0;
+}
+
 // read the whole mountinfo into a linked list
 struct mountinfo *mountinfo_read() {
     char filename[FILENAME_MAX + 1];
@@ -214,6 +229,9 @@ struct mountinfo *mountinfo_read() {
 
         mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
 
+        if(unlikely(is_read_only(mi->mount_options)))
+            mi->flags |= MOUNTINFO_READONLY;
+
         // count the optional fields
 /*
         unsigned long wo = w;
@@ -254,6 +272,9 @@ struct mountinfo *mountinfo_read() {
 
             mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
 
+            if(unlikely(is_read_only(mi->super_options)))
+                mi->flags |= MOUNTINFO_READONLY;
+
             if(unlikely(ME_DUMMY(mi->mount_source, mi->filesystem)))
                 mi->flags |= MOUNTINFO_IS_DUMMY;
 
index d47b6112562f70dca15331a1828d1e5bffa2aba8..53f4456498f4340994af1e6e1e55f6be8e9aa50a 100644 (file)
@@ -7,6 +7,7 @@
 #define MOUNTINFO_IS_SAME_DEV   0x00000008
 #define MOUNTINFO_NO_STAT       0x00000010
 #define MOUNTINFO_NO_SIZE       0x00000020
+#define MOUNTINFO_READONLY      0x00000040
 
 struct mountinfo {
     long id;                // mount ID: unique identifier of the mount (may be reused after umount(2)).
index 818a6a7098294c950ce1517e9215ae632b4ddaac..a6e77fc309cb7c79dbba5efbd66a96d3e9c57698 100644 (file)
@@ -2,39 +2,56 @@
 
 #define MAX_INTERRUPT_NAME 50
 
+struct cpu_interrupt {
+    unsigned long long value;
+    RRDDIM *rd;
+};
+
 struct interrupt {
     int used;
     char *id;
     char name[MAX_INTERRUPT_NAME + 1];
+    RRDDIM *rd;
     unsigned long long total;
-    unsigned long long value[];
+    struct cpu_interrupt cpu[];
 };
 
 // since each interrupt is variable in size
 // we use this to calculate its record size
-#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(unsigned long long)))
+#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(struct cpu_interrupt)))
 
 // given a base, get a pointer to each record
 #define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[line * recordsize(cpus)])
 
-static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
+static inline struct interrupt *get_interrupts_array(uint32_t lines, int cpus) {
     static struct interrupt *irrs = NULL;
-    static int allocated = 0;
+    static uint32_t allocated = 0;
+
+    if(unlikely(lines != allocated)) {
+        uint32_t l;
+        int c;
 
-    if(unlikely(lines > allocated)) {
         irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
+
+        // reset all interrupt RRDDIM pointers as any line could have shifted
+        for(l = 0; l < lines ;l++) {
+            struct interrupt *irr = irrindex(irrs, l, cpus);
+            irr->rd = NULL;
+            irr->name[0] = '\0';
+            for(c = 0; c < cpus ;c++)
+                irr->cpu[c].rd = NULL;
+        }
+
         allocated = lines;
     }
 
     return irrs;
 }
 
-int do_proc_softirqs(int update_every, unsigned long long dt) {
+int do_proc_softirqs(int update_every, usec_t dt) {
     (void)dt;
-
     static procfile *ff = NULL;
     static int cpus = -1, do_per_core = -1;
-
     struct interrupt *irrs = NULL;
 
     if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
@@ -62,7 +79,7 @@ int do_proc_softirqs(int update_every, unsigned long long dt) {
         uint32_t w;
         cpus = 0;
         for(w = 0; w < words ; w++) {
-            if(unlikely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
+            if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
                 cpus++;
         }
     }
@@ -94,12 +111,12 @@ int do_proc_softirqs(int update_every, unsigned long long dt) {
 
         int c;
         for(c = 0; c < cpus ;c++) {
-            if(unlikely((c + 1) < (int)words))
-                irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
+            if(likely((c + 1) < (int)words))
+                irr->cpu[c].value = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
             else
-                irr->value[c] = 0;
+                irr->cpu[c].value = 0;
 
-            irr->total += irr->value[c];
+            irr->total += irr->cpu[c].value;
         }
 
         strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
@@ -112,21 +129,30 @@ int do_proc_softirqs(int update_every, unsigned long long dt) {
     // --------------------------------------------------------------------
 
     st = rrdset_find_bytype("system", "softirqs");
-    if(unlikely(!st)) {
-        st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED);
-
-        for(l = 0; l < lines ;l++) {
-            struct interrupt *irr = irrindex(irrs, l, cpus);
-            if(unlikely(!irr->used)) continue;
-            rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
-        }
-    }
+    if(unlikely(!st)) st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED);
     else rrdset_next(st);
 
     for(l = 0; l < lines ;l++) {
         struct interrupt *irr = irrindex(irrs, l, cpus);
         if(unlikely(!irr->used)) continue;
-        rrddim_set(st, irr->id, irr->total);
+        // some interrupt may have changed without changing the total number of lines
+        // if the same number of interrupts have been added and removed between two
+        // calls of this function.
+        if(unlikely(!irr->rd || strncmp(irr->name, irr->rd->name, MAX_INTERRUPT_NAME) != 0)) {
+            irr->rd = rrddim_find(st, irr->id);
+            if(unlikely(!irr->rd))
+                irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+            else
+                rrddim_set_name(st, irr->rd, irr->name);
+
+            // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
+            if(likely(do_per_core)) {
+                int c;
+                for (c = 0; c < cpus ;c++)
+                    irr->cpu[c].rd = NULL;
+            }
+        }
+        rrddim_set_by_pointer(st, irr->rd, irr->total);
     }
     rrdset_done(st);
 
@@ -144,26 +170,27 @@ int do_proc_softirqs(int update_every, unsigned long long dt) {
                 for(l = 0; l < lines ;l++) {
                     struct interrupt *irr = irrindex(irrs, l, cpus);
                     if(unlikely(!irr->used)) continue;
-                    core_sum += irr->value[c];
+                    core_sum += irr->cpu[c].value;
                 }
                 if(unlikely(core_sum == 0)) continue; // try next core
 
                 char title[100+1];
                 snprintfz(title, 100, "CPU%d softirqs", c);
                 st = rrdset_create("cpu", id, NULL, "softirqs", "cpu.softirqs", title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);
-
-                for(l = 0; l < lines ;l++) {
-                    struct interrupt *irr = irrindex(irrs, l, cpus);
-                    if(unlikely(!irr->used)) continue;
-                    rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
-                }
             }
             else rrdset_next(st);
 
             for(l = 0; l < lines ;l++) {
                 struct interrupt *irr = irrindex(irrs, l, cpus);
                 if(unlikely(!irr->used)) continue;
-                rrddim_set(st, irr->id, irr->value[c]);
+                if(unlikely(!irr->cpu[c].rd)) {
+                    irr->cpu[c].rd = rrddim_find(st, irr->id);
+                    if(unlikely(!irr->cpu[c].rd))
+                        irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+                    else
+                        rrddim_set_name(st, irr->cpu[c].rd, irr->name);
+                }
+                rrddim_set_by_pointer(st, irr->cpu[c].rd, irr->cpu[c].value);
             }
             rrdset_done(st);
         }
index 0e34f2eeec8017123fb352121eacc701c3b3d0ef..1a9b7a7fc02d04fdea4fc386fb9eb59ca6499fcf 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-int do_proc_stat(int update_every, unsigned long long dt) {
+int do_proc_stat(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index bde74f452196b7f35e2ee3e7c1e28793c56e1303..5c0893e351016cdd48a8349c55effb61d400e20c 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt) {
+int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index a8058398409077a2db021c43405e6794e0cc2672..2f4472a919a27152b68f07cb5d202934484012ea 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-int do_proc_vmstat(int update_every, unsigned long long dt) {
+int do_proc_vmstat(int update_every, usec_t dt) {
     (void)dt;
 
     static procfile *ff = NULL;
index bce7c348fa0339933f98c20070fb8f1890eb5d8c..b47bdd225f6c6de6b4c587a73013d6c80630648d 100644 (file)
@@ -1010,7 +1010,7 @@ const char *registry_to_announce(void) {
 
 void registry_set_cookie(struct web_client *w, const char *guid) {
     char edate[100];
-    time_t et = time(NULL) + registry.persons_expiration;
+    time_t et = now_realtime_sec() + registry.persons_expiration;
     struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
     strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
 
index 52de637bccf97c1b0bdd16a744ed4db030ccbf34..f24602e3934306cd6a291ecb5d3db5d36e35ad0a 100644 (file)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -56,7 +56,7 @@ RRDHOST localhost = {
 void rrdhost_init(char *hostname) {
     localhost.hostname = hostname;
     localhost.health_log.next_log_id =
-        localhost.health_log.next_alarm_id = time(NULL);
+        localhost.health_log.next_alarm_id = now_realtime_sec();
 }
 
 void rrdhost_rwlock(RRDHOST *host) {
@@ -525,7 +525,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
             error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
             memset(st, 0, size);
         }
-        else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) {
+        else if((now_realtime_sec() - st->last_updated.tv_sec) > update_every * entries) {
             errno = 0;
             error("File %s is too old. Clearing it.", fullfilename);
             memset(st, 0, size);
@@ -653,7 +653,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
     if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
     if(rd) {
         struct timeval now;
-        gettimeofday(&now, NULL);
+        now_realtime_timeval(&now);
 
         if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) {
             errno = 0;
@@ -685,7 +685,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
             error("File %s does not have the same refresh frequency. Clearing it.", fullfilename);
             memset(rd, 0, size);
         }
-        else if(usec_dt(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * 1000000ULL)) {
+        else if(dt_usec(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * USEC_PER_SEC)) {
             errno = 0;
             error("File %s is too old. Clearing it.", fullfilename);
             memset(rd, 0, size);
@@ -977,7 +977,7 @@ collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number
 {
     debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value);
 
-    gettimeofday(&rd->last_collected_time, NULL);
+    now_realtime_timeval(&rd->last_collected_time);
     rd->collected_value = value;
     rd->updated = 1;
     rd->counter++;
@@ -998,33 +998,33 @@ collected_number rrddim_set(RRDSET *st, const char *id, collected_number value)
     return rrddim_set_by_pointer(st, rd, value);
 }
 
-void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds)
+void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds)
 {
     if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) {
         // the first entry
-        microseconds = st->update_every * 1000000ULL;
+        microseconds = st->update_every * USEC_PER_SEC;
     }
     st->usec_since_last_update = microseconds;
 }
 
-void rrdset_next_usec(RRDSET *st, unsigned long long microseconds)
+void rrdset_next_usec(RRDSET *st, usec_t microseconds)
 {
     struct timeval now;
-    gettimeofday(&now, NULL);
+    now_realtime_timeval(&now);
 
     if(unlikely(!st->last_collected_time.tv_sec)) {
         // the first entry
-        microseconds = st->update_every * 1000000ULL;
+        microseconds = st->update_every * USEC_PER_SEC;
     }
     else if(unlikely(!microseconds)) {
         // no dt given by the plugin
-        microseconds = usec_dt(&now, &st->last_collected_time);
+        microseconds = dt_usec(&now, &st->last_collected_time);
     }
     else {
         // microseconds has the time since the last collection
-        unsigned long long now_usec = timeval_usec(&now);
-        unsigned long long last_usec = timeval_usec(&st->last_collected_time);
-        unsigned long long since_last_usec = usec_dt(&now, &st->last_collected_time);
+        usec_t now_usec = timeval_usec(&now);
+        usec_t last_usec = timeval_usec(&st->last_collected_time);
+        usec_t since_last_usec = dt_usec(&now, &st->last_collected_time);
 
         // verify the microseconds given is good
         if(unlikely(microseconds > since_last_usec)) {
@@ -1052,7 +1052,7 @@ void rrdset_next_usec(RRDSET *st, unsigned long long microseconds)
     st->usec_since_last_update = microseconds;
 }
 
-unsigned long long rrdset_done(RRDSET *st)
+usec_t rrdset_done(RRDSET *st)
 {
     if(unlikely(netdata_exit)) return 0;
 
@@ -1070,12 +1070,12 @@ unsigned long long rrdset_done(RRDSET *st)
     unsigned int
         stored_entries = 0;     // the number of entries we have stored in the db, during this call to rrdset_done()
 
-    unsigned long long
+    usec_t
         last_collect_ut,        // the timestamp in microseconds, of the last collected value
         now_collect_ut,         // the timestamp in microseconds, of this collected value (this is NOW)
         last_stored_ut,         // the timestamp in microseconds, of the last stored entry in the db
         next_store_ut,          // the timestamp in microseconds, of the next entry to store in the db
-        update_every_ut = st->update_every * 1000000ULL; // st->update_every in microseconds
+        update_every_ut = st->update_every * USEC_PER_SEC; // st->update_every in microseconds
 
     if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0))
         error("Cannot set pthread cancel state to DISABLE.");
@@ -1102,10 +1102,10 @@ unsigned long long rrdset_done(RRDSET *st)
     if(unlikely(!st->last_collected_time.tv_sec)) {
         // it is the first entry
         // set the last_collected_time to now
-        gettimeofday(&st->last_collected_time, NULL);
+        now_realtime_timeval(&st->last_collected_time);
         timeval_align(&st->last_collected_time, st->update_every);
 
-        last_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - update_every_ut;
+        last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - update_every_ut;
 
         // the first entry should not be stored
         store_this_entry = 0;
@@ -1116,10 +1116,10 @@ unsigned long long rrdset_done(RRDSET *st)
     else {
         // it is not the first entry
         // calculate the proper last_collected_time, using usec_since_last_update
-        last_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
-        unsigned long long ut = last_collect_ut + st->usec_since_last_update;
-        st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL);
-        st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL);
+        last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
+        usec_t ut = last_collect_ut + st->usec_since_last_update;
+        st->last_collected_time.tv_sec = (time_t) (ut / USEC_PER_SEC);
+        st->last_collected_time.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
     }
 
     // if this set has not been updated in the past
@@ -1127,9 +1127,9 @@ unsigned long long rrdset_done(RRDSET *st)
     if(unlikely(!st->last_updated.tv_sec)) {
         // it has never been updated before
         // set a fake last_updated, in the past using usec_since_last_update
-        unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
-        st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
-        st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
+        usec_t ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - st->usec_since_last_update;
+        st->last_updated.tv_sec = (time_t) (ut / USEC_PER_SEC);
+        st->last_updated.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
 
         // the first entry should not be stored
         store_this_entry = 0;
@@ -1139,18 +1139,18 @@ unsigned long long rrdset_done(RRDSET *st)
     }
 
     // check if we will re-write the entire data set
-    if(unlikely(usec_dt(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) {
+    if(unlikely(dt_usec(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) {
         info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Reseting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec);
         rrdset_reset(st);
 
         st->usec_since_last_update = update_every_ut;
 
-        gettimeofday(&st->last_collected_time, NULL);
+        now_realtime_timeval(&st->last_collected_time);
         timeval_align(&st->last_collected_time, st->update_every);
 
-        unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
-        st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
-        st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
+        usec_t ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - st->usec_since_last_update;
+        st->last_updated.tv_sec = (time_t) (ut / USEC_PER_SEC);
+        st->last_updated.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
 
         // the first entry should not be stored
         store_this_entry = 0;
@@ -1161,9 +1161,9 @@ unsigned long long rrdset_done(RRDSET *st)
     // last_stored_ut = the last time we added a value to the storage
     // now_collect_ut = the time the current value has been collected
     // next_store_ut  = the time of the next interpolation point
-    last_stored_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec;
-    now_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
-    next_store_ut  = (st->last_updated.tv_sec + st->update_every) * 1000000ULL;
+    last_stored_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec;
+    now_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
+    next_store_ut  = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC;
 
     if(unlikely(st->debug)) {
         debug(D_RRD_STATS, "%s: last_collect_ut = %0.3Lf (last collection time)", st->name, (long double)last_collect_ut/1000000.0);
@@ -1366,7 +1366,7 @@ unsigned long long rrdset_done(RRDSET *st)
 #endif
     }
 
-    unsigned long long first_ut = last_stored_ut;
+    usec_t first_ut = last_stored_ut;
     long long iterations = (now_collect_ut - last_stored_ut) / (update_every_ut);
     if((now_collect_ut % (update_every_ut)) == 0) iterations++;
 
@@ -1380,7 +1380,7 @@ unsigned long long rrdset_done(RRDSET *st)
             debug(D_RRD_STATS, "%s: next_store_ut  = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0);
         }
 
-        st->last_updated.tv_sec = (time_t) (next_store_ut / 1000000ULL);
+        st->last_updated.tv_sec = (time_t) (next_store_ut / USEC_PER_SEC);
         st->last_updated.tv_usec = 0;
 
         for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
index f0d86540ddd62bb321438b4df7b229cde17d0c68..dbaf986503675fde06923ddc66d01024e08c5b23 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -244,7 +244,7 @@ struct rrdset {
 
     uint32_t hash_name;                             // a simple hash on the name
 
-    unsigned long long usec_since_last_update;      // the time in microseconds since the last collection of data
+    usec_t usec_since_last_update;                  // the time in microseconds since the last collection of data
 
     struct timeval last_updated;                    // when this data set was last updated (updated every time the rrd_stats_done() function)
     struct timeval last_collected_time;             // when did this data set last collected values
@@ -355,11 +355,11 @@ extern RRDSET *rrdset_find(const char *id);
 extern RRDSET *rrdset_find_bytype(const char *type, const char *id);
 extern RRDSET *rrdset_find_byname(const char *name);
 
-extern void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds);
-extern void rrdset_next_usec(RRDSET *st, unsigned long long microseconds);
+extern void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds);
+extern void rrdset_next_usec(RRDSET *st, usec_t microseconds);
 #define rrdset_next(st) rrdset_next_usec(st, 0ULL)
 
-extern unsigned long long rrdset_done(RRDSET *st);
+extern usec_t rrdset_done(RRDSET *st);
 
 // get the total duration in seconds of the round robin database
 #define rrdset_duration(st) ((time_t)( (((st)->counter >= ((unsigned long)(st)->entries))?(unsigned long)(st)->entries:(st)->counter) * (st)->update_every ))
index d4a200fec7747363fe8aeae59679fe555450d461..c7a46982bb83437cee3cb3ee31a2e7f86bb3050f 100644 (file)
@@ -127,7 +127,7 @@ void rrd_stats_api_v1_charts(BUFFER *wb)
 
 unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb)
 {
-    time_t now = time(NULL);
+    time_t now = now_realtime_sec();
 
     pthread_rwlock_rdlock(&st->rwlock);
 
index cef7cb449c2bcb93c1edcffd4581622e374cb647..a42178efc3188d14f406880460a712d7a62e7d2d 100644 (file)
@@ -1391,12 +1391,12 @@ void update_cgroup_charts(int update_every) {
 // ----------------------------------------------------------------------------
 // cgroups main
 
-int do_sys_fs_cgroup(int update_every, unsigned long long dt) {
+int do_sys_fs_cgroup(int update_every, usec_t dt) {
     (void)dt;
 
     static int cgroup_global_config_read = 0;
     static time_t last_run = 0;
-    time_t now = time(NULL);
+    time_t now = now_realtime_sec();
 
     if(unlikely(!cgroup_global_config_read)) {
         read_cgroup_plugin_configuration();
@@ -1433,24 +1433,24 @@ void *cgroups_main(void *ptr)
     int vdo_cpu_netdata             = !config_get_boolean("plugin:cgroups", "cgroups plugin resources", 1);
 
     // keep track of the time each module was called
-    unsigned long long sutime_sys_fs_cgroup = 0ULL;
+    usec_t sutime_sys_fs_cgroup = 0ULL;
 
     // the next time we will run - aligned properly
-    unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
+    usec_t sunext = (now_realtime_sec() - (now_realtime_sec() % rrd_update_every) + rrd_update_every) * USEC_PER_SEC;
 
     RRDSET *stcpu_thread = NULL;
 
     for(;;) {
-        unsigned long long sunow;
+        usec_t sunow;
         if(unlikely(netdata_exit)) break;
 
         // delay until it is our time to run
-        while((sunow = time_usec()) < sunext)
+        while((sunow = now_realtime_usec()) < sunext)
             sleep_usec(sunext - sunow);
 
         // find the next time we need to run
-        while(time_usec() > sunext)
-            sunext += rrd_update_every * 1000000ULL;
+        while(now_realtime_usec() > sunext)
+            sunext += rrd_update_every * USEC_PER_SEC;
 
         if(unlikely(netdata_exit)) break;
 
@@ -1458,7 +1458,7 @@ void *cgroups_main(void *ptr)
 
         if(!vdo_sys_fs_cgroup) {
             debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
-            sunow = time_usec();
+            sunow = now_realtime_usec();
             vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
             sutime_sys_fs_cgroup = sunow;
         }
index 8c51be1df5e0b08337b61656d2682634eefdf35f..727bca3e575b2622264fade50e8d7c2d990e7526 100644 (file)
@@ -19,7 +19,7 @@ KSM_NAME_VALUE values[] = {
         [PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
 };
 
-int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt) {
+int do_sys_kernel_mm_ksm(int update_every, usec_t dt) {
     static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL, *ff_pages_to_scan = NULL;
     static long page_size = -1;
 
index 139e99755bdf036a95569a507f39ef24a9fc416b..9be32b3805ae52e292090fe027ec82d55473f2ca 100644 (file)
@@ -901,7 +901,7 @@ int run_test(struct test *test)
     st->debug = 1;
 
     // feed it with the test data
-    time_t time_now = 0, time_start = time(NULL);
+    time_t time_now = 0, time_start = now_realtime_sec();
     unsigned long c;
     collected_number last = 0;
     for(c = 0; c < test->feed_entries; c++) {
@@ -1130,7 +1130,7 @@ int unit_test(long delay, long shift)
         if(do_absi) rrddim_set(st, "percentage-of-incremental-row", i);
 
         if(!c) {
-            gettimeofday(&st->last_collected_time, NULL);
+            now_realtime_timeval(&st->last_collected_time);
             st->last_collected_time.tv_usec = shift;
         }
 
index 93ba782af279a05356765964862bdff770b07d4b..bc05f0d8d32f59f8aea65c69e7f628a51238e532 100644 (file)
@@ -143,6 +143,26 @@ void buffer_strcat(BUFFER *wb, const char *txt)
     }
 }
 
+void buffer_strcat_htmlescape(BUFFER *wb, const char *txt)
+{
+    char b[2] = { [0] = '\0', [1] = '\0' };
+
+    while(*txt) {
+        switch(*txt) {
+            case '&': buffer_strcat(wb, "&amp;"); break;
+            case '<': buffer_strcat(wb, "&lt;"); break;
+            case '>': buffer_strcat(wb, "&gt;"); break;
+            case '"': buffer_strcat(wb, "&quot;"); break;
+            case '/': buffer_strcat(wb, "&#x2F;"); break;
+            case '\'': buffer_strcat(wb, "&#x27;"); break;
+            default: {
+                b[0] = *txt;
+                buffer_strcat(wb, b);
+            }
+        }
+        txt++;
+    }
+}
 
 void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...)
 {
index ee611209bc888c2fb24e7a4f4fb68d405b8849c1..4c2d599996ab99403ca7625b32cae88a99bbb061 100644 (file)
@@ -64,6 +64,7 @@ extern void buffer_increase(BUFFER *b, size_t free_size_required);
 extern void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) __attribute__ (( format (printf, 3, 4)));
 extern void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args);
 extern void buffer_sprintf(BUFFER *wb, const char *fmt, ...) __attribute__ (( format (printf, 2, 3)));
+extern void buffer_strcat_htmlescape(BUFFER *wb, const char *txt);
 
 extern void buffer_char_replace(BUFFER *wb, char from, char to);
 
index 0280e142caccfd2dc64d75cf076bbd1ec17c1882..50779b54af6dbb208bd70d8bd8a3b582d5f1333f 100644 (file)
@@ -125,7 +125,7 @@ void web_client_reset(struct web_client *w) {
 
     if(likely(w->last_url[0])) {
         struct timeval tv;
-        gettimeofday(&tv, NULL);
+        now_realtime_timeval(&tv);
 
         size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
         size_t sent = size;
@@ -136,7 +136,7 @@ void web_client_reset(struct web_client *w) {
         // --------------------------------------------------------------------
         // global statistics
 
-        finished_web_request_statistics(usec_dt(&tv, &w->tv_in),
+        finished_web_request_statistics(dt_usec(&tv, &w->tv_in),
                                         w->stats_received_bytes,
                                         w->stats_sent_bytes,
                                         size,
@@ -152,9 +152,9 @@ void web_client_reset(struct web_client *w) {
         log_access("%llu: (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: %d '%s'",
                    w->id,
                    sent, size, -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0),
-                   usec_dt(&w->tv_ready, &w->tv_in) / 1000.0,
-                   usec_dt(&tv, &w->tv_ready) / 1000.0,
-                   usec_dt(&tv, &w->tv_in) / 1000.0,
+                   dt_usec(&w->tv_ready, &w->tv_in) / 1000.0,
+                   dt_usec(&tv, &w->tv_ready) / 1000.0,
+                   dt_usec(&tv, &w->tv_in) / 1000.0,
                    (w->mode == WEB_CLIENT_MODE_FILECOPY) ? "filecopy" : ((w->mode == WEB_CLIENT_MODE_OPTIONS)
                                                                          ? "options" : "data"),
                    w->response.code,
@@ -308,7 +308,8 @@ int mysendfile(struct web_client *w, char *filename)
     for(s = filename; *s ;s++) {
         if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
             debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
-            buffer_sprintf(w->response.data, "File '%s' cannot be served. Filename contains invalid character '%c'", filename, *s);
+            buffer_sprintf(w->response.data, "Filename contains invalid characters: ");
+            buffer_strcat_htmlescape(w->response.data, filename);
             return 400;
         }
     }
@@ -316,7 +317,8 @@ int mysendfile(struct web_client *w, char *filename)
     // if the filename contains a .. refuse to serve it
     if(strstr(filename, "..") != 0) {
         debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
-        buffer_sprintf(w->response.data, "File '%s' cannot be served. Relative filenames with '..' in them are not supported.", filename);
+        buffer_strcat(w->response.data, "Relative filenames are not supported: ");
+        buffer_strcat_htmlescape(w->response.data, filename);
         return 400;
     }
 
@@ -328,21 +330,24 @@ int mysendfile(struct web_client *w, char *filename)
     struct stat stat;
     if(lstat(webfilename, &stat) != 0) {
         debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
-        buffer_sprintf(w->response.data, "File '%s' does not exist, or is not accessible.", webfilename);
+        buffer_strcat(w->response.data, "File does not exist, or is not accessible: ");
+        buffer_strcat_htmlescape(w->response.data, webfilename);
         return 404;
     }
 
     // check if the file is owned by expected user
     if(stat.st_uid != web_files_uid()) {
         error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, stat.st_uid, web_files_uid());
-        buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
+        buffer_strcat(w->response.data, "Access to file is not permitted: ");
+        buffer_strcat_htmlescape(w->response.data, webfilename);
         return 403;
     }
 
     // check if the file is owned by expected group
     if(stat.st_gid != web_files_gid()) {
         error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, stat.st_gid, web_files_gid());
-        buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
+        buffer_strcat(w->response.data, "Access to file is not permitted: ");
+        buffer_strcat_htmlescape(w->response.data, webfilename);
         return 403;
     }
 
@@ -353,7 +358,8 @@ int mysendfile(struct web_client *w, char *filename)
 
     if((stat.st_mode & S_IFMT) != S_IFREG) {
         error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
-        buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
+        buffer_strcat(w->response.data, "Access to file is not permitted: ");
+        buffer_strcat_htmlescape(w->response.data, webfilename);
         return 403;
     }
 
@@ -365,12 +371,14 @@ int mysendfile(struct web_client *w, char *filename)
         if(errno == EBUSY || errno == EAGAIN) {
             error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
             buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
-            buffer_sprintf(w->response.data, "The file '%s' is currently busy. Please try again later.", webfilename);
+            buffer_strcat(w->response.data, "File is currently busy, please try again later: ");
+            buffer_strcat_htmlescape(w->response.data, webfilename);
             return 307;
         }
         else {
             error("%llu: Cannot open file '%s'.", w->id, webfilename);
-            buffer_sprintf(w->response.data, "Cannot open file '%s'.", webfilename);
+            buffer_strcat(w->response.data, "Cannot open file: ");
+            buffer_strcat_htmlescape(w->response.data, webfilename);
             return 404;
         }
     }
@@ -733,7 +741,8 @@ int web_client_api_request_single_chart(struct web_client *w, char *url, void ca
     RRDSET *st = rrdset_find(chart);
     if(!st) st = rrdset_find_byname(chart);
     if(!st) {
-        buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
+        buffer_strcat(w->response.data, "Chart is not found: ");
+        buffer_strcat_htmlescape(w->response.data, chart);
         ret = 404;
         goto cleanup;
     }
@@ -931,7 +940,7 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) {
 
         if (refresh > 0) {
             buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
-            w->response.data->expires = time(NULL) + refresh;
+            w->response.data->expires = now_realtime_sec() + refresh;
         }
         else buffer_no_cacheable(w->response.data);
 
@@ -980,7 +989,7 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) {
         ret = 500;
 
         // if the collected value is too old, don't calculate its value
-        if (rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above)))
+        if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above)))
             ret = rrd2value(st,
                             w->response.data,
                             &n,
@@ -1003,7 +1012,7 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) {
         }
         else if (refresh > 0) {
             buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
-            w->response.data->expires = time(NULL) + refresh;
+            w->response.data->expires = now_realtime_sec() + refresh;
         }
         else buffer_no_cacheable(w->response.data);
 
@@ -1130,7 +1139,8 @@ int web_client_api_request_v1_data(struct web_client *w, char *url)
     RRDSET *st = rrdset_find(chart);
     if(!st) st = rrdset_find_byname(chart);
     if(!st) {
-        buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
+        buffer_strcat(w->response.data, "Chart is not found: ");
+        buffer_strcat_htmlescape(w->response.data, chart);
         ret = 404;
         goto cleanup;
     }
@@ -1309,27 +1319,31 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
     }
 
     if(action == 'A' && (!machine_guid || !machine_url || !url_name)) {
+        error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
+                machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
         buffer_flush(w->response.data);
-        buffer_sprintf(w->response.data, "Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
-                       machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
+        buffer_strcat(w->response.data, "Invalid registry Access request.");
         return 400;
     }
     else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) {
+        error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
+                machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
         buffer_flush(w->response.data);
-        buffer_sprintf(w->response.data, "Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
-                       machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
+        buffer_strcat(w->response.data, "Invalid registry Delete request.");
         return 400;
     }
     else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) {
+        error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
+                machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
         buffer_flush(w->response.data);
-        buffer_sprintf(w->response.data, "Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
-                       machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
+        buffer_strcat(w->response.data, "Invalid registry Search request.");
         return 400;
     }
     else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) {
+        error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
+                machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
         buffer_flush(w->response.data);
-        buffer_sprintf(w->response.data, "Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
-                       machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
+        buffer_strcat(w->response.data, "Invalid registry Switch request.");
         return 400;
     }
 
@@ -1390,19 +1404,19 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
             if(unlikely(cookie && person_guid[0] && !strcmp(person_guid, REGISTRY_VERIFY_COOKIES_GUID)))
                 person_guid[0] = '\0';
 
-            return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, time(NULL));
+            return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec());
 
         case 'D':
             w->tracking_required = 1;
-            return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, time(NULL));
+            return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec());
 
         case 'S':
             w->tracking_required = 1;
-            return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, time(NULL));
+            return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec());
 
         case 'W':
             w->tracking_required = 1;
-            return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, time(NULL));
+            return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec());
 
         case 'H':
             return registry_request_hello_json(w);
@@ -1460,13 +1474,14 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
 
         else {
             buffer_flush(w->response.data);
-            buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);
+            buffer_strcat(w->response.data, "Unsupported v1 API command: ");
+            buffer_strcat_htmlescape(w->response.data, tok);
             return 404;
         }
     }
     else {
         buffer_flush(w->response.data);
-        buffer_sprintf(w->response.data, "API v1 command?");
+        buffer_sprintf(w->response.data, "Which API v1 command?");
         return 400;
     }
 }
@@ -1481,7 +1496,8 @@ int web_client_api_request(struct web_client *w, char *url)
             return web_client_api_request_v1(w, url);
         else {
             buffer_flush(w->response.data);
-            buffer_sprintf(w->response.data, "Unsupported API version: %s", tok);
+            buffer_strcat(w->response.data, "Unsupported API version: ");
+            buffer_strcat_htmlescape(w->response.data, tok);
             return 404;
         }
     }
@@ -1937,7 +1953,7 @@ void web_client_process(struct web_client *w) {
 #endif
 
     // start timing us
-    gettimeofday(&w->tv_in, NULL);
+    now_realtime_timeval(&w->tv_in);
 
     if(unlikely(!hash_api)) {
         hash_api = simple_hash("api");
@@ -2098,14 +2114,16 @@ void web_client_process(struct web_client *w) {
                         if(!st) st = rrdset_find(tok);
                         if(!st) {
                             code = 404;
-                            buffer_sprintf(w->response.data, "Chart %s is not found.\r\n", tok);
+                            buffer_strcat(w->response.data, "Chart is not found: ");
+                            buffer_strcat_htmlescape(w->response.data, tok);
                             debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
                         }
                         else {
                             code = 200;
                             debug_flags |= D_RRD_STATS;
                             st->debug = !st->debug;
-                            buffer_sprintf(w->response.data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
+                            buffer_sprintf(w->response.data, "Chart has now debug %s: ", st->debug?"enabled":"disabled");
+                            buffer_strcat_htmlescape(w->response.data, tok);
                             debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
                         }
                     }
@@ -2147,7 +2165,7 @@ void web_client_process(struct web_client *w) {
         }
     }
 
-    gettimeofday(&w->tv_ready, NULL);
+    now_realtime_timeval(&w->tv_ready);
     w->response.sent = 0;
     w->response.code = code;
 
index 8dd1a5f64d172be0c968c4a693ec9d8f5f377e91..cc5936aaf36cc1dc7d92fe9fd0f5f291fd5951e9 100644 (file)
@@ -663,7 +663,7 @@ p {
             <div class=grid-cell><h3><span class=star>&#x2605;</span> In real-time</h3>
                 <p>netdata collects thousands of metrics per server <strong>per second</strong>,
                     with <a href="https://github.com/firehol/netdata/wiki/Performance#netdata-daemon" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Performance>just 1% CPU</a>
-                    utilization of a single core, <a href="https://github.com/firehol/netdata/wiki/Memory-Requirements" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=MemoryRequirements>a few MB or RAM</a>
+                    utilization of a single core, <a href="https://github.com/firehol/netdata/wiki/Memory-Requirements" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=MemoryRequirements>a few MB of RAM</a>
                     and no disk I/O at all.
                     View everything on <strong>stunning</strong> real-time interactive web dashboards, even when netdata is
                     running on low-end hardware.
@@ -1060,10 +1060,11 @@ p {
         netdata has received significant contributions from:<br/>&nbsp;<br/>
         <a href="https://github.com/philwhineray" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Phil>Phil Whineray</a> (release management),<br/>
         <a href="https://github.com/alonbl" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Alon>Alon Bar-Lev</a> (autoconf and automake),<br/>
-        <a href="https://github.com/titpetric" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=titpetric>Tit Petric</a> (docker maintainer),<br/>
+        <a href="https://github.com/titpetric" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=titpetric>Tit Petric</a> (docker image maintainer),<br/>
         <a href="https://github.com/paulfantom" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Pawel>PaweÅ‚ Krupa</a> (python.d.plugin and modules),<br/>
         <a href="https://github.com/simonnagl" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=simonnagl>simonnagl</a> (disk plugin and more),<br/>
         <a href="https://github.com/fredericopissarra" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Frederico>Frederico Lamberti Pissarra</a> (performance improvements)<br/>
+        <a href="https://github.com/vlvkobal" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=VladimirKobal>Vladimir Kobal</a> (FreeBSD port)<br/>
         &nbsp;<br/>
         and dozens more enthusiasts, engineers and professionals.<br/>&nbsp;<br/>
     </p>
index f24389687878d32df7ca6057cf5abfb1c36b1a6d..d4d4446c4872fbc7d20b5be7ec57ef8aba53bca3 100644 (file)
         gotoServerInit();
     };
 
-    var this_is_demo = null;
+    var this_is_demo = null; // FIXME
     function isdemo() {
         if(this_is_demo !== null) return this_is_demo;
         this_is_demo = false;
 
         if(typeof charts['system.ram'] !== 'undefined')
             head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
-            + ' data-dimensions="used|buffers"'
+            + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
             + ' data-append-options="percentage"'
             + ' data-chart-library="easypiechart"'
             + ' data-title="Used RAM"'
             <div class="modal-content">
                 <div class="modal-header">
                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
-                    <h4 class="modal-title" id="welcomeModalLabel">Welcome!</h4>
+                    <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</h4>
                 </div>
                 <div class="modal-body">
-                        <div class="p">
-                        <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is the fastest way to visualize metrics. It is a resource efficient, highly optimized system for collecting and visualizing any type of real-time time series data, from CPU usage, disk activity, SQL queries, API calls, web site visitors, etc.
-                        </div>
-                        <div class="p">
-                        <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> tries to visualize the truth of <b>now</b>, in its <b>greatest detail</b>, so that you can get insights of what is happening now and what just happened, on your systems and applications.
-                        </div>
-                        <div class="p">
-                        To make a chart in <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>, you just need a <b>number</b>. Just a number you can read somehow. <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> will turn this number to a real time, interactive, web chart. For collecting these numbers, it supports <a href="https://github.com/firehol/netdata/wiki/External-Plugins" target="_blank">external plugins</a>, even <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">shell</a> or <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">node.js</a> plugins. Any computer program, in any language, that can print a few lines of text on its standard output, can be a netdata data collector.
-                        </div>
-                        <div class="p">
-                        <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> can embed charts everywhere, like this one <div data-netdata="system.cpu" data-dimensions="system" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-system-at="system.cpu.system.modal.1"></div> (my CPU system usage which is <span id="system.cpu.system.modal.1" style="display: inline-block; width: 40px; text-align: right;"></span>%),
-                        or this one <div data-netdata="ipv4.tcppackets" data-dimensions="received" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-received-at="ipv4.tcppackets.received.modal.1"></div> (my IPv4 received TCP packets, which are <span id="ipv4.tcppackets.received.modal.1" style="display: inline-block; width: 60px; text-align: right;"></span>/second).
-                        </div>
-                        <div class="p">
-                        You can have <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> charts on your site too. Just give it a <code>div</code> and a real time chart, zoomable and draggable will appear (try it even on these tiny ones - <b>drag</b> them to pan horizontally, <b>shift + drag</b> to zoom in, on <b>chrome shift + mouse wheel</b> to zoom in/out, <b>double click</b> on them to reset them - don't be afraid of <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> performance - <a href="https://github.com/firehol/netdata/wiki/Performance" target="_blank">a raspberry pi 2 can sustain 300 charts updates per second</a>!).
-                        </div>
-                        <div class="p">
-                        For more information please refer to the <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata wiki</a></b>.
+                    <div class="p">
+                        <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;">
+                            if there is a metric for something, we want it visualised<br/>
+                            and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong>
                         </div>
+                    </div>
+                    <div class="p">
+                        <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
+                        is a new way to monitor your systems and applications, to get <strong>real-time insights</strong>
+                        of what is really happening and what affects performance.
+                        It is carefully optimised to be a real-time system, without interfering in any way,
+                        to the core function of your systems.
+                    </div>
+                    <div class="p">
+                        <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
+                        has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>.
+                        When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k
+                        metrics, all collected per second, and still the cpu utilisation remained negligible.
+                        <br/>
+                        We have also tried to give each metric, a meaning, a context.
+                        We have grouped and categorized all metrics into meaningful charts, providing a
+                        better understanding of the underlying technologies and mechanisms.
+                    </div>
+                    <div class="p">
+                        <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is free,
+                        open-source software. If you decide to use it,
+                        <strong><a href="https://github.com/firehol/netdata/wiki/a-github-star-is-important" target="_blank">it is important to give netdata a star at GitHub</a></strong>.
+                    </div>
+                    <div class="p">
+                        Enjoy real-time performance monitoring!
+                    </div>
+                    <div class="p">
+                        Costa Tsaousis
+                    </div>
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>