提交 a1b1c1ea 编写于 作者: A antirez

Fix MULTI / EXEC rendering in MONITOR output.

Before of this commit it used to be like this:

MULTI
EXEC
... actual commands of the transaction ...

Because after all that is the natural order of things. Transaction
commands are queued and executed *only after* EXEC is called.

However this makes debugging with MONITOR a mess, so the code was
modified to provide a coherent output.

What happens is that MULTI is rendered in the MONITOR output as far as
possible, instead EXEC is propagated only after the transaction is
executed, or even in the case it fails because of WATCH, so in this case
you'll simply see:

MULTI
EXEC

An empty transaction.
上级 be6cbd3a
......@@ -96,7 +96,7 @@ void execCommand(redisClient *c) {
c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS);
unwatchAllKeys(c);
addReply(c,shared.nullmultibulk);
return;
goto handle_monitor;
}
/* Replicate a MULTI request now that we are sure the block is executed.
......@@ -132,6 +132,15 @@ void execCommand(redisClient *c) {
* always send the MULTI command (we can't know beforehand if the
* next operations will contain at least a modification to the DB). */
server.dirty++;
handle_monitor:
/* Send EXEC to clients waiting data from MONITOR. We do it here
* since the natural order of commands execution is actually:
* MUTLI, EXEC, ... commands inside transaction ...
* Instead EXEC is flagged as REDIS_CMD_SKIP_MONITOR in the command
* table, and we do it here with correct ordering. */
if (listLength(server.monitors) && !server.loading)
replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);
}
/* ===================== WATCH (CAS alike for MULTI/EXEC) ===================
......
......@@ -110,6 +110,7 @@ struct redisCommand *commandTable;
* t: Allow command while a slave has stale data but is not allowed to
* server this data. Normally no command is accepted in this condition
* but just a few.
* M: Do not automatically propagate the command on MONITOR.
*/
struct redisCommand redisCommandTable[] = {
{"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
......@@ -216,7 +217,7 @@ struct redisCommand redisCommandTable[] = {
{"lastsave",lastsaveCommand,1,"r",0,NULL,0,0,0,0,0},
{"type",typeCommand,2,"r",0,NULL,1,1,1,0,0},
{"multi",multiCommand,1,"rs",0,NULL,0,0,0,0,0},
{"exec",execCommand,1,"s",0,NULL,0,0,0,0,0},
{"exec",execCommand,1,"sM",0,NULL,0,0,0,0,0},
{"discard",discardCommand,1,"rs",0,NULL,0,0,0,0,0},
{"sync",syncCommand,1,"ars",0,NULL,0,0,0,0,0},
{"replconf",replconfCommand,-1,"ars",0,NULL,0,0,0,0,0},
......@@ -1386,6 +1387,7 @@ void populateCommandTable(void) {
case 'S': c->flags |= REDIS_CMD_SORT_FOR_SCRIPT; break;
case 'l': c->flags |= REDIS_CMD_LOADING; break;
case 't': c->flags |= REDIS_CMD_STALE; break;
case 'M': c->flags |= REDIS_CMD_SKIP_MONITOR; break;
default: redisPanic("Unsupported command flag"); break;
}
f++;
......@@ -1461,7 +1463,7 @@ struct redisCommand *lookupCommandByCString(char *s) {
}
/* Propagate the specified command (in the context of the specified database id)
* to AOF, Slaves and Monitors.
* to AOF and Slaves.
*
* flags are an xor between:
* + REDIS_PROPAGATE_NONE (no propagation of command at all)
......@@ -1491,8 +1493,12 @@ void call(redisClient *c, int flags) {
/* Sent the command to clients in MONITOR mode, only if the commands are
* not geneated from reading an AOF. */
if (listLength(server.monitors) && !server.loading)
if (listLength(server.monitors) &&
!server.loading &&
!(c->cmd->flags & REDIS_CMD_SKIP_MONITOR))
{
replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);
}
/* Call the command. */
redisOpArrayInit(&server.also_propagate);
......
......@@ -86,6 +86,7 @@
#define REDIS_CMD_SORT_FOR_SCRIPT 256 /* "S" flag */
#define REDIS_CMD_LOADING 512 /* "l" flag */
#define REDIS_CMD_STALE 1024 /* "t" flag */
#define REDIS_CMD_SKIP_MONITOR 2048 /* "M" flag */
/* Object types */
#define REDIS_STRING 0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册