|
@@ -40,6 +40,7 @@
|
|
|
#include <assert.h>
|
|
|
#include <stdarg.h>
|
|
|
#include <limits.h>
|
|
|
+#include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
#include <sys/time.h>
|
|
@@ -252,6 +253,43 @@ static sendsize_t zookeeper_send(socket_t s, const void* buf, size_t len)
|
|
|
return send(s, buf, len, SEND_FLAGS);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Get the system time.
|
|
|
+ *
|
|
|
+ * If the monotonic clock is available, we use that. The monotonic clock does
|
|
|
+ * not change when the wall-clock time is adjusted by NTP or the system
|
|
|
+ * administrator. The monotonic clock returns a value which is monotonically
|
|
|
+ * increasing.
|
|
|
+ *
|
|
|
+ * If POSIX monotonic clocks are not available, we fall back on the wall-clock.
|
|
|
+ *
|
|
|
+ * @param tv (out param) The time.
|
|
|
+ */
|
|
|
+void get_system_time(struct timeval *tv)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+#ifdef CLOCK_MONOTONIC_RAW
|
|
|
+ // On Linux, CLOCK_MONOTONIC is affected by ntp slew but CLOCK_MONOTONIC_RAW
|
|
|
+ // is not. We want the non-slewed (constant rate) CLOCK_MONOTONIC_RAW if it
|
|
|
+ // is available.
|
|
|
+ struct timespec ts = { 0 };
|
|
|
+ ret = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
|
|
+ tv->tv_sec = ts.tv_sec;
|
|
|
+ tv->tv_usec = ts.tv_nsec / 1000;
|
|
|
+#elif _POSIX_MONOTONIC_CLOCK
|
|
|
+ struct timespec ts = { 0 };
|
|
|
+ ret = clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
+ tv->tv_sec = ts.tv_sec;
|
|
|
+ tv->tv_usec = ts.tv_nsec / 1000;
|
|
|
+#else
|
|
|
+ ret = gettimeofday(tv, NULL);
|
|
|
+#endif
|
|
|
+ if (ret) {
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const void *zoo_get_context(zhandle_t *zh)
|
|
|
{
|
|
|
return zh->context;
|
|
@@ -1931,7 +1969,7 @@ static struct timeval get_timeval(int interval)
|
|
|
|
|
|
rc = serialize_RequestHeader(oa, "header", &h);
|
|
|
enter_critical(zh);
|
|
|
- gettimeofday(&zh->last_ping, 0);
|
|
|
+ get_system_time(&zh->last_ping);
|
|
|
rc = rc < 0 ? rc : add_void_completion(zh, h.xid, 0, 0);
|
|
|
rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
|
|
|
get_buffer_len(oa));
|
|
@@ -2069,7 +2107,7 @@ int zookeeper_interest(zhandle_t *zh, socket_t *fd, int *interest,
|
|
|
return ZBADARGUMENTS;
|
|
|
if (is_unrecoverable(zh))
|
|
|
return ZINVALIDSTATE;
|
|
|
- gettimeofday(&now, 0);
|
|
|
+ get_system_time(&now);
|
|
|
if(zh->next_deadline.tv_sec!=0 || zh->next_deadline.tv_usec!=0){
|
|
|
int time_left = calculate_interval(&zh->next_deadline, &now);
|
|
|
int max_exceed = zh->recv_timeout / 10 > 200 ? 200 :
|
|
@@ -2279,7 +2317,7 @@ static int check_events(zhandle_t *zh, int events)
|
|
|
"failed while receiving a server response");
|
|
|
}
|
|
|
if (rc > 0) {
|
|
|
- gettimeofday(&zh->last_recv, 0);
|
|
|
+ get_system_time(&zh->last_recv);
|
|
|
if (zh->input_buffer != &zh->primer_buffer) {
|
|
|
queue_buffer(&zh->to_process, zh->input_buffer, 0);
|
|
|
} else {
|
|
@@ -2733,7 +2771,7 @@ static void isSocketReadable(zhandle_t* zh)
|
|
|
}
|
|
|
#endif
|
|
|
else{
|
|
|
- gettimeofday(&zh->socket_readable,0);
|
|
|
+ get_system_time(&zh->socket_readable);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2745,7 +2783,7 @@ static void checkResponseLatency(zhandle_t* zh)
|
|
|
if(zh->socket_readable.tv_sec==0)
|
|
|
return;
|
|
|
|
|
|
- gettimeofday(&now,0);
|
|
|
+ get_system_time(&now);
|
|
|
delay=calculate_interval(&zh->socket_readable, &now);
|
|
|
if(delay>20)
|
|
|
LOG_DEBUG(LOGCALLBACK(zh), "The following server response has spent at least %dms sitting in the client socket recv buffer",delay);
|
|
@@ -2851,7 +2889,7 @@ int zookeeper_process(zhandle_t *zh, int events)
|
|
|
if(hdr.xid == PING_XID){
|
|
|
int elapsed = 0;
|
|
|
struct timeval now;
|
|
|
- gettimeofday(&now, 0);
|
|
|
+ get_system_time(&now);
|
|
|
elapsed = calculate_interval(&zh->last_ping, &now);
|
|
|
LOG_DEBUG(LOGCALLBACK(zh), "Got ping response in %d ms", elapsed);
|
|
|
|
|
@@ -4071,7 +4109,7 @@ int flush_send_queue(zhandle_t*zh, int timeout)
|
|
|
fd_set pollSet;
|
|
|
struct timeval wait;
|
|
|
#endif
|
|
|
- gettimeofday(&started,0);
|
|
|
+ get_system_time(&started);
|
|
|
// we can't use dequeue_buffer() here because if (non-blocking) send_buffer()
|
|
|
// returns EWOULDBLOCK we'd have to put the buffer back on the queue.
|
|
|
// we use a recursive lock instead and only dequeue the buffer if a send was
|
|
@@ -4084,7 +4122,7 @@ int flush_send_queue(zhandle_t*zh, int timeout)
|
|
|
#endif
|
|
|
int elapsed;
|
|
|
struct timeval now;
|
|
|
- gettimeofday(&now,0);
|
|
|
+ get_system_time(&now);
|
|
|
elapsed=calculate_interval(&started,&now);
|
|
|
if (elapsed>timeout) {
|
|
|
rc = ZOPERATIONTIMEOUT;
|
|
@@ -4123,7 +4161,7 @@ int flush_send_queue(zhandle_t*zh, int timeout)
|
|
|
// if the buffer has been sent successfully, remove it from the queue
|
|
|
if (rc > 0)
|
|
|
remove_buffer(&zh->to_send);
|
|
|
- gettimeofday(&zh->last_send, 0);
|
|
|
+ get_system_time(&zh->last_send);
|
|
|
rc = ZOK;
|
|
|
}
|
|
|
unlock_buffer_list(&zh->to_send);
|