summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2011-08-09 14:57:51 -0700
committerdormando <dormando@rydia.net>2011-08-10 08:44:52 -0700
commit51b68daa195ba37af1c87ba324eea504bd4cacdd (patch)
tree37bae358d9cab0c7782afb0246cb288084e5d41d
parentbaf85511adc37c0b47016f3a223ff9a82d1d5d79 (diff)
downloadmemcached-51b68daa195ba37af1c87ba324eea504bd4cacdd.tar.gz
Use a monotonically increasing timer
gettimeofday() can flip around all willy-nilly, and is actually common for users to cause this by having memcached start on boot before ntp launches and corrects system time. libevent fires events on a monotonically increasing clock, so we can more or less safely tick our internal timer up by one second every time the handler runs. Unfortunately we support expiration by date. If memcached's start time isn't in sync with the rest of the world this feature won't work well, but it never did. Was originally going to make this optional, but I can't come up with a great reason to do so. If it turns out this isn't "accurate enough", we can add the clock_gettime() code inline.
-rw-r--r--memcached.c25
1 files changed, 8 insertions, 17 deletions
diff --git a/memcached.c b/memcached.c
index e47920f..21ee227 100644
--- a/memcached.c
+++ b/memcached.c
@@ -95,11 +95,6 @@ static int add_iov(conn *c, const void *buf, int len);
static int add_msghdr(conn *c);
-/* time handling */
-static void set_current_time(void); /* update the global variable holding
- global 32-bit seconds-since-start time
- (to avoid 64 bit time_t) */
-
static void conn_free(conn *c);
/** exported globals **/
@@ -2002,8 +1997,6 @@ static void process_bin_flush(conn *c) {
exptime = ntohl(req->message.body.expiration);
}
- set_current_time();
-
if (exptime > 0) {
settings.oldest_live = realtime(exptime) - 1;
} else {
@@ -3060,7 +3053,6 @@ static void process_command(conn *c, char *command) {
} else if (ntokens >= 2 && ntokens <= 4 && (strcmp(tokens[COMMAND_TOKEN].value, "flush_all") == 0)) {
time_t exptime = 0;
- set_current_time();
set_noreply_maybe(c, tokens, ntokens);
@@ -4107,14 +4099,10 @@ static int server_socket_unix(const char *path, int access_mask) {
volatile rel_time_t current_time;
static struct event clockevent;
-/* time-sensitive callers can call it by hand with this, outside the normal ever-1-second timer */
-static void set_current_time(void) {
- struct timeval timer;
-
- gettimeofday(&timer, NULL);
- current_time = (rel_time_t) (timer.tv_sec - process_started);
-}
-
+/* libevent uses a monotonic clock when available for event scheduling. Aside
+ * from jitter, simply ticking our internal timer here is accurate enough.
+ * Note that users who are setting explicit dates for expiration times *must*
+ * ensure their clocks are correct before starting memcached. */
static void clock_handler(const int fd, const short which, void *arg) {
struct timeval t = {.tv_sec = 1, .tv_usec = 0};
static bool initialized = false;
@@ -4124,13 +4112,16 @@ static void clock_handler(const int fd, const short which, void *arg) {
evtimer_del(&clockevent);
} else {
initialized = true;
+ /* process_started is initialized to time() - 2. We initialize to 1 so
+ * flush_all won't underflow during tests. */
+ current_time = 1;
}
evtimer_set(&clockevent, clock_handler, 0);
event_base_set(main_base, &clockevent);
evtimer_add(&clockevent, &t);
- set_current_time();
+ current_time++;
}
static void usage(void) {