Update PR #6537 patch to for generality.
After the thread in #6537 and thanks to the suggestions received, this commit updates the original patch in order to: 1. Solve the problem of updating the time in multiple places by updating it in call(). 2. Avoid introducing a new field but use our cached time. This required some minor refactoring to the function updating the time, and the introduction of a new cached time in microseconds in order to use less gettimeofday() calls.
This commit is contained in:
parent
e542132b07
commit
824f5f0b7a
8
src/db.c
8
src/db.c
@ -1198,8 +1198,12 @@ int keyIsExpired(redisDb *db, robj *key) {
|
|||||||
* blocked to when the Lua script started. This way a key can expire
|
* blocked to when the Lua script started. This way a key can expire
|
||||||
* only the first time it is accessed and not in the middle of the
|
* only the first time it is accessed and not in the middle of the
|
||||||
* script execution, making propagation to slaves / AOF consistent.
|
* script execution, making propagation to slaves / AOF consistent.
|
||||||
* See issue #1525 on Github for more information. */
|
* See issue #1525 on Github for more information.
|
||||||
mstime_t now = server.lua_caller ? server.lua_time_start : server.cmd_start_mstime;
|
*
|
||||||
|
* Outside the Lua script execution, we use the cached time server.mstime
|
||||||
|
* that is updated before commands executions in call(). */
|
||||||
|
mstime_t now = server.lua_caller ? server.lua_time_start :
|
||||||
|
server.mstime;
|
||||||
|
|
||||||
return now > when;
|
return now > when;
|
||||||
}
|
}
|
||||||
|
@ -1961,7 +1961,7 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
|
|||||||
/* The DB can take some non trivial amount of time to load. Update
|
/* The DB can take some non trivial amount of time to load. Update
|
||||||
* our cached time since it is used to create and update the last
|
* our cached time since it is used to create and update the last
|
||||||
* interaction time with clients and for other important things. */
|
* interaction time with clients and for other important things. */
|
||||||
updateCachedTime();
|
updateCachedTime(0);
|
||||||
if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER)
|
if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER)
|
||||||
replicationSendNewlineToMaster();
|
replicationSendNewlineToMaster();
|
||||||
loadingProgress(r->processed_bytes);
|
loadingProgress(r->processed_bytes);
|
||||||
|
36
src/server.c
36
src/server.c
@ -1736,20 +1736,29 @@ void databasesCron(void) {
|
|||||||
/* We take a cached value of the unix time in the global state because with
|
/* We take a cached value of the unix time in the global state because with
|
||||||
* virtual memory and aging there is to store the current time in objects at
|
* virtual memory and aging there is to store the current time in objects at
|
||||||
* every object access, and accuracy is not needed. To access a global var is
|
* every object access, and accuracy is not needed. To access a global var is
|
||||||
* a lot faster than calling time(NULL) */
|
* a lot faster than calling time(NULL).
|
||||||
void updateCachedTime(void) {
|
*
|
||||||
server.unixtime = time(NULL);
|
* This function should be fast because it is called at every command execution
|
||||||
server.mstime = mstime();
|
* in call(), so it is possible to decide if to update the daylight saving
|
||||||
|
* info or not using the 'update_daylight_info' argument. Normally we update
|
||||||
|
* such info only when calling this function from serverCron() but not when
|
||||||
|
* calling it from call(). */
|
||||||
|
void updateCachedTime(int update_daylight_info) {
|
||||||
|
server.ustime = ustime();
|
||||||
|
server.mstime = server.ustime / 1000;
|
||||||
|
server.unixtime = server.mstime / 1000;
|
||||||
|
|
||||||
/* To get information about daylight saving time, we need to call
|
/* To get information about daylight saving time, we need to call
|
||||||
* localtime_r and cache the result. However calling localtime_r in this
|
* localtime_r and cache the result. However calling localtime_r in this
|
||||||
* context is safe since we will never fork() while here, in the main
|
* context is safe since we will never fork() while here, in the main
|
||||||
* thread. The logging function will call a thread safe version of
|
* thread. The logging function will call a thread safe version of
|
||||||
* localtime that has no locks. */
|
* localtime that has no locks. */
|
||||||
struct tm tm;
|
if (update_daylight_info) {
|
||||||
time_t ut = server.unixtime;
|
struct tm tm;
|
||||||
localtime_r(&ut,&tm);
|
time_t ut = server.unixtime;
|
||||||
server.daylight_active = tm.tm_isdst;
|
localtime_r(&ut,&tm);
|
||||||
|
server.daylight_active = tm.tm_isdst;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkChildrenDone(void) {
|
void checkChildrenDone(void) {
|
||||||
@ -1838,7 +1847,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
|||||||
if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);
|
if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);
|
||||||
|
|
||||||
/* Update the time cache. */
|
/* Update the time cache. */
|
||||||
updateCachedTime();
|
updateCachedTime(1);
|
||||||
|
|
||||||
server.hz = server.config_hz;
|
server.hz = server.config_hz;
|
||||||
/* Adapt the server.hz value to the number of configured clients. If we have
|
/* Adapt the server.hz value to the number of configured clients. If we have
|
||||||
@ -2252,7 +2261,7 @@ void createSharedObjects(void) {
|
|||||||
void initServerConfig(void) {
|
void initServerConfig(void) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
updateCachedTime();
|
updateCachedTime(1);
|
||||||
getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);
|
getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);
|
||||||
server.runid[CONFIG_RUN_ID_SIZE] = '\0';
|
server.runid[CONFIG_RUN_ID_SIZE] = '\0';
|
||||||
changeReplicationId();
|
changeReplicationId();
|
||||||
@ -3238,7 +3247,8 @@ void preventCommandReplication(client *c) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void call(client *c, int flags) {
|
void call(client *c, int flags) {
|
||||||
long long dirty, start, duration;
|
long long dirty;
|
||||||
|
ustime_t start, duration;
|
||||||
int client_old_flags = c->flags;
|
int client_old_flags = c->flags;
|
||||||
struct redisCommand *real_cmd = c->cmd;
|
struct redisCommand *real_cmd = c->cmd;
|
||||||
|
|
||||||
@ -3259,7 +3269,8 @@ void call(client *c, int flags) {
|
|||||||
|
|
||||||
/* Call the command. */
|
/* Call the command. */
|
||||||
dirty = server.dirty;
|
dirty = server.dirty;
|
||||||
start = ustime();
|
updateCachedTime(0);
|
||||||
|
start = server.ustime;
|
||||||
c->cmd->proc(c);
|
c->cmd->proc(c);
|
||||||
duration = ustime()-start;
|
duration = ustime()-start;
|
||||||
dirty = server.dirty-dirty;
|
dirty = server.dirty-dirty;
|
||||||
@ -3596,7 +3607,6 @@ int processCommand(client *c) {
|
|||||||
queueMultiCommand(c);
|
queueMultiCommand(c);
|
||||||
addReply(c,shared.queued);
|
addReply(c,shared.queued);
|
||||||
} else {
|
} else {
|
||||||
server.cmd_start_mstime = mstime();
|
|
||||||
call(c,CMD_CALL_FULL);
|
call(c,CMD_CALL_FULL);
|
||||||
c->woff = server.master_repl_offset;
|
c->woff = server.master_repl_offset;
|
||||||
if (listLength(server.ready_keys))
|
if (listLength(server.ready_keys))
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
typedef long long mstime_t; /* millisecond time type. */
|
typedef long long mstime_t; /* millisecond time type. */
|
||||||
|
typedef long long ustime_t; /* microsecond time type. */
|
||||||
|
|
||||||
#include "ae.h" /* Event driven programming library */
|
#include "ae.h" /* Event driven programming library */
|
||||||
#include "sds.h" /* Dynamic safe strings */
|
#include "sds.h" /* Dynamic safe strings */
|
||||||
@ -1400,8 +1401,8 @@ struct redisServer {
|
|||||||
_Atomic time_t unixtime; /* Unix time sampled every cron cycle. */
|
_Atomic time_t unixtime; /* Unix time sampled every cron cycle. */
|
||||||
time_t timezone; /* Cached timezone. As set by tzset(). */
|
time_t timezone; /* Cached timezone. As set by tzset(). */
|
||||||
int daylight_active; /* Currently in daylight saving time. */
|
int daylight_active; /* Currently in daylight saving time. */
|
||||||
long long mstime; /* 'unixtime' with milliseconds resolution. */
|
mstime_t mstime; /* 'unixtime' in milliseconds. */
|
||||||
mstime_t cmd_start_mstime;
|
ustime_t ustime; /* 'unixtime' in microseconds. */
|
||||||
/* Pubsub */
|
/* Pubsub */
|
||||||
dict *pubsub_channels; /* Map channels to list of subscribed clients */
|
dict *pubsub_channels; /* Map channels to list of subscribed clients */
|
||||||
list *pubsub_patterns; /* A list of pubsub_patterns */
|
list *pubsub_patterns; /* A list of pubsub_patterns */
|
||||||
@ -1997,7 +1998,7 @@ void populateCommandTable(void);
|
|||||||
void resetCommandTableStats(void);
|
void resetCommandTableStats(void);
|
||||||
void adjustOpenFilesLimit(void);
|
void adjustOpenFilesLimit(void);
|
||||||
void closeListeningSockets(int unlink_unix_socket);
|
void closeListeningSockets(int unlink_unix_socket);
|
||||||
void updateCachedTime(void);
|
void updateCachedTime(int update_daylight_info);
|
||||||
void resetServerStats(void);
|
void resetServerStats(void);
|
||||||
void activeDefragCycle(void);
|
void activeDefragCycle(void);
|
||||||
unsigned int getLRUClock(void);
|
unsigned int getLRUClock(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user