X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/753bb3dcbda2fbb91539057e300b999bc750c9e0..4b1f6ad3e7a5c7c28618e43e7539c9a937bf8521:/src/t_hash.c?ds=sidebyside diff --git a/src/t_hash.c b/src/t_hash.c index b3928450..aa021b03 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -135,7 +135,9 @@ int hashTypeExists(robj *o, robj *field) { } /* Add an element, discard the old if the key already exists. - * Return 0 on insert and 1 on update. */ + * Return 0 on insert and 1 on update. + * This function will take care of incrementing the reference count of the + * retained fields and value objects. */ int hashTypeSet(robj *o, robj *field, robj *value) { int update = 0; @@ -168,30 +170,23 @@ int hashTypeSet(robj *o, robj *field, robj *value) { zl = ziplistPush(zl, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL); zl = ziplistPush(zl, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL); } - o->ptr = zl; - decrRefCount(field); decrRefCount(value); /* Check if the ziplist needs to be converted to a hash table */ - if (hashTypeLength(o) > server.hash_max_ziplist_entries) { + if (hashTypeLength(o) > server.hash_max_ziplist_entries) hashTypeConvert(o, REDIS_ENCODING_HT); - } - } else if (o->encoding == REDIS_ENCODING_HT) { if (dictReplace(o->ptr, field, value)) { /* Insert */ incrRefCount(field); } else { /* Update */ update = 1; } - incrRefCount(value); - } else { redisPanic("Unknown hash encoding"); } - return update; } @@ -408,7 +403,11 @@ void hashTypeConvertZiplist(robj *o, int enc) { value = hashTypeCurrentObject(hi, REDIS_HASH_VALUE); value = tryObjectEncoding(value); ret = dictAdd(dict, field, value); - redisAssert(ret == DICT_OK); + if (ret != DICT_OK) { + redisLogHexDump(REDIS_WARNING,"ziplist with dup elements dump", + o->ptr,ziplistBlobLen(o->ptr)); + redisAssert(ret == DICT_OK); + } } hashTypeReleaseIterator(hi); @@ -520,7 +519,7 @@ void hincrbyCommand(redisClient *c) { void hincrbyfloatCommand(redisClient *c) { double long value, incr; - robj *o, *current, *new; + robj *o, *current, *new, *aux; if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != REDIS_OK) return; if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return; @@ -540,9 +539,17 @@ void hincrbyfloatCommand(redisClient *c) { hashTypeTryObjectEncoding(o,&c->argv[2],NULL); hashTypeSet(o,c->argv[2],new); addReplyBulk(c,new); - decrRefCount(new); signalModifiedKey(c->db,c->argv[1]); server.dirty++; + + /* Always replicate HINCRBYFLOAT as an HSET command with the final value + * in order to make sure that differences in float pricision or formatting + * will not create differences in replicas or after an AOF restart. */ + aux = createStringObject("HSET",4); + rewriteClientCommandArgument(c,0,aux); + decrRefCount(aux); + rewriteClientCommandArgument(c,3,new); + decrRefCount(new); } static void addHashFieldToReply(redisClient *c, robj *o, robj *field) {