mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
Update PR #6537: use a fresh time outside call().
One problem with the solution proposed so far in #6537 is that key lookups outside a command execution via call(), still used a cached time. The cached time needed to be refreshed in multiple places, especially because of modules callbacks from timers, cluster bus, and thread safe contexts, that may use RM_Open(). In order to avoid this problem, this commit introduces the ability to detect if we are inside call(): this way we can use the reference fixed time only when we are in the context of a command execution or Lua script, but for the asynchronous lookups, we can still use mstime() to get a fresh time reference.
This commit is contained in:
parent
824f5f0b7a
commit
8b2c0f9044
27
src/db.c
27
src/db.c
@ -1188,6 +1188,7 @@ void propagateExpire(redisDb *db, robj *key, int lazy) {
|
|||||||
/* Check if the key is expired. */
|
/* Check if the key is expired. */
|
||||||
int keyIsExpired(redisDb *db, robj *key) {
|
int keyIsExpired(redisDb *db, robj *key) {
|
||||||
mstime_t when = getExpire(db,key);
|
mstime_t when = getExpire(db,key);
|
||||||
|
mstime_t now;
|
||||||
|
|
||||||
if (when < 0) return 0; /* No expire for this key */
|
if (when < 0) return 0; /* No expire for this key */
|
||||||
|
|
||||||
@ -1198,13 +1199,27 @@ 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. */
|
||||||
*
|
if (server.lua_caller) {
|
||||||
* Outside the Lua script execution, we use the cached time server.mstime
|
now = server.lua_time_start;
|
||||||
* that is updated before commands executions in call(). */
|
}
|
||||||
mstime_t now = server.lua_caller ? server.lua_time_start :
|
/* If we are in the middle of a command execution, we still want to use
|
||||||
server.mstime;
|
* a reference time that does not change: in that case we just use the
|
||||||
|
* cached time, that we update before each call in the call() function.
|
||||||
|
* This way we avoid that commands such as RPOPLPUSH or similar, that
|
||||||
|
* may re-open the same key multiple times, can invalidate an already
|
||||||
|
* open object in a next call, if the next call will see the key expired,
|
||||||
|
* while the first did not. */
|
||||||
|
else if (server.call_depth > 0) {
|
||||||
|
now = server.mstime;
|
||||||
|
}
|
||||||
|
/* For the other cases, we want to use the most fresh time we have. */
|
||||||
|
else {
|
||||||
|
now = mstime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The key expired if the current (virtual or real) time is greater
|
||||||
|
* than the expire time of the key. */
|
||||||
return now > when;
|
return now > when;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2780,6 +2780,7 @@ void initServer(void) {
|
|||||||
server.hz = server.config_hz;
|
server.hz = server.config_hz;
|
||||||
server.pid = getpid();
|
server.pid = getpid();
|
||||||
server.current_client = NULL;
|
server.current_client = NULL;
|
||||||
|
server.call_depth = 0;
|
||||||
server.clients = listCreate();
|
server.clients = listCreate();
|
||||||
server.clients_index = raxNew();
|
server.clients_index = raxNew();
|
||||||
server.clients_to_close = listCreate();
|
server.clients_to_close = listCreate();
|
||||||
@ -3252,6 +3253,8 @@ void call(client *c, int flags) {
|
|||||||
int client_old_flags = c->flags;
|
int client_old_flags = c->flags;
|
||||||
struct redisCommand *real_cmd = c->cmd;
|
struct redisCommand *real_cmd = c->cmd;
|
||||||
|
|
||||||
|
server.call_depth++;
|
||||||
|
|
||||||
/* Sent the command to clients in MONITOR mode, only if the commands are
|
/* Sent the command to clients in MONITOR mode, only if the commands are
|
||||||
* not generated from reading an AOF. */
|
* not generated from reading an AOF. */
|
||||||
if (listLength(server.monitors) &&
|
if (listLength(server.monitors) &&
|
||||||
@ -3377,6 +3380,7 @@ void call(client *c, int flags) {
|
|||||||
trackingRememberKeys(caller);
|
trackingRememberKeys(caller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server.call_depth--;
|
||||||
server.stat_numcommands++;
|
server.stat_numcommands++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,7 +1134,8 @@ struct redisServer {
|
|||||||
list *clients_pending_write; /* There is to write or install handler. */
|
list *clients_pending_write; /* There is to write or install handler. */
|
||||||
list *clients_pending_read; /* Client has pending read socket buffers. */
|
list *clients_pending_read; /* Client has pending read socket buffers. */
|
||||||
list *slaves, *monitors; /* List of slaves and MONITORs */
|
list *slaves, *monitors; /* List of slaves and MONITORs */
|
||||||
client *current_client; /* Current client, only used on crash report */
|
client *current_client; /* Current client executing the command. */
|
||||||
|
long call_depth; /* call() re-entering count. */
|
||||||
rax *clients_index; /* Active clients dictionary by client ID. */
|
rax *clients_index; /* Active clients dictionary by client ID. */
|
||||||
int clients_paused; /* True if clients are currently paused */
|
int clients_paused; /* True if clients are currently paused */
|
||||||
mstime_t clients_pause_end_time; /* Time when we undo clients_paused */
|
mstime_t clients_pause_end_time; /* Time when we undo clients_paused */
|
||||||
|
Loading…
Reference in New Issue
Block a user