From 97224de7f962f8c39cb357969f83378d12d25f96 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Sat, 17 Apr 2010 12:33:43 +0200 Subject: [PATCH 1/3] strip tryObjectEncoding from hashSet, to enable the arguments being encoded in-place --- redis.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/redis.c b/redis.c index 90fe5e80..75159e4e 100644 --- a/redis.c +++ b/redis.c @@ -6068,6 +6068,14 @@ static void hashTryConversion(robj *subject, robj **argv, int start, int end) { } } +/* Encode given objects in-place when the hash uses a dict. */ +static void hashTryObjectEncoding(robj *subject, robj **o1, robj **o2) { + if (subject->encoding == REDIS_ENCODING_HT) { + *o1 = tryObjectEncoding(*o1); + *o2 = tryObjectEncoding(*o2); + } +} + /* Get the value from a hash identified by key. Returns either a string * object or NULL if the value cannot be found. The refcount of the object * is always increased by 1 when the value was found. */ @@ -6126,7 +6134,6 @@ static int hashSet(robj *o, robj *key, robj *value) { if (zipmapLen(o->ptr) > server.hash_max_zipmap_entries) convertToRealHash(o); } else { - value = tryObjectEncoding(value); if (dictReplace(o->ptr,key,value)) { /* Insert */ incrRefCount(key); @@ -6250,6 +6257,7 @@ static void hsetCommand(redisClient *c) { if ((o = hashLookupWriteOrCreate(c,c->argv[1])) == NULL) return; hashTryConversion(o,c->argv,2,3); + hashTryObjectEncoding(o,&c->argv[2], &c->argv[3]); update = hashSet(o,c->argv[2],c->argv[3]); addReply(c, update ? shared.czero : shared.cone); server.dirty++; @@ -6263,6 +6271,7 @@ static void hsetnxCommand(redisClient *c) { if (hashExists(o, c->argv[2])) { addReply(c, shared.czero); } else { + hashTryObjectEncoding(o,&c->argv[2], &c->argv[3]); hashSet(o,c->argv[2],c->argv[3]); addReply(c, shared.cone); server.dirty++; @@ -6281,6 +6290,7 @@ static void hmsetCommand(redisClient *c) { if ((o = hashLookupWriteOrCreate(c,c->argv[1])) == NULL) return; hashTryConversion(o,c->argv,2,c->argc-1); for (i = 2; i < c->argc; i += 2) { + hashTryObjectEncoding(o,&c->argv[i], &c->argv[i+1]); hashSet(o,c->argv[i],c->argv[i+1]); } addReply(c, shared.ok); From edc2f63ad9c961e54a10f27a44a4b64868160eaa Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Sat, 17 Apr 2010 12:35:22 +0200 Subject: [PATCH 2/3] increment dirty counter after hmset --- redis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/redis.c b/redis.c index 75159e4e..e272b89e 100644 --- a/redis.c +++ b/redis.c @@ -6294,6 +6294,7 @@ static void hmsetCommand(redisClient *c) { hashSet(o,c->argv[i],c->argv[i+1]); } addReply(c, shared.ok); + server.dirty++; } static void hincrbyCommand(redisClient *c) { From 3f973463a7a5d70785dd0c7d33e0e5624a474c94 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Sat, 17 Apr 2010 12:46:23 +0200 Subject: [PATCH 3/3] make sure that the resulting value in hincrby is encoded when possible --- redis.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/redis.c b/redis.c index e272b89e..6a952b01 100644 --- a/redis.c +++ b/redis.c @@ -2775,6 +2775,23 @@ static robj *createStringObject(char *ptr, size_t len) { return createObject(REDIS_STRING,sdsnewlen(ptr,len)); } +static robj *createStringObjectFromLongLong(long long value) { + robj *o; + if (value >= 0 && value < REDIS_SHARED_INTEGERS) { + incrRefCount(shared.integers[value]); + o = shared.integers[value]; + } else { + o = createObject(REDIS_STRING, NULL); + if (value >= LONG_MIN && value <= LONG_MAX) { + o->encoding = REDIS_ENCODING_INT; + o->ptr = (void*)((long)value); + } else { + o->ptr = sdscatprintf(sdsempty(),"%lld",value); + } + } + return o; +} + static robj *dupStringObject(robj *o) { assert(o->encoding == REDIS_ENCODING_RAW); return createStringObject(o->ptr,sdslen(o->ptr)); @@ -6071,8 +6088,8 @@ static void hashTryConversion(robj *subject, robj **argv, int start, int end) { /* Encode given objects in-place when the hash uses a dict. */ static void hashTryObjectEncoding(robj *subject, robj **o1, robj **o2) { if (subject->encoding == REDIS_ENCODING_HT) { - *o1 = tryObjectEncoding(*o1); - *o2 = tryObjectEncoding(*o2); + if (o1) *o1 = tryObjectEncoding(*o1); + if (o2) *o2 = tryObjectEncoding(*o2); } } @@ -6316,7 +6333,8 @@ static void hincrbyCommand(redisClient *c) { } value += incr; - new = createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%lld",value)); + new = createStringObjectFromLongLong(value); + hashTryObjectEncoding(o,&c->argv[2],NULL); hashSet(o,c->argv[2],new); decrRefCount(new); addReplyLongLong(c,value);