void getsetCommand(redisClient *c) { uint16_t version = sdsversion(c->argv[1]->ptr); if (getGenericCommand(c) == REDIS_ERR) return; c->argv[2] = tryObjectEncoding(c->argv[2]); if (c->returncode == REDIS_OK_NOT_EXIST) { sdsversion_change(c->argv[1]->ptr, 0); } else { if(c->version_care && version != 0 && version != c->version) { c->returncode = REDIS_ERR_VERSION_ERROR; return; } else { sdsversion_change(c->argv[1]->ptr, c->version); } } if(c->version_care) { sdsversion_add(c->argv[1]->ptr, 1); } dbSuperReplace(c->db,c->argv[1],c->argv[2]); incrRefCount(c->argv[2]); c->db->dirty++; if (c->expiretime > 0) { setExpire(c->db,c->argv[1],c->expiretime); } else if(c->expiretime == 0) { removeXExpire(c->db, c->argv[1]); } c->returncode = REDIS_OK; }
void pushnGenericCommand(redisClient *c, int where) { /* return_value must be null,otherwise it have memory leak */ c->returncode = REDIS_ERR; robj *lobj = lookupKeyWriteWithVersion(c->db, c->argv[1], &c->version); robj* key = c->argv[1]; if(lobj != NULL) { if(checkType(c, lobj, REDIS_LIST)) { c->returncode = REDIS_ERR_WRONG_TYPE_ERROR; return; } uint16_t version = sdsversion(key->ptr); if(c->version_care && version != 0 && version != c->version) { c->returncode = REDIS_ERR_VERSION_ERROR; return; } else { sdsversion_change(key->ptr, c->version); } } else { sdsversion_change(key->ptr, 0); } if(c->version_care) { sdsversion_add(key->ptr, 1); } c->return_value = (void*)zmalloc(sizeof(push_return_value)); if(c->return_value == NULL) { c->returncode = REDIS_ERR_MEMORY_ALLOCATE_ERROR; return; } int i = 2; for(; i < c->argc; i++) { if(lobj == NULL) { c->argv[i] = tryObjectEncoding(c->argv[i]); lobj = createZiplistObject(); dbAdd(c->db,c->argv[1],lobj); } unsigned long list_len = listTypeLength(lobj); if (list_len >= (unsigned long)(c->server->list_max_size)) { break; } listTypePush(c,lobj,c->argv[i],where); c->server->dirty++; } if (i != 2) { dbUpdateKey(c->db, key); EXPIRE_OR_NOT }
void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expire) { int retval; long seconds = 0; /* initialized to avoid an harmness warning */ robj *oldval; c->returncode = REDIS_ERR; if (expire) { if (getLongFromObject(expire, &seconds) != REDIS_OK) { c->returncode = REDIS_ERR_IS_NOT_INTEGER; return; } } oldval = lookupKeyWriteWithVersion(c->db,key,&(c->version)); /* Force expire of old key if needed */ if(oldval != NULL) { if(checkType(c, oldval, REDIS_STRING)) { c->returncode = REDIS_ERR_WRONG_TYPE_ERROR; return; } uint16_t version = sdsversion(key->ptr); if(c->version_care && version != 0 && version != c->version) { c->returncode = REDIS_ERR_VERSION_ERROR; return; } else { sdsversion_change(key->ptr, c->version); } } else { sdsversion_change(key->ptr, 0); } if(c->version_care) { sdsversion_add(key->ptr, 1); } retval = dbAdd(c->db,key,val); if (retval == REDIS_ERR) { if (!nx) { dbSuperReplace(c->db,key,val); incrRefCount(val); } else { c->returncode = REDIS_OK_BUT_ALREADY_EXIST; return; } } else { incrRefCount(val); } c->db->dirty++; if (expire) { setExpire(c->db,key,seconds); } else if(c->expiretime == 0) { removeXExpire(c->db, key); } c->returncode = REDIS_OK; }
void incrDecrCommand(redisClient *c, long long init_value, long long incr) { c->returncode = REDIS_ERR; long long value; long long oldvalue; robj *o; oldvalue=0; oldvalue++; o = lookupKeyWriteWithVersion(c->db,c->argv[1],&(c->version)); if (o != NULL && checkType(c,o,REDIS_STRING)) { c->returncode = REDIS_ERR_WRONG_TYPE_ERROR; return; } robj* key = c->argv[1]; if(o != NULL) { uint16_t version = sdsversion(key->ptr); if(c->version_care && version != 0 && version != c->version) { c->returncode = REDIS_ERR_VERSION_ERROR; return; } else { sdsversion_change(key->ptr, c->version); } } else { sdsversion_change(key->ptr, 0); } if(c->version_care) { sdsversion_add(key->ptr, 1); } if (o == NULL) { value = init_value; } else if (getLongLongFromObject(o,&value) != REDIS_OK) { c->returncode = REDIS_ERR_IS_NOT_INTEGER; return; } oldvalue = value; value += incr; value = (int32_t)value; o = createStringObjectFromLongLong(value); dbSuperReplace(c->db,c->argv[1],o); c->db->dirty++; EXPIRE_OR_NOT c->retvalue.llnum = value; c->returncode = REDIS_OK; }
robj *lookupKeyWithVersion(redisDb *db, robj *key, uint16_t* version) { dictEntry *de = dictFind(db->dict, key->ptr); if(de) { robj *val = dictGetEntryVal(de); sds key_tmp = dictGetEntryKey(de); *version = sdsversion(key_tmp); val->lru = shared.lruclock; db->stat_keyspace_hits++; return val; } else { db->stat_keyspace_misses++; return NULL; } }
/* Return a random key, in form of a Redis object. * If there are no keys, NULL is returned. * * The function makes sure to return keys not already expired. */ robj *dbRandomKey(redisDb *db) { struct dictEntry *de; while(1) { sds key; robj *keyobj; de = dictGetRandomKey(db->dict); if (de == NULL) return NULL; key = dictGetEntryKey(de); keyobj = createStringObject(key,sdslen(key),sdslogiclock(key),sdsversion(key)); if (dictFind(db->expires,key)) { if (expireIfNeeded(db,keyobj)) { decrRefCount(keyobj); continue; /* search for another key. This expired. */ } } return keyobj; } }