mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 08:38:27 -05:00
LPUSHPOP first implementation
This commit is contained in:
parent
bcfc686db7
commit
12f9d551b6
2
TODO
2
TODO
@ -3,13 +3,13 @@ VERSION 1.1 TODO
|
|||||||
* For now only the last argument gets integer encoded, so make sure that: 1) every multi bulk commands implemented will have the last arg that is indeed a value, and not used otherwise. 2) to explicitly call the function to encode the object in MSET and other commands where there are multiple "values".
|
* For now only the last argument gets integer encoded, so make sure that: 1) every multi bulk commands implemented will have the last arg that is indeed a value, and not used otherwise. 2) to explicitly call the function to encode the object in MSET and other commands where there are multiple "values".
|
||||||
* Man pages for MSET MSETNX and SRANDMEMBER, Z-commands, ...
|
* Man pages for MSET MSETNX and SRANDMEMBER, Z-commands, ...
|
||||||
* ZSETs missing stuff: ZINCRBY
|
* ZSETs missing stuff: ZINCRBY
|
||||||
* Add all the missing symbols for the static functions into the table. Crete a Tcl script to check this. This backtrace on segfault is indeed *very* useful.
|
|
||||||
* Use strcoll() to compare objects in sorted sets, like it already happens for SORT.
|
* Use strcoll() to compare objects in sorted sets, like it already happens for SORT.
|
||||||
* LMOVE, as discussed in the Redis group.
|
* LMOVE, as discussed in the Redis group.
|
||||||
* EXPIRE, EXPIREAT, ZSCORE tests.
|
* EXPIRE, EXPIREAT, ZSCORE tests.
|
||||||
* Write docs for the "STORE" operaiton of SORT, and GET "#" option.
|
* Write docs for the "STORE" operaiton of SORT, and GET "#" option.
|
||||||
* Append only mode: testing and a command to rebuild the log from scratch.
|
* Append only mode: testing and a command to rebuild the log from scratch.
|
||||||
* Profiling and optimizations. For instance the commands lookup is probably starting to eat too CPU being a simple list. To implement binary search or an hash table lookup can be a win probably.
|
* Profiling and optimizations. For instance the commands lookup is probably starting to eat too CPU being a simple list. To implement binary search or an hash table lookup can be a win probably.
|
||||||
|
* Redis-cli should be able to select a different DB than 0 using some switch.
|
||||||
|
|
||||||
VERSION 1.2 TODO
|
VERSION 1.2 TODO
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ static struct redisCommand cmdTable[] = {
|
|||||||
{"lrange",4,REDIS_CMD_INLINE},
|
{"lrange",4,REDIS_CMD_INLINE},
|
||||||
{"ltrim",4,REDIS_CMD_INLINE},
|
{"ltrim",4,REDIS_CMD_INLINE},
|
||||||
{"lrem",4,REDIS_CMD_BULK},
|
{"lrem",4,REDIS_CMD_BULK},
|
||||||
|
{"lpoppush",3,REDIS_CMD_BULK},
|
||||||
{"sadd",3,REDIS_CMD_BULK},
|
{"sadd",3,REDIS_CMD_BULK},
|
||||||
{"srem",3,REDIS_CMD_BULK},
|
{"srem",3,REDIS_CMD_BULK},
|
||||||
{"smove",4,REDIS_CMD_BULK},
|
{"smove",4,REDIS_CMD_BULK},
|
||||||
|
70
redis.c
70
redis.c
@ -446,6 +446,7 @@ static void flushdbCommand(redisClient *c);
|
|||||||
static void flushallCommand(redisClient *c);
|
static void flushallCommand(redisClient *c);
|
||||||
static void sortCommand(redisClient *c);
|
static void sortCommand(redisClient *c);
|
||||||
static void lremCommand(redisClient *c);
|
static void lremCommand(redisClient *c);
|
||||||
|
static void lpoppushCommand(redisClient *c);
|
||||||
static void infoCommand(redisClient *c);
|
static void infoCommand(redisClient *c);
|
||||||
static void mgetCommand(redisClient *c);
|
static void mgetCommand(redisClient *c);
|
||||||
static void monitorCommand(redisClient *c);
|
static void monitorCommand(redisClient *c);
|
||||||
@ -489,6 +490,7 @@ static struct redisCommand cmdTable[] = {
|
|||||||
{"lrange",lrangeCommand,4,REDIS_CMD_INLINE},
|
{"lrange",lrangeCommand,4,REDIS_CMD_INLINE},
|
||||||
{"ltrim",ltrimCommand,4,REDIS_CMD_INLINE},
|
{"ltrim",ltrimCommand,4,REDIS_CMD_INLINE},
|
||||||
{"lrem",lremCommand,4,REDIS_CMD_BULK},
|
{"lrem",lremCommand,4,REDIS_CMD_BULK},
|
||||||
|
{"lpoppush",lpoppushCommand,3,REDIS_CMD_BULK},
|
||||||
{"sadd",saddCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
|
{"sadd",saddCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
|
||||||
{"srem",sremCommand,3,REDIS_CMD_BULK},
|
{"srem",sremCommand,3,REDIS_CMD_BULK},
|
||||||
{"smove",smoveCommand,4,REDIS_CMD_BULK},
|
{"smove",smoveCommand,4,REDIS_CMD_BULK},
|
||||||
@ -1403,10 +1405,10 @@ static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask)
|
|||||||
c->sentlen = 0;
|
c->sentlen = 0;
|
||||||
}
|
}
|
||||||
/* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT
|
/* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT
|
||||||
* bytes, in a single threaded server it's a good idea to server
|
* bytes, in a single threaded server it's a good idea to serve
|
||||||
* other clients as well, even if a very large request comes from
|
* other clients as well, even if a very large request comes from
|
||||||
* super fast link that is always able to accept data (in real world
|
* super fast link that is always able to accept data (in real world
|
||||||
* terms think to 'KEYS *' against the loopback interfae) */
|
* scenario think about 'KEYS *' against the loopback interfae) */
|
||||||
if (totwritten > REDIS_MAX_WRITE_PER_EVENT) break;
|
if (totwritten > REDIS_MAX_WRITE_PER_EVENT) break;
|
||||||
}
|
}
|
||||||
if (nwritten == -1) {
|
if (nwritten == -1) {
|
||||||
@ -3468,6 +3470,70 @@ static void lremCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the semantic of this command:
|
||||||
|
* LPOPPUSH srclist dstlist:
|
||||||
|
* IF LLEN(srclist) > 0
|
||||||
|
* element = RPOP srclist
|
||||||
|
* LPUSH dstlist element
|
||||||
|
* RETURN element
|
||||||
|
* ELSE
|
||||||
|
* RETURN nil
|
||||||
|
* END
|
||||||
|
* END
|
||||||
|
*
|
||||||
|
* The idea is to be able to get an element from a list in a reliable way
|
||||||
|
* since the element is not just returned but pushed against another list
|
||||||
|
* as well. This command was originally proposed by Ezra Zygmuntowicz.
|
||||||
|
*/
|
||||||
|
static void lpoppushCommand(redisClient *c) {
|
||||||
|
robj *sobj;
|
||||||
|
|
||||||
|
sobj = lookupKeyWrite(c->db,c->argv[1]);
|
||||||
|
if (sobj == NULL) {
|
||||||
|
addReply(c,shared.nullbulk);
|
||||||
|
} else {
|
||||||
|
if (sobj->type != REDIS_LIST) {
|
||||||
|
addReply(c,shared.wrongtypeerr);
|
||||||
|
} else {
|
||||||
|
list *srclist = sobj->ptr;
|
||||||
|
listNode *ln = listLast(srclist);
|
||||||
|
|
||||||
|
if (ln == NULL) {
|
||||||
|
addReply(c,shared.nullbulk);
|
||||||
|
} else {
|
||||||
|
robj *dobj = lookupKeyWrite(c->db,c->argv[2]);
|
||||||
|
robj *ele = listNodeValue(ln);
|
||||||
|
list *dstlist;
|
||||||
|
|
||||||
|
if (dobj == NULL) {
|
||||||
|
|
||||||
|
/* Create the list if the key does not exist */
|
||||||
|
dobj = createListObject();
|
||||||
|
dictAdd(c->db->dict,c->argv[2],dobj);
|
||||||
|
incrRefCount(c->argv[2]);
|
||||||
|
} else if (dobj->type != REDIS_LIST) {
|
||||||
|
addReply(c,shared.wrongtypeerr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Add the element to the target list */
|
||||||
|
dstlist = dobj->ptr;
|
||||||
|
listAddNodeHead(dstlist,ele);
|
||||||
|
incrRefCount(ele);
|
||||||
|
|
||||||
|
/* Send the element to the client as reply as well */
|
||||||
|
addReplyBulkLen(c,ele);
|
||||||
|
addReply(c,ele);
|
||||||
|
addReply(c,shared.crlf);
|
||||||
|
|
||||||
|
/* Finally remove the element from the source list */
|
||||||
|
listDelNode(srclist,ln);
|
||||||
|
server.dirty++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ==================================== Sets ================================ */
|
/* ==================================== Sets ================================ */
|
||||||
|
|
||||||
static void saddCommand(redisClient *c) {
|
static void saddCommand(redisClient *c) {
|
||||||
|
@ -916,7 +916,7 @@ proc stress {} {
|
|||||||
set randval [expr int(rand()*10000)]
|
set randval [expr int(rand()*10000)]
|
||||||
set randidx0 [expr int(rand()*10)]
|
set randidx0 [expr int(rand()*10)]
|
||||||
set randidx1 [expr int(rand()*10)]
|
set randidx1 [expr int(rand()*10)]
|
||||||
set cmd [expr int(rand()*10)]
|
set cmd [expr int(rand()*20)]
|
||||||
catch {
|
catch {
|
||||||
if {$cmd == 0} {$r set $randkey $randval}
|
if {$cmd == 0} {$r set $randkey $randval}
|
||||||
if {$cmd == 1} {$r get $randkey}
|
if {$cmd == 1} {$r get $randkey}
|
||||||
@ -924,10 +924,16 @@ proc stress {} {
|
|||||||
if {$cmd == 3} {$r lpush $randkey $randval}
|
if {$cmd == 3} {$r lpush $randkey $randval}
|
||||||
if {$cmd == 4} {$r rpop $randkey}
|
if {$cmd == 4} {$r rpop $randkey}
|
||||||
if {$cmd == 5} {$r del $randkey}
|
if {$cmd == 5} {$r del $randkey}
|
||||||
if {$cmd == 6} {$r lrange $randkey $randidx0 $randidx1}
|
if {$cmd == 6} {$r llen $randkey}
|
||||||
if {$cmd == 7} {$r ltrim $randkey $randidx0 $randidx1}
|
if {$cmd == 7} {$r lrange $randkey $randidx0 $randidx1}
|
||||||
if {$cmd == 8} {$r lindex $randkey $randidx0}
|
if {$cmd == 8} {$r ltrim $randkey $randidx0 $randidx1}
|
||||||
if {$cmd == 9} {$r lset $randkey $randidx0 $randval}
|
if {$cmd == 9} {$r lindex $randkey $randidx0}
|
||||||
|
if {$cmd == 10} {$r lset $randkey $randidx0 $randval}
|
||||||
|
if {$cmd == 11} {$r sadd $randkey $randval}
|
||||||
|
if {$cmd == 12} {$r srem $randkey $randval}
|
||||||
|
if {$cmd == 13} {$r smove $randkey $randval}
|
||||||
|
if {$cmd == 14} {$r scard $randkey}
|
||||||
|
if {$cmd == 15} {$r expire $randkey [expr $randval%60]}
|
||||||
}
|
}
|
||||||
flush stdout
|
flush stdout
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user