summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2011-03-23 18:09:17 +0100
committerantirez <antirez@gmail.com>2011-03-23 18:09:17 +0100
commit9791f0f8ceb18e2e3c297a8c479307b7af0f9830 (patch)
treea9efb22e822b995c7a65ab88c43ca1e5ddf8eee9 /src
parent03af999cb0befed9d2556c2df1eb0511de2d96d2 (diff)
downloadredis-9791f0f8ceb18e2e3c297a8c479307b7af0f9830.tar.gz
new preloading implemented, still EXEC not handled correctly, everything to test
Diffstat (limited to 'src')
-rw-r--r--src/db.c72
-rw-r--r--src/dscache.c14
-rw-r--r--src/redis.c2
-rw-r--r--src/redis.h26
4 files changed, 98 insertions, 16 deletions
diff --git a/src/db.c b/src/db.c
index 9daa5ddbd..9bc299ca1 100644
--- a/src/db.c
+++ b/src/db.c
@@ -616,3 +616,75 @@ void persistCommand(redisClient *c) {
}
}
}
+
+/* -----------------------------------------------------------------------------
+ * API to get key arguments from commands
+ * ---------------------------------------------------------------------------*/
+
+int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, int *numkeys) {
+ int j, i = 0, last, *keys;
+ REDIS_NOTUSED(argv);
+
+ if (cmd->firstkey == 0) {
+ *numkeys = 0;
+ return NULL;
+ }
+ last = cmd->lastkey;
+ if (last < 0) last = argc+last;
+ keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1));
+ for (j = cmd->firstkey; j <= last; j += cmd->keystep) {
+ redisAssert(j < argc);
+ keys[i] = j;
+ }
+ return keys;
+}
+
+int *getKeysFromCommand(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {
+ if (cmd->getkeys_proc) {
+ return cmd->getkeys_proc(cmd,argv,argc,numkeys,flags);
+ } else {
+ return getKeysUsingCommandTable(cmd,argv,argc,numkeys);
+ }
+}
+
+void getKeysFreeResult(int *result) {
+ zfree(result);
+}
+
+int *noPreloadGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {
+ if (flags & REDIS_GETKEYS_PRELOAD) {
+ *numkeys = 0;
+ return NULL;
+ } else {
+ return getKeysUsingCommandTable(cmd,argv,argc,numkeys);
+ }
+}
+
+int *renameGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {
+ if (flags & REDIS_GETKEYS_PRELOAD) {
+ int *keys = zmalloc(sizeof(int));
+ *numkeys = 1;
+ keys[0] = 1;
+ return NULL;
+ } else {
+ return getKeysUsingCommandTable(cmd,argv,argc,numkeys);
+ }
+}
+
+int *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {
+ int i, num, *keys;
+ REDIS_NOTUSED(cmd);
+ REDIS_NOTUSED(flags);
+
+ num = atoi(argv[2]->ptr);
+ /* Sanity check. Don't return any key if the command is going to
+ * reply with syntax error. */
+ if (num > (argc-3)) {
+ *numkeys = 0;
+ return NULL;
+ }
+ keys = zmalloc(num);
+ for (i = 0; i < num; i++) keys[i] = 3+i;
+ *numkeys = num;
+ return keys;
+}
diff --git a/src/dscache.c b/src/dscache.c
index cbe9bb016..5813052ed 100644
--- a/src/dscache.c
+++ b/src/dscache.c
@@ -903,6 +903,7 @@ int waitForSwappedKey(redisClient *c, robj *key) {
return 1;
}
+#if 0
/* Preload keys for any command with first, last and step values for
* the command keys prototype, as defined in the command table. */
void waitForMultipleSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv) {
@@ -955,6 +956,7 @@ void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int
}
}
}
+#endif
/* Is this client attempting to run a command against swapped keys?
* If so, block it ASAP, load the keys in background, then resume it.
@@ -967,11 +969,13 @@ void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int
* Return 1 if the client is marked as blocked, 0 if the client can
* continue as the keys it is going to access appear to be in memory. */
int blockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd) {
- if (cmd->vm_preload_proc != NULL) {
- cmd->vm_preload_proc(c,cmd,c->argc,c->argv);
- } else {
- waitForMultipleSwappedKeys(c,cmd,c->argc,c->argv);
- }
+ int *keyindex, numkeys, j;
+
+ keyindex = getKeysFromCommand(cmd,c->argv,c->argc,&numkeys,REDIS_GETKEYS_PRELOAD);
+ for (j = 0; j < numkeys; j++) waitForSwappedKey(c,c->argv[keyindex[j]]);
+ getKeysFreeResult(keyindex);
+
+#warning "Handle EXEC here"
/* If the client was blocked for at least one key, mark it as blocked. */
if (listLength(c->io_keys)) {
diff --git a/src/redis.c b/src/redis.c
index 51e58f587..19fd912cb 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -168,7 +168,7 @@ struct redisCommand redisCommandTable[] = {
{"lastsave",lastsaveCommand,1,0,NULL,0,0,0,0,0},
{"type",typeCommand,2,0,NULL,1,1,1,0,0},
{"multi",multiCommand,1,0,NULL,0,0,0,0,0},
- {"exec",execCommand,1,REDIS_CMD_DENYOOM,execGetKeys,0,0,0,0,0},
+ {"exec",execCommand,1,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0},
{"discard",discardCommand,1,0,NULL,0,0,0,0,0},
{"sync",syncCommand,1,0,NULL,0,0,0,0,0},
{"flushdb",flushdbCommand,1,0,NULL,0,0,0,0,0},
diff --git a/src/redis.h b/src/redis.h
index cdddb6012..b51883309 100644
--- a/src/redis.h
+++ b/src/redis.h
@@ -507,20 +507,19 @@ typedef struct pubsubPattern {
} pubsubPattern;
typedef void redisCommandProc(redisClient *c);
-typedef void redisVmPreloadProc(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
+typedef int *redisGetKeysProc(struct redisCommand *cmd, robj **argv, int argc, int *numkeys, int flags);
struct redisCommand {
char *name;
redisCommandProc *proc;
int arity;
int flags;
- /* Use a function to determine which keys need to be loaded
- * in the background prior to executing this command. Takes precedence
- * over vm_firstkey and others, ignored when NULL */
- redisVmPreloadProc *vm_preload_proc;
+ /* Use a function to determine keys arguments in a command line.
+ * Used both for diskstore preloading and Redis Cluster. */
+ redisGetKeysProc *getkeys_proc;
/* What keys should be loaded in background when calling this command? */
- int vm_firstkey; /* The first argument that's a key (0 = no keys) */
- int vm_lastkey; /* THe last argument that's a key */
- int vm_keystep; /* The step between first and last key */
+ int firstkey; /* The first argument that's a key (0 = no keys) */
+ int lastkey; /* THe last argument that's a key */
+ int keystep; /* The step between first and last key */
long long microseconds, calls;
};
@@ -829,8 +828,6 @@ void freeIOJob(iojob *j);
void queueIOJob(iojob *j);
void waitEmptyIOJobsQueue(void);
void processAllPendingIOJobs(void);
-void zunionInterBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
-void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
int blockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd);
int dontWaitForSwappedKey(redisClient *c, robj *key);
void handleClientsBlockedOnSwappedKey(redisDb *db, robj *key);
@@ -917,6 +914,15 @@ int selectDb(redisClient *c, int id);
void signalModifiedKey(redisDb *db, robj *key);
void signalFlushedDb(int dbid);
+/* API to get key arguments from commands */
+#define REDIS_GETKEYS_ALL 0
+#define REDIS_GETKEYS_PRELOAD 1
+int *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys, int flags);
+void getKeysFreeResult(int *result);
+int *noPreloadGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags);
+int *renameGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags);
+int *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags);
+
/* Git SHA1 */
char *redisGitSHA1(void);
char *redisGitDirty(void);