Compare commits

...
2 Commits
Author SHA1 Message Date
antirez 9545957a67 Scripting: native lua.exists() implementation.
This was a test to check how much faster native implementation would be.
In initial tests it does not look like is this huge win.

After all this is at least in part obvious. Now scripting.c tries to
avoid allocations of argument vectors, and turning ":1" accumulated in
the client buffer into a Lua type is a fast operation.
2015-03-06 16:24:44 -08:00
antirez 2bf27c3361 Transactions: Implementation of the IF command 2015-03-06 10:35:45 -08:00
5 changed files with 80 additions and 2 deletions
+1 -1
View File
@@ -62,7 +62,7 @@ robj *lookupKeyRead(redisDb *db, robj *key) {
if (expireIfNeeded(db,key) == 1) {
/* Key expired. If we are in the context of a master, expireIfNeeded()
* returns 0 only when the key does not exist at all, so it's save
* returns 0 only when the key does not exist at all, so it's safe
* to return NULL ASAP. */
if (server.masterhost == NULL) return NULL;
+42
View File
@@ -304,6 +304,9 @@ void touchWatchedKeysOnFlush(int dbid) {
}
}
/* WATCH key key key ...
* Add keys to the set of watched keys. If those keys are modified
* before the next transaction is executed, the transaction aborts. */
void watchCommand(redisClient *c) {
int j;
@@ -316,8 +319,47 @@ void watchCommand(redisClient *c) {
addReply(c,shared.ok);
}
/* UNWATCH
* Flush the set of watched keys. */
void unwatchCommand(redisClient *c) {
unwatchAllKeys(c);
c->flags &= (~REDIS_DIRTY_CAS);
addReply(c,shared.ok);
}
/* IF XX key key key ...
* IF NX key key key ...
* Abort transaction if condition is not met. */
void ifCommand(redisClient *c) {
int j;
int xx = 0, nx = 0;
if (!(c->flags & REDIS_MULTI)) {
addReplyError(c,"IF outside MULTI is not allowed");
return;
}
/* Check if it's xx or nx option, trying to do it reasonably fast. */
char *a = c->argv[1]->ptr;
if ((a[0] == 'n' || a[0] == 'N') &&
(a[1] == 'x' || a[1] == 'X') && a[2] == '\0')
{
nx = 1;
} else if ((a[0] == 'x' || a[0] == 'X') &&
(a[1] == 'x' || a[1] == 'X') && a[2] == '\0')
{
xx = 1;
} else {
addReply(c,shared.syntaxerr);
return;
}
/* Check if keys exist / don't exist, and flag the transaction if
* at least one key fails the test according to NX / XX option. */
for (j = 2; j < c->argc; j++) {
robj *o = lookupKeyRead(c->db,c->argv[j]);
if ((o != NULL && nx) || (o == NULL && xx))
c->flags |= REDIS_DIRTY_CAS;
}
addReply(c,shared.ok);
}
+2 -1
View File
@@ -261,6 +261,7 @@ struct redisCommand redisCommandTable[] = {
{"pubsub",pubsubCommand,-2,"pltrR",0,NULL,0,0,0,0,0},
{"watch",watchCommand,-2,"rsF",0,NULL,1,-1,1,0,0},
{"unwatch",unwatchCommand,1,"rsF",0,NULL,0,0,0,0,0},
{"if",ifCommand,-2,"rsF",0,NULL,2,-1,1,0,0},
{"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0},
{"restore",restoreCommand,-4,"wm",0,NULL,1,1,1,0,0},
{"restore-asking",restoreCommand,-4,"wmk",0,NULL,1,1,1,0,0},
@@ -2336,7 +2337,7 @@ int processCommand(redisClient *c) {
/* Exec the command */
if (c->flags & REDIS_MULTI &&
c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&
c->cmd->proc != execCommand && c->cmd->proc != ifCommand &&
c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)
{
queueMultiCommand(c);
+1
View File
@@ -1561,6 +1561,7 @@ void pfcountCommand(redisClient *c);
void pfmergeCommand(redisClient *c);
void pfdebugCommand(redisClient *c);
void latencyCommand(redisClient *c);
void ifCommand(redisClient *c);
#if defined(__GNUC__)
void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
+34
View File
@@ -458,6 +458,35 @@ int luaRedisPCallCommand(lua_State *lua) {
return luaRedisGenericCommand(lua,0);
}
int luaExistsCommand(lua_State *lua) {
int argc = lua_gettop(lua);
redisClient *c = server.lua_client;
char *obj_s;
size_t obj_len;
robj *key, *val;
/* Require at least one argument */
if (argc != 1) {
luaPushError(lua,
"redis.exists() needs exactly one argument");
return 1;
}
obj_s = (char*)lua_tolstring(lua,1,&obj_len);
if (obj_s == NULL) {
luaPushError(lua,
"redis.exists() argument must be a string");
return 1;
}
key = createStringObject(obj_s,obj_len);
val = lookupKeyRead(c->db,key);
decrRefCount(key);
lua_pushnumber(lua,val != NULL);
return 1;
}
/* This adds redis.sha1hex(string) to Lua scripts using the same hashing
* function used for sha1ing lua scripts. */
int luaRedisSha1hexCommand(lua_State *lua) {
@@ -664,6 +693,11 @@ void scriptingInit(void) {
lua_pushcfunction(lua,luaRedisPCallCommand);
lua_settable(lua,-3);
/* redis.exists */
lua_pushstring(lua,"exists");
lua_pushcfunction(lua,luaExistsCommand);
lua_settable(lua,-3);
/* redis.log and log levels. */
lua_pushstring(lua,"log");
lua_pushcfunction(lua,luaLogCommand);