mirror of
https://github.com/fluencelabs/redis
synced 2025-03-17 16:10:50 +00:00
new preloading implemented, still EXEC not handled correctly, everything to test
This commit is contained in:
parent
03af999cb0
commit
9791f0f8ce
72
src/db.c
72
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;
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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},
|
||||
|
26
src/redis.h
26
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user