int setTypeAdd(robj *subject, robj *value) { long long llval; if (subject->encoding == REDIS_ENCODING_HT) { if (dictAdd(subject->ptr,value,NULL) == DICT_OK) { incrRefCount(value); return 1; } } else if (subject->encoding == REDIS_ENCODING_INTSET) { if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) { uint8_t success = 0; subject->ptr = intsetAdd(subject->ptr,llval,&success); if (success) { /* Convert to regular set when the intset contains * too many entries. */ if (intsetLen(subject->ptr) > server.set_max_intset_entries) setTypeConvert(subject,REDIS_ENCODING_HT); return 1; } } else { /* Failed to get integer from object, convert to regular set. */ setTypeConvert(subject,REDIS_ENCODING_HT); /* The set *was* an intset and this value is not integer * encodable, so dictAdd should always work. */ redisAssert(dictAdd(subject->ptr,value,NULL) == DICT_OK); incrRefCount(value); return 1; } } else { redisPanic("Unknown set encoding"); } return 0; }
/* Factory method to return a set that *can* hold "value". When the object has * an integer-encodable value, an intset will be returned. Otherwise a regular * hash table. */ robj* setTypeCreate(robj* value) { if (isObjectRepresentableAsLongLong(value, NULL) == REDIS_OK) { return createIntsetObject(); } return createSetObject(); }
int setTypeIsMember(robj *subject, robj *value) { long long llval; if (subject->encoding == REDIS_ENCODING_HT) { return dictFind((dict*)subject->ptr,value) != NULL; } else if (subject->encoding == REDIS_ENCODING_INTSET) { if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) { return intsetFind((intset*)subject->ptr,llval); } } else { redisPanic("Unknown set encoding"); } return 0; }
int setTypeRemove(robj *setobj, robj *value) { long long llval; if (setobj->encoding == REDIS_ENCODING_HT) { if (dictDelete(setobj->ptr,value) == DICT_OK) { if (htNeedsResize(setobj->ptr)) dictResize(setobj->ptr); return 1; } } else if (setobj->encoding == REDIS_ENCODING_INTSET) { if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) { int success; setobj->ptr = intsetRemove(setobj->ptr,llval,&success); if (success) return 1; } } else { redisPanic("Unknown set encoding"); } return 0; }
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); }