summaryrefslogtreecommitdiff
path: root/redis.c
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2010-05-07 14:17:10 +0200
committerPieter Noordhuis <pcnoordhuis@gmail.com>2010-05-07 14:22:21 +0200
commit3805e04f788a27938095b3d79d987210140283a9 (patch)
tree5bea572846fa0e6921148a3ae2b81282b27fb1ce /redis.c
parent739ba0d21119778438c36ea60fdb263271783468 (diff)
downloadredis-3805e04f788a27938095b3d79d987210140283a9.tar.gz
added function that preloads all keys needed to execute a MULTI/EXEC block
Diffstat (limited to 'redis.c')
-rw-r--r--redis.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/redis.c b/redis.c
index 46f97273a..f81db41cd 100644
--- a/redis.c
+++ b/redis.c
@@ -610,6 +610,7 @@ static void waitEmptyIOJobsQueue(void);
static void vmReopenSwapFile(void);
static int vmFreePage(off_t page);
static void zunionInterBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
+static void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
static int blockClientOnSwappedKeys(struct redisCommand *cmd, redisClient *c);
static int dontWaitForSwappedKey(redisClient *c, robj *key);
static void handleClientsBlockedOnSwappedKey(redisDb *db, robj *key);
@@ -826,7 +827,7 @@ static struct redisCommand cmdTable[] = {
{"lastsave",lastsaveCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
{"type",typeCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
{"multi",multiCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
- {"exec",execCommand,1,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,0,0,0},
+ {"exec",execCommand,1,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,execBlockClientOnSwappedKeys,0,0,0},
{"discard",discardCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
{"sync",syncCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
{"flushdb",flushdbCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
@@ -9576,6 +9577,32 @@ static void zunionInterBlockClientOnSwappedKeys(redisClient *c, struct redisComm
}
}
+/* Preload keys needed to execute the entire MULTI/EXEC block.
+ *
+ * This function is called by blockClientOnSwappedKeys when EXEC is issued,
+ * and will block the client when any command requires a swapped out value. */
+static void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv) {
+ int i, margc;
+ struct redisCommand *mcmd;
+ robj **margv;
+ REDIS_NOTUSED(cmd);
+ REDIS_NOTUSED(argc);
+ REDIS_NOTUSED(argv);
+
+ if (!(c->flags & REDIS_MULTI)) return;
+ for (i = 0; i < c->mstate.count; i++) {
+ mcmd = c->mstate.commands[i].cmd;
+ margc = c->mstate.commands[i].argc;
+ margv = c->mstate.commands[i].argv;
+
+ if (mcmd->vm_preload_proc != NULL) {
+ mcmd->vm_preload_proc(c,mcmd,margc,margv);
+ } else {
+ waitForMultipleSwappedKeys(c,mcmd,margc,margv);
+ }
+ }
+}
+
/* Is this client attempting to run a command against swapped keys?
* If so, block it ASAP, load the keys in background, then resume it.
*