mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
API to lookup commands with their original name.
A new server.orig_commands table was added to the server structure, this contains a copy of the commant table unaffected by rename-command statements in redis.conf. A new API lookupCommandOrOriginal() was added that checks both tables, new first, old later, so that rewriteClientCommandVector() and friends can lookup commands with their new or original name in order to fix the client->cmd pointer when the argument vector is renamed. This fixes the segfault of issue #986, but does not fix a wider range of problems resulting from renaming commands that actually operate on data and are registered into the AOF file or propagated to slaves... That is command renaming should be handled with care.
This commit is contained in:
parent
4d62912619
commit
7b190a08cf
@ -1295,7 +1295,7 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
|
||||
/* Replace argv and argc with our new versions. */
|
||||
c->argv = argv;
|
||||
c->argc = argc;
|
||||
c->cmd = lookupCommand(c->argv[0]->ptr);
|
||||
c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);
|
||||
redisAssertWithInfo(c,NULL,c->cmd != NULL);
|
||||
va_end(ap);
|
||||
}
|
||||
@ -1313,7 +1313,7 @@ void rewriteClientCommandArgument(redisClient *c, int i, robj *newval) {
|
||||
|
||||
/* If this is the command name make sure to fix c->cmd. */
|
||||
if (i == 0) {
|
||||
c->cmd = lookupCommand(c->argv[0]->ptr);
|
||||
c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);
|
||||
redisAssertWithInfo(c,NULL,c->cmd != NULL);
|
||||
}
|
||||
}
|
||||
|
24
src/redis.c
24
src/redis.c
@ -1249,6 +1249,7 @@ void initServerConfig() {
|
||||
* initial configuration, since command names may be changed via
|
||||
* redis.conf using the rename-command directive. */
|
||||
server.commands = dictCreate(&commandTableDictType,NULL);
|
||||
server.orig_commands = dictCreate(&commandTableDictType,NULL);
|
||||
populateCommandTable();
|
||||
server.delCommand = lookupCommandByCString("del");
|
||||
server.multiCommand = lookupCommandByCString("multi");
|
||||
@ -1443,7 +1444,7 @@ void populateCommandTable(void) {
|
||||
for (j = 0; j < numcommands; j++) {
|
||||
struct redisCommand *c = redisCommandTable+j;
|
||||
char *f = c->sflags;
|
||||
int retval;
|
||||
int retval1, retval2;
|
||||
|
||||
while(*f != '\0') {
|
||||
switch(*f) {
|
||||
@ -1465,8 +1466,11 @@ void populateCommandTable(void) {
|
||||
f++;
|
||||
}
|
||||
|
||||
retval = dictAdd(server.commands, sdsnew(c->name), c);
|
||||
assert(retval == DICT_OK);
|
||||
retval1 = dictAdd(server.commands, sdsnew(c->name), c);
|
||||
/* Populate an additional dictionary that will be unaffected
|
||||
* by rename-command statements in redis.conf. */
|
||||
retval2 = dictAdd(server.orig_commands, sdsnew(c->name), c);
|
||||
redisAssert(retval1 == DICT_OK && retval2 == DICT_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1534,6 +1538,20 @@ struct redisCommand *lookupCommandByCString(char *s) {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* Lookup the command in the current table, if not found also check in
|
||||
* the original table containing the original command names unaffected by
|
||||
* redis.conf rename-command statement.
|
||||
*
|
||||
* This is used by functions rewriting the argument vector such as
|
||||
* rewriteClientCommandVector() in order to set client->cmd pointer
|
||||
* correctly even if the command was renamed. */
|
||||
struct redisCommand *lookupCommandOrOriginal(sds name) {
|
||||
struct redisCommand *cmd = dictFetchValue(server.commands, name);
|
||||
|
||||
if (!cmd) cmd = dictFetchValue(server.orig_commands,name);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* Propagate the specified command (in the context of the specified database id)
|
||||
* to AOF and Slaves.
|
||||
*
|
||||
|
@ -658,7 +658,8 @@ struct redisServer {
|
||||
/* General */
|
||||
int hz; /* serverCron() calls frequency in hertz */
|
||||
redisDb *db;
|
||||
dict *commands; /* Command table hash table */
|
||||
dict *commands; /* Command table */
|
||||
dict *orig_commands; /* Command table before command renaming. */
|
||||
aeEventLoop *el;
|
||||
unsigned lruclock:22; /* Clock incrementing every minute, for LRU */
|
||||
unsigned lruclock_padding:10;
|
||||
@ -1148,6 +1149,7 @@ int processCommand(redisClient *c);
|
||||
void setupSignalHandlers(void);
|
||||
struct redisCommand *lookupCommand(sds name);
|
||||
struct redisCommand *lookupCommandByCString(char *s);
|
||||
struct redisCommand *lookupCommandOrOriginal(sds name);
|
||||
void call(redisClient *c, int flags);
|
||||
void propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int flags);
|
||||
void alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int target);
|
||||
|
Loading…
Reference in New Issue
Block a user