void timespec_from_ns(struct timespec* a, uint64_t ns);
int64_t timespec_ns(struct timespec* a);
int64_t timespec_diff(struct timespec* a, struct timespec* b);
-long timespec_diff_10us(struct timespec* a, struct timespec* b);
-void timespec_add_10us(struct timespec* a, long t_10u);
+void timespec_add(struct timespec* a, int64_t ns);
void usage(int);
int wait_for_reply(long);
void print_per_system_stats(void);
struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
-/*** function definitions ***/
-
-static inline void copy_timespec(struct timespec *dst, const struct timespec *src)
-{
- dst->tv_sec = src->tv_sec;
- dst->tv_nsec = src->tv_nsec;
-}
-
-static inline long ns_to_tick(int64_t ns)
-{
- ns /= 1000; // ns -> us
- ns /= 10; // us -> 10us ticks
- return (long)ns;
-}
-
/************************************************************
Function: main
if (report_interval) {
next_report_time = start_time;
- timespec_add_10us(&next_report_time, report_interval);
+ timespec_add(&next_report_time, (int64_t)report_interval*10000);
}
last_send_time.tv_sec = current_time.tv_sec - 10000;
void main_loop()
{
long lt;
- long wait_time;
+ int64_t wait_time_ns;
struct event *event;
struct host_entry *h;
/* timeout event ? */
if (event_queue_timeout.first &&
- timespec_diff_10us(&event_queue_timeout.first->ev_time, ¤t_time) <= 0)
+ timespec_diff(&event_queue_timeout.first->ev_time, ¤t_time) <= 0)
{
event = ev_dequeue(&event_queue_timeout);
h = event->host;
/* ping event ? */
if (event_queue_ping.first &&
- timespec_diff_10us(&event_queue_ping.first->ev_time, ¤t_time) <= 0)
+ timespec_diff(&event_queue_ping.first->ev_time, ¤t_time) <= 0)
{
/* Make sure that we don't ping more than once every "interval" */
- lt = timespec_diff_10us(¤t_time, &last_send_time);
- if (lt < interval)
+ lt = timespec_diff(¤t_time, &last_send_time);
+ if (lt < interval*10000)
goto wait_for_reply;
/* Dequeue the event */
if (loop_flag || (count_flag && event->ping_index+1 < count)) {
struct timespec next_ping_time;
next_ping_time = event->ev_time;
- timespec_add_10us(&next_ping_time, perhost_interval);
+ timespec_add(&next_ping_time, (int64_t)perhost_interval*10000);
host_add_ping_event(h, event->ping_index+1, &next_ping_time);
}
}
wait_for_reply:
/* When is the next ping next event? */
- wait_time = -1;
+ wait_time_ns = -1;
if (event_queue_ping.first) {
- wait_time = timespec_diff_10us(&event_queue_ping.first->ev_time, ¤t_time);
- if (wait_time < 0)
- wait_time = 0;
+ wait_time_ns = timespec_diff(&event_queue_ping.first->ev_time, ¤t_time);
+ if (wait_time_ns < 0)
+ wait_time_ns = 0;
/* make sure that we wait enough, so that the inter-ping delay is
* bigger than 'interval' */
- if (wait_time < interval) {
- lt = timespec_diff_10us(¤t_time, &last_send_time);
- if (lt < interval) {
- wait_time = interval - lt;
+ if (wait_time_ns < interval*10000) {
+ lt = timespec_diff(¤t_time, &last_send_time);
+ if (lt < interval*10000) {
+ wait_time_ns = interval*10000 - lt;
}
}
- dbg_printf("next ping event in %ld ms (%s)\n", wait_time / 100, event_queue_ping.first->host->host);
+ dbg_printf("next ping event in %ld ms (%s)\n", wait_time_ns / 1000000, event_queue_ping.first->host->host);
}
/* When is the next timeout event? */
if (event_queue_timeout.first) {
- long wait_time_timeout = timespec_diff_10us(&event_queue_timeout.first->ev_time, ¤t_time);
- if(wait_time < 0 || wait_time_timeout < wait_time) {
- wait_time = wait_time_timeout;
- if (wait_time < 0) {
- wait_time = 0;
+ long wait_time_timeout = timespec_diff(&event_queue_timeout.first->ev_time, ¤t_time);
+ if(wait_time_ns < 0 || wait_time_timeout < wait_time_ns) {
+ wait_time_ns = wait_time_timeout;
+ if (wait_time_ns < 0) {
+ wait_time_ns = 0;
}
}
- dbg_printf("next timeout event in %ld ms (%s)\n", wait_time / 100, event_queue_timeout.first->host->host);
+ dbg_printf("next timeout event in %ld ms (%s)\n", wait_time_timeout / 1000000, event_queue_timeout.first->host->host);
}
/* When is the next report due? */
if (report_interval && (loop_flag || count_flag)) {
- long wait_time_next_report = timespec_diff_10us(&next_report_time, ¤t_time);
- if (wait_time_next_report < wait_time) {
- wait_time = wait_time_next_report;
- if (wait_time < 0) {
- wait_time = 0;
+ long wait_time_next_report = timespec_diff(&next_report_time, ¤t_time);
+ if (wait_time_next_report < wait_time_ns) {
+ wait_time_ns = wait_time_next_report;
+ if (wait_time_ns < 0) {
+ wait_time_ns = 0;
}
}
- dbg_printf("next report event in %ld ms\n", wait_time_next_report / 100);
+ dbg_printf("next report event in %ld ms\n", wait_time_next_report / 1000000);
}
/* if wait_time is still -1, it means that we are waiting for nothing... */
- if(wait_time == -1) {
+ if(wait_time_ns == -1) {
break;
}
/* Receive replies */
/* (this is what sleeps during each loop iteration) */
- dbg_printf("waiting up to %ld ms\n", wait_time/100);
- if (wait_for_reply(wait_time)) {
+ dbg_printf("waiting up to %ld ms\n", wait_time_ns / 1000000);
+ if (wait_for_reply(wait_time_ns)) {
while (wait_for_reply(0))
; /* process other replies in the queue */
}
}
/* Print report */
- if (report_interval && (loop_flag || count_flag) && (timespec_diff_10us(¤t_time, &next_report_time) >= 0)) {
+ if (report_interval && (loop_flag || count_flag) && (timespec_diff(¤t_time, &next_report_time) >= 0)) {
if (netdata_flag)
print_netdata();
else
print_per_system_splits();
- while (timespec_diff_10us(¤t_time, &next_report_time) >= 0)
- timespec_add_10us(&next_report_time, report_interval);
+ while (timespec_diff(¤t_time, &next_report_time) >= 0)
+ timespec_add(&next_report_time, (int64_t)report_interval*10000);
}
}
}
else {
/* schedule timeout */
struct timespec timeout_time = current_time;
- timespec_add_10us(&timeout_time, h->timeout);
+ timespec_add(&timeout_time, (int64_t)(h->timeout)*10000);
host_add_timeout_event(h, index, &timeout_time);
/* mark this trial as outstanding */
return -1;
}
-int receive_packet(int socket,
+int receive_packet(int64_t wait_time,
struct timespec* reply_timestamp,
struct sockaddr* reply_src_addr,
size_t reply_src_addr_len,
char* reply_buf,
size_t reply_buf_len)
{
+ struct timeval to;
+ int s = 0;
int recv_len;
static unsigned char msg_control[40];
struct iovec msg_iov = {
struct cmsghdr* cmsg;
#endif
- recv_len = recvmsg(socket, &recv_msghdr, 0);
+ /* Wait for a socket to become ready */
+ if (wait_time) {
+ to.tv_sec = wait_time / UINT64_C(1000000000);
+ to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1;
+
+ }
+ else {
+ to.tv_sec = 0;
+ to.tv_usec = 0;
+ }
+ dbg_printf("wait time: %ld\n", wait_time);
+ s = socket_can_read(&to);
+ if (s == -1) {
+ return 0; /* timeout */
+ }
+ dbg_printf("socket ready: %d\n", s);
+
+ recv_len = recvmsg(s, &recv_msghdr, 0);
if (recv_len <= 0) {
return 0;
}
}
#endif
-int wait_for_reply(long wait_time)
+int wait_for_reply(int64_t wait_time)
{
int result;
static char buffer[4096];
SEQMAP_VALUE* seqmap_value;
unsigned short id;
unsigned short seq;
- struct timeval to;
- int s = 0;
-
- /* Wait for a socket to become ready */
- if (wait_time) {
- if (wait_time < 100000) {
- to.tv_sec = 0;
- to.tv_usec = wait_time * 10;
- }
- else {
- to.tv_sec = wait_time / 100000;
- to.tv_usec = (wait_time % 100000) * 10;
- }
- }
- else {
- to.tv_sec = 0;
- to.tv_usec = 0;
- }
- s = socket_can_read(&to);
- if (s == -1) {
- return 0; /* timeout */
- }
/* Receive packet */
- result = receive_packet(s, /* socket */
+ result = receive_packet(wait_time, /* max. wait time, in ns */
&recv_time, /* reply_timestamp */
(struct sockaddr*)&response_addr, /* reply_src_addr */
sizeof(response_addr), /* reply_src_addr_len */
);
if (result <= 0) {
- return 1;
+ return 0;
}
clock_gettime(CLOCKID, ¤t_time);
/* discard reply if delay is larger than timeout
* (see also: github #32) */
- if (ns_to_tick(this_reply) > h->timeout) {
+ if (this_reply > (int64_t)(h->timeout)*10000) {
return 1;
}
int64_t timespec_ns(struct timespec* a)
{
- return (a->tv_sec * 1000000000LL) + a->tv_nsec;
-}
-int64_t timespec_10us(struct timespec* a)
-{
- return (a->tv_sec * 100000) + a->tv_nsec / 10000;
+ return ((int64_t) a->tv_sec * UINT64_C(1000000000)) + a->tv_nsec;
}
void timespec_from_ns(struct timespec* a, uint64_t ns)
{
- a->tv_sec = ns / 1000000000ULL;
- a->tv_nsec = ns % 1000000000ULL;
+ a->tv_sec = ns / UINT64_C(1000000000);
+ a->tv_nsec = ns % UINT64_C(1000000000);
}
int64_t timespec_diff(struct timespec* a, struct timespec* b)
{
return timespec_ns(a) - timespec_ns(b);
}
-long timespec_diff_10us(struct timespec* a, struct timespec* b)
-{
- return (long)(timespec_10us(a) - timespec_10us(b));
-}
/************************************************************
Function: timespec_add
*************************************************************/
-void timespec_add_10us(struct timespec* a, long t_10u)
+void timespec_add(struct timespec* a, int64_t ns)
{
- uint64_t ns = t_10u;
- ns *= 10; // tick -> us
- ns *= 1000; // us -> ns
- a->tv_sec += (ns + a->tv_nsec) / 1000000000ULL;
- a->tv_nsec = (ns + a->tv_nsec) % 1000000000ULL;
+ a->tv_sec += (ns + a->tv_nsec) / UINT64_C(1000000000);
+ a->tv_nsec = (ns + a->tv_nsec) % UINT64_C(1000000000);
}
/************************************************************
ev_enqueue(&event_queue_ping, event);
dbg_printf("%s [%d]: add ping event in %ld ms\n",
- event->host->host, index, timespec_diff_10us(&event->ev_time, ¤t_time) / 100);
+ event->host->host, index, timespec_diff(&event->ev_time, ¤t_time) / 1000000);
}
void host_add_timeout_event(HOST_ENTRY *h, int index, struct timespec *ts)
ev_enqueue(&event_queue_timeout, event);
dbg_printf("%s [%d]: add timeout event in %ld ms\n",
- event->host->host, index, timespec_diff_10us(&event->ev_time, ¤t_time) / 100);
+ event->host->host, index, timespec_diff(&event->ev_time, ¤t_time) / 1000000);
}
struct event *host_get_timeout_event(HOST_ENTRY *h, int index)