예제 #1
0
파일: t_set.c 프로젝트: jrun/redis
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;
}
예제 #2
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();
}
예제 #3
0
파일: t_set.c 프로젝트: jrun/redis
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;
}
예제 #4
0
파일: t_set.c 프로젝트: jrun/redis
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;
}
예제 #5
0
파일: t_set.c 프로젝트: jrun/redis
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); 
}