Added msadd #20

Closed
wants to merge 3 commits into
from
Jump to file or symbol
Failed to load files and symbols.
+131 −0
Split
View
@@ -98,6 +98,7 @@ struct redisCommand readonlyCommandTable[] = {
{"lrem",lremCommand,4,0,NULL,1,1,1},
{"rpoplpush",rpoplpushcommand,3,REDIS_CMD_DENYOOM,NULL,1,2,1},
{"sadd",saddCommand,3,REDIS_CMD_DENYOOM,NULL,1,1,1},
+ {"msadd",msaddCommand,-3,REDIS_CMD_DENYOOM,NULL,1,1,1},
{"srem",sremCommand,3,0,NULL,1,1,1},
{"smove",smoveCommand,4,0,NULL,1,2,1},
{"sismember",sismemberCommand,3,0,NULL,1,1,1},
View
@@ -890,6 +890,7 @@ void ltrimCommand(redisClient *c);
void typeCommand(redisClient *c);
void lsetCommand(redisClient *c);
void saddCommand(redisClient *c);
+void msaddCommand(redisClient *c);
void sremCommand(redisClient *c);
void smoveCommand(redisClient *c);
void sismemberCommand(redisClient *c);
View
@@ -197,6 +197,82 @@ void saddCommand(redisClient *c) {
}
}
+void msaddCommand(redisClient *c) {
+ int setnum, valnum;
+ int i, j;
+ robj **sets;
+
+ setnum = atoi(c->argv[1]->ptr);
+ valnum = atoi(c->argv[2]->ptr);
+
+ if (setnum < 1) {
+ addReplyError(c,
+ "at least 1 input key is needed for MSADD");
+ return;
+ }
+
+ if (valnum < 1) {
+ addReplyError(c,
+ "at least 1 input value is needed for MSADD");
+ return;
+ }
+
+ /* test if the expected number of keys would overflow */
+ if (3+setnum+valnum > c->argc) {
+ addReply(c,shared.syntaxerr);
+ return;
+ }
+
+ int useintset = 0;
+ for (j = 0; j < valnum; j++) {
+ robj *value = c->argv[3 + setnum + j];
+ if (isObjectRepresentableAsLongLong(value,NULL) != REDIS_OK) {
+ useintset = 1;
+ break;
+ }
+ }
+
+ sets = zmalloc(sizeof(robj*)*setnum);
+ int notset = 0;
+ for (i = 0; i < setnum; i++) {
+ robj *key = c->argv[3 + i];
+ robj *set = lookupKeyWrite(c->db, key);
+ if (set == NULL) {
+ if (useintset == 1)
+ set = createIntsetObject();
+ else
+ set = createSetObject();
+ dbAdd(c->db,key,set);
+ } else {
+ if (set->type != REDIS_SET) {
+ notset = 1;
+ break;
+ }
+ }
+ sets[i] = set;
+ }
+
+ if (notset == 1) {
+ addReply(c,shared.wrongtypeerr);
+ } else {
+ long long inserted = 0;
+ for (i = 0; i < setnum; i++) {
+ for (j = 0; j < valnum; j++) {
+ robj *key = c->argv[3 + i];
+ robj *value = c->argv[3 + setnum + j];
+ robj *set = sets[i];
+ if (setTypeAdd(set,value)) {
+ touchWatchedKey(c->db,key);
+ server.dirty++;
+ inserted++;
+ }
+ }
+ }
+ addReplyLongLong(c,inserted);
+ }
+ zfree(sets);
+}
+
void sremCommand(redisClient *c) {
robj *set;
View
@@ -59,6 +59,59 @@ start_server {
assert_encoding hashtable myset
}
+ test {MSADD, SISMEMBER, SMEMBERS basics - regular sets} {
+ create_set myset {foo}
+ create_set anotherset {bar}
+ assert_encoding hashtable myset
+ assert_equal 1 [r msadd 2 1 anotherset myset bar]
+ assert_equal 0 [r msadd 2 1 anotherset myset bar]
+ assert_equal 0 [r msadd 1 1 myset bar]
+ assert_equal 1 [r msadd 1 2 anotherset bar baz]
+ assert_equal 2 [r scard myset]
+ assert_equal 1 [r sismember myset foo]
+ assert_equal 1 [r sismember myset bar]
+ assert_equal 0 [r sismember myset baz]
+ assert_equal 0 [r sismember myset bla]
+ assert_equal 0 [r sismember anotherset foo]
+ assert_equal 1 [r sismember anotherset bar]
+ assert_equal 1 [r sismember anotherset baz]
+ assert_equal 0 [r sismember anotherset bla]
+ assert_equal {bar foo} [lsort [r smembers myset]]
+ }
+
+ test {MSADD against non set} {
+ r lpush mylist foo
+ create_set myset {foo}
+ assert_error ERR*kind* {r msadd 1 1 mylist bar}
+ assert_error ERR*kind* {r msadd 2 1 mylist myset bar}
+ }
+
+ test "MSADD a non-integer against an intset" {
+ create_set myset {1 2 3}
+ create_set anotherset {foo}
+ assert_encoding intset myset
+ assert_equal 1 [r msadd 1 1 myset a]
+ assert_equal 2 [r msadd 2 1 myset anotherset b]
+ assert_encoding hashtable myset
+ }
+
+ test "MSADD overflows the maximum allowed integers in an intset" {
+ r del myset
+ for {set i 0} {$i < 512} {incr i} { r sadd myset $i }
+ assert_encoding intset myset
+ assert_equal 1 [r msadd 1 1 myset 512]
+ assert_encoding hashtable myset
+ }
+
+# TODO: do this test. It works manually, but I can't make it work with tcl
+# test "MSADD creates an intset with more than the maximum allowed" {
+# r del myset
+# set var ""
+# for {set i 0} {$i < 513} {incr i} { append var " " $i }
+# assert_equal 513 [r msadd 1 513 myset $var]
+# assert_encoding hashtable myset
+# }
+
test "Set encoding after DEBUG RELOAD" {
r del myintset myhashset mylargeintset
for {set i 0} {$i < 100} {incr i} { r sadd myintset $i }