diff --git a/src/aof.c b/src/aof.c index 89f17abab..2a29f72fb 100644 --- a/src/aof.c +++ b/src/aof.c @@ -591,7 +591,7 @@ int rioWriteBulkObject(rio *r, robj *obj) { * in a child process when this function is called). */ if (obj->encoding == REDIS_ENCODING_INT) { return rioWriteBulkLongLong(r,(long)obj->ptr); - } else if (obj->encoding == REDIS_ENCODING_RAW) { + } else if (sdsEncodedObject(obj)) { return rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr)); } else { redisPanic("Unknown string encoding"); diff --git a/src/bitops.c b/src/bitops.c index c96a9e3c7..599d4dd8e 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -133,7 +133,7 @@ void setbitCommand(redisClient *c) { /* Create a copy when the object is shared or encoded. */ if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) { robj *decoded = getDecodedObject(o); - o = createStringObject(decoded->ptr, sdslen(decoded->ptr)); + o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr)); decrRefCount(decoded); dbOverwrite(c->db,c->argv[1],o); } @@ -174,12 +174,12 @@ void getbitCommand(redisClient *c) { byte = bitoffset >> 3; bit = 7 - (bitoffset & 0x7); - if (o->encoding != REDIS_ENCODING_RAW) { - if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr)) - bitval = llbuf[byte] & (1 << bit); - } else { + if (sdsEncodedObject(o)) { if (byte < sdslen(o->ptr)) bitval = ((uint8_t*)o->ptr)[byte] & (1 << bit); + } else { + if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr)) + bitval = llbuf[byte] & (1 << bit); } addReply(c, bitval ? shared.cone : shared.czero); diff --git a/src/cluster.c b/src/cluster.c index 76ab67112..017989df3 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -2691,7 +2691,7 @@ try_again: rioWriteBulkString(&cmd,"RESTORE-ASKING",14)); else redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"RESTORE",7)); - redisAssertWithInfo(c,NULL,c->argv[3]->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(c,NULL,sdsEncodedObject(c->argv[3])); redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,c->argv[3]->ptr,sdslen(c->argv[3]->ptr))); redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl)); diff --git a/src/config.c b/src/config.c index 78b458dcc..3a14a6e94 100644 --- a/src/config.c +++ b/src/config.c @@ -550,8 +550,8 @@ void loadServerConfig(char *filename, char *options) { void configSetCommand(redisClient *c) { robj *o; long long ll; - redisAssertWithInfo(c,c->argv[2],c->argv[2]->encoding == REDIS_ENCODING_RAW); - redisAssertWithInfo(c,c->argv[2],c->argv[3]->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(c,c->argv[2],sdsEncodedObject(c->argv[2])); + redisAssertWithInfo(c,c->argv[3],sdsEncodedObject(c->argv[3])); o = c->argv[3]; if (!strcasecmp(c->argv[2]->ptr,"dbfilename")) { @@ -918,7 +918,7 @@ void configGetCommand(redisClient *c) { char *pattern = o->ptr; char buf[128]; int matches = 0; - redisAssertWithInfo(c,o,o->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(c,o,sdsEncodedObject(o)); /* String values */ config_get_string_field("dbfilename",server.rdb_filename); diff --git a/src/debug.c b/src/debug.c index 0a947e564..a0352b5dd 100644 --- a/src/debug.c +++ b/src/debug.c @@ -373,9 +373,7 @@ void _redisAssertPrintClientInfo(redisClient *c) { char buf[128]; char *arg; - if (c->argv[j]->type == REDIS_STRING && - c->argv[j]->encoding == REDIS_ENCODING_RAW) - { + if (c->argv[j]->type == REDIS_STRING && sdsEncodedObject(c->argv[j])) { arg = (char*) c->argv[j]->ptr; } else { snprintf(buf,sizeof(buf),"Object type: %d, encoding: %d", @@ -391,7 +389,7 @@ void redisLogObjectDebugInfo(robj *o) { redisLog(REDIS_WARNING,"Object type: %d", o->type); redisLog(REDIS_WARNING,"Object encoding: %d", o->encoding); redisLog(REDIS_WARNING,"Object refcount: %d", o->refcount); - if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_RAW) { + if (o->type == REDIS_STRING && sdsEncodedObject(o)) { redisLog(REDIS_WARNING,"Object raw string len: %zu", sdslen(o->ptr)); if (sdslen(o->ptr) < 4096) { sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr)); diff --git a/src/networking.c b/src/networking.c index e2cbf9ad8..4066d69a8 100644 --- a/src/networking.c +++ b/src/networking.c @@ -184,12 +184,15 @@ void _addReplyObjectToList(redisClient *c, robj *o) { if (listLength(c->reply) == 0) { incrRefCount(o); listAddNodeTail(c->reply,o); - c->reply_bytes += zmalloc_size_sds(o->ptr); + c->reply_bytes += (o->encoding == REDIS_ENCODING_RAW) ? + zmalloc_size_sds(o->ptr) : + sdslen(o->ptr); } else { tail = listNodeValue(listLast(c->reply)); /* Append to this object when possible. */ if (tail->ptr != NULL && + tail->encoding == REDIS_ENCODING_RAW && sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES) { c->reply_bytes -= zmalloc_size_sds(tail->ptr); @@ -199,7 +202,9 @@ void _addReplyObjectToList(redisClient *c, robj *o) { } else { incrRefCount(o); listAddNodeTail(c->reply,o); - c->reply_bytes += zmalloc_size_sds(o->ptr); + c->reply_bytes += (o->encoding == REDIS_ENCODING_RAW) ? + zmalloc_size_sds(o->ptr) : + sdslen(o->ptr); } } asyncCloseClientOnOutputBufferLimitReached(c); @@ -222,7 +227,7 @@ void _addReplySdsToList(redisClient *c, sds s) { tail = listNodeValue(listLast(c->reply)); /* Append to this object when possible. */ - if (tail->ptr != NULL && + if (tail->ptr != NULL && tail->encoding == REDIS_ENCODING_RAW && sdslen(tail->ptr)+sdslen(s) <= REDIS_REPLY_CHUNK_BYTES) { c->reply_bytes -= zmalloc_size_sds(tail->ptr); @@ -247,12 +252,14 @@ void _addReplyStringToList(redisClient *c, char *s, size_t len) { robj *o = createStringObject(s,len); listAddNodeTail(c->reply,o); - c->reply_bytes += zmalloc_size_sds(o->ptr); + c->reply_bytes += (o->encoding == REDIS_ENCODING_RAW) ? + zmalloc_size_sds(o->ptr) : + sdslen(o->ptr); } else { tail = listNodeValue(listLast(c->reply)); /* Append to this object when possible. */ - if (tail->ptr != NULL && + if (tail->ptr != NULL && tail->encoding == REDIS_ENCODING_RAW && sdslen(tail->ptr)+len <= REDIS_REPLY_CHUNK_BYTES) { c->reply_bytes -= zmalloc_size_sds(tail->ptr); @@ -263,7 +270,9 @@ void _addReplyStringToList(redisClient *c, char *s, size_t len) { robj *o = createStringObject(s,len); listAddNodeTail(c->reply,o); - c->reply_bytes += zmalloc_size_sds(o->ptr); + c->reply_bytes += (o->encoding == REDIS_ENCODING_RAW) ? + zmalloc_size_sds(o->ptr) : + sdslen(o->ptr); } } asyncCloseClientOnOutputBufferLimitReached(c); @@ -284,7 +293,7 @@ void addReply(redisClient *c, robj *obj) { * If the encoding is RAW and there is room in the static buffer * we'll be able to send the object to the client without * messing with its page. */ - if (obj->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(obj)) { if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) _addReplyObjectToList(c,obj); } else if (obj->encoding == REDIS_ENCODING_INT) { @@ -396,6 +405,7 @@ void setDeferredMultiBulkLength(redisClient *c, void *node, long length) { len = listNodeValue(ln); len->ptr = sdscatprintf(sdsempty(),"*%ld\r\n",length); + len->encoding = REDIS_ENCODING_RAW; /* in case it was an EMBSTR. */ c->reply_bytes += zmalloc_size_sds(len->ptr); if (ln->next != NULL) { next = listNodeValue(ln->next); @@ -468,7 +478,7 @@ void addReplyMultiBulkLen(redisClient *c, long length) { void addReplyBulkLen(redisClient *c, robj *obj) { size_t len; - if (obj->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(obj)) { len = sdslen(obj->ptr); } else { long n = (long)obj->ptr; @@ -765,7 +775,9 @@ void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) { } else { o = listNodeValue(listFirst(c->reply)); objlen = sdslen(o->ptr); - objmem = zmalloc_size_sds(o->ptr); + objmem = (o->encoding == REDIS_ENCODING_RAW) ? + zmalloc_size_sds(o->ptr) : + sdslen(o->ptr); if (objlen == 0) { listDelNode(c->reply,listFirst(c->reply)); diff --git a/src/object.c b/src/object.c index 472d4a34b..9efb590f8 100644 --- a/src/object.c +++ b/src/object.c @@ -44,10 +44,47 @@ robj *createObject(int type, void *ptr) { return o; } -robj *createStringObject(char *ptr, size_t len) { +/* Create a string object with encoding REDIS_ENCODING_RAW, that is a plain + * string object where o->ptr points to a proper sds string. */ +robj *createRawStringObject(char *ptr, size_t len) { return createObject(REDIS_STRING,sdsnewlen(ptr,len)); } +/* Create a string object with encoding REDIS_ENCODING_EMBSTR, that is + * an object where the sds string is actually an unmodifiable string + * allocated in the same chunk as the object itself. */ +robj *createEmbeddedStringObject(char *ptr, size_t len) { + robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr)+len+1); + struct sdshdr *sh = (void*)(o+1); + + o->type = REDIS_STRING; + o->encoding = REDIS_ENCODING_EMBSTR; + o->ptr = sh+1; + o->refcount = 1; + o->lru = server.lruclock; + + sh->len = len; + sh->free = 0; + if (ptr) { + memcpy(sh->buf,ptr,len); + sh->buf[len] = '\0'; + } else { + memset(sh->buf,0,len+1); + } + return o; +} + +/* Create a string object with EMBSTR encoding if it is smaller than + * REIDS_ENCODING_EMBSTR_SIZE_LIMIT, otherwise the RAW encoding is + * used. */ +#define REDIS_ENCODING_EMBSTR_SIZE_LIMIT 32 +robj *createStringObject(char *ptr, size_t len) { + if (len <= REDIS_ENCODING_EMBSTR_SIZE_LIMIT) + return createEmbeddedStringObject(ptr,len); + else + return createRawStringObject(ptr,len); +} + robj *createStringObjectFromLongLong(long long value) { robj *o; if (value >= 0 && value < REDIS_SHARED_INTEGERS) { @@ -89,9 +126,33 @@ robj *createStringObjectFromLongDouble(long double value) { return createStringObject(buf,len); } +/* Duplicate a string object, with the guarantee that the returned object + * has the same encoding as the original one. + * + * This function also guarantees that duplicating a small integere object + * (or a string object that contains a representation of a small integer) + * will always result in a fresh object that is unshared (refcount == 1). + * + * The resulting object always has refcount set to 1. */ robj *dupStringObject(robj *o) { - redisAssertWithInfo(NULL,o,o->encoding == REDIS_ENCODING_RAW); - return createStringObject(o->ptr,sdslen(o->ptr)); + robj *d; + + redisAssert(o->type == REDIS_STRING); + + switch(o->encoding) { + case REDIS_ENCODING_RAW: + return createRawStringObject(o->ptr,sdslen(o->ptr)); + case REDIS_ENCODING_EMBSTR: + return createEmbeddedStringObject(o->ptr,sdslen(o->ptr)); + case REDIS_ENCODING_INT: + d = createObject(REDIS_STRING, NULL); + d->encoding = REDIS_ENCODING_INT; + d->ptr = o->ptr; + return d; + default: + redisPanic("Wrong encoding."); + break; + } } robj *createListObject(void) { @@ -279,7 +340,7 @@ robj *tryObjectEncoding(robj *o) { long value; sds s = o->ptr; - if (o->encoding != REDIS_ENCODING_RAW) + if (o->encoding == REDIS_ENCODING_INT) return o; /* Already encoded */ /* It's not safe to encode shared objects: shared objects can be shared @@ -291,7 +352,17 @@ robj *tryObjectEncoding(robj *o) { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); /* Check if we can represent this string as a long integer */ - if (!string2l(s,sdslen(s),&value)) return o; + if (!string2l(s,sdslen(s),&value)) { + /* Integer encoding not possible. Check if we can use EMBSTR. */ + if (sdslen(s) <= REDIS_ENCODING_EMBSTR_SIZE_LIMIT) { + robj *emb = createEmbeddedStringObject(s,sdslen(s)); + decrRefCount(o); + return emb; + } else { + /* Otherwise return the original object. */ + return o; + } + } /* Ok, this object can be encoded... * @@ -305,8 +376,8 @@ robj *tryObjectEncoding(robj *o) { incrRefCount(shared.integers[value]); return shared.integers[value]; } else { + if (o->encoding == REDIS_ENCODING_RAW) sdsfree(o->ptr); o->encoding = REDIS_ENCODING_INT; - sdsfree(o->ptr); o->ptr = (void*) value; return o; } @@ -317,7 +388,7 @@ robj *tryObjectEncoding(robj *o) { robj *getDecodedObject(robj *o) { robj *dec; - if (o->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(o)) { incrRefCount(o); return o; } @@ -350,21 +421,21 @@ int compareStringObjectsWithFlags(robj *a, robj *b, int flags) { int bothsds = 1; if (a == b) return 0; - if (a->encoding != REDIS_ENCODING_RAW) { + if (sdsEncodedObject(a)) { + astr = a->ptr; + alen = sdslen(astr); + } else { alen = ll2string(bufa,sizeof(bufa),(long) a->ptr); astr = bufa; bothsds = 0; - } else { - astr = a->ptr; - alen = sdslen(astr); } - if (b->encoding != REDIS_ENCODING_RAW) { + if (sdsEncodedObject(b)) { + bstr = b->ptr; + blen = sdslen(bstr); + } else { blen = ll2string(bufb,sizeof(bufb),(long) b->ptr); bstr = bufb; bothsds = 0; - } else { - bstr = b->ptr; - blen = sdslen(bstr); } if (flags & REDIS_COMPARE_COLL) { return strcoll(astr,bstr); @@ -393,7 +464,10 @@ int collateStringObjects(robj *a, robj *b) { * this function is faster then checking for (compareStringObject(a,b) == 0) * because it can perform some more optimization. */ int equalStringObjects(robj *a, robj *b) { - if (a->encoding != REDIS_ENCODING_RAW && b->encoding != REDIS_ENCODING_RAW){ + if (a->encoding == REDIS_ENCODING_INT && + b->encoding == REDIS_ENCODING_INT){ + /* If both strings are integer encoded just check if the stored + * long is the same. */ return a->ptr == b->ptr; } else { return compareStringObjects(a,b) == 0; @@ -402,7 +476,7 @@ int equalStringObjects(robj *a, robj *b) { size_t stringObjectLen(robj *o) { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); - if (o->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(o)) { return sdslen(o->ptr); } else { char buf[32]; @@ -419,7 +493,7 @@ int getDoubleFromObject(robj *o, double *target) { value = 0; } else { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); - if (o->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(o)) { errno = 0; value = strtod(o->ptr, &eptr); if (isspace(((char*)o->ptr)[0]) || @@ -461,7 +535,7 @@ int getLongDoubleFromObject(robj *o, long double *target) { value = 0; } else { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); - if (o->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(o)) { errno = 0; value = strtold(o->ptr, &eptr); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || @@ -499,7 +573,7 @@ int getLongLongFromObject(robj *o, long long *target) { value = 0; } else { redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); - if (o->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(o)) { errno = 0; value = strtoll(o->ptr, &eptr, 10); if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || @@ -554,6 +628,7 @@ char *strEncoding(int encoding) { case REDIS_ENCODING_ZIPLIST: return "ziplist"; case REDIS_ENCODING_INTSET: return "intset"; case REDIS_ENCODING_SKIPLIST: return "skiplist"; + case REDIS_ENCODING_EMBSTR: return "embstr"; default: return "unknown"; } } diff --git a/src/rdb.c b/src/rdb.c index c53c157c5..1c2b0ed0d 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -325,7 +325,7 @@ int rdbSaveStringObject(rio *rdb, robj *obj) { if (obj->encoding == REDIS_ENCODING_INT) { return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr); } else { - redisAssertWithInfo(NULL,obj,obj->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(NULL,obj,sdsEncodedObject(obj)); return rdbSaveRawString(rdb,obj->ptr,sdslen(obj->ptr)); } } @@ -795,7 +795,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) { /* If we are using a ziplist and the value is too big, convert * the object to a real list. */ if (o->encoding == REDIS_ENCODING_ZIPLIST && - ele->encoding == REDIS_ENCODING_RAW && + sdsEncodedObject(ele) && sdslen(ele->ptr) > server.list_max_ziplist_value) listTypeConvert(o,REDIS_ENCODING_LINKEDLIST); @@ -869,9 +869,8 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) { if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL; /* Don't care about integer-encoded strings. */ - if (ele->encoding == REDIS_ENCODING_RAW && - sdslen(ele->ptr) > maxelelen) - maxelelen = sdslen(ele->ptr); + if (sdsEncodedObject(ele) && sdslen(ele->ptr) > maxelelen) + maxelelen = sdslen(ele->ptr); znode = zslInsert(zs->zsl,score,ele); dictAdd(zs->dict,ele,&znode->score); @@ -903,10 +902,10 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) { /* Load raw strings */ field = rdbLoadStringObject(rdb); if (field == NULL) return NULL; - redisAssert(field->encoding == REDIS_ENCODING_RAW); + redisAssert(sdsEncodedObject(field)); value = rdbLoadStringObject(rdb); if (value == NULL) return NULL; - redisAssert(field->encoding == REDIS_ENCODING_RAW); + redisAssert(sdsEncodedObject(value)); /* Add pair to ziplist */ o->ptr = ziplistPush(o->ptr, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL); diff --git a/src/redis.c b/src/redis.c index 99955488e..8a833d509 100644 --- a/src/redis.c +++ b/src/redis.c @@ -465,7 +465,7 @@ int dictEncObjKeyCompare(void *privdata, const void *key1, unsigned int dictEncObjHash(const void *key) { robj *o = (robj*) key; - if (o->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(o)) { return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr)); } else { if (o->encoding == REDIS_ENCODING_INT) { diff --git a/src/redis.h b/src/redis.h index e78dc528d..57e39ad2b 100644 --- a/src/redis.h +++ b/src/redis.h @@ -174,6 +174,7 @@ #define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */ #define REDIS_ENCODING_INTSET 6 /* Encoded as intset */ #define REDIS_ENCODING_SKIPLIST 7 /* Encoded as skiplist */ +#define REDIS_ENCODING_EMBSTR 8 /* Embedded sds string encoding */ /* Defines related to the dump file format. To store 32 bits lengths for short * keys requires a lot of space, so we check the most significant 2 bits of @@ -1138,6 +1139,8 @@ void freeZsetObject(robj *o); void freeHashObject(robj *o); robj *createObject(int type, void *ptr); robj *createStringObject(char *ptr, size_t len); +robj *createRawStringObject(char *ptr, size_t len); +robj *createEmbeddedStringObject(char *ptr, size_t len); robj *dupStringObject(robj *o); int isObjectRepresentableAsLongLong(robj *o, long long *llongval); robj *tryObjectEncoding(robj *o); @@ -1164,6 +1167,7 @@ int compareStringObjects(robj *a, robj *b); int collateStringObjects(robj *a, robj *b); int equalStringObjects(robj *a, robj *b); unsigned long estimateObjectIdleTime(robj *o); +#define sdsEncodedObject(objptr) (objptr->encoding == REDIS_ENCODING_RAW || objptr->encoding == REDIS_ENCODING_EMBSTR) /* Synchronous I/O with timeout */ ssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout); diff --git a/src/slowlog.c b/src/slowlog.c index fdc18e579..ff6ccf472 100644 --- a/src/slowlog.c +++ b/src/slowlog.c @@ -63,7 +63,7 @@ slowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration) { } else { /* Trim too long strings as well... */ if (argv[j]->type == REDIS_STRING && - argv[j]->encoding == REDIS_ENCODING_RAW && + sdsEncodedObject(argv[j]) && sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING) { sds s = sdsnewlen(argv[j]->ptr, SLOWLOG_ENTRY_MAX_STRING); diff --git a/src/sort.c b/src/sort.c index a4b062645..ebdf5469c 100644 --- a/src/sort.c +++ b/src/sort.c @@ -411,7 +411,7 @@ void sortCommand(redisClient *c) { if (alpha) { if (sortby) vector[j].u.cmpobj = getDecodedObject(byval); } else { - if (byval->encoding == REDIS_ENCODING_RAW) { + if (sdsEncodedObject(byval)) { char *eptr; vector[j].u.score = strtod(byval->ptr,&eptr); diff --git a/src/t_hash.c b/src/t_hash.c index 9484e531b..3b87b92ca 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -43,7 +43,7 @@ void hashTypeTryConversion(robj *o, robj **argv, int start, int end) { if (o->encoding != REDIS_ENCODING_ZIPLIST) return; for (i = start; i <= end; i++) { - if (argv[i]->encoding == REDIS_ENCODING_RAW && + if (sdsEncodedObject(argv[i]) && sdslen(argv[i]->ptr) > server.hash_max_ziplist_value) { hashTypeConvert(o, REDIS_ENCODING_HT); diff --git a/src/t_list.c b/src/t_list.c index 0413dc69b..a8ce9b976 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -40,7 +40,7 @@ void signalListAsReady(redisClient *c, robj *key); * objects are never too long. */ void listTypeTryConversion(robj *subject, robj *value) { if (subject->encoding != REDIS_ENCODING_ZIPLIST) return; - if (value->encoding == REDIS_ENCODING_RAW && + if (sdsEncodedObject(value) && sdslen(value->ptr) > server.list_max_ziplist_value) listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST); } @@ -234,7 +234,7 @@ void listTypeInsert(listTypeEntry *entry, robj *value, int where) { int listTypeEqual(listTypeEntry *entry, robj *o) { listTypeIterator *li = entry->li; if (li->encoding == REDIS_ENCODING_ZIPLIST) { - redisAssertWithInfo(NULL,o,o->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(NULL,o,sdsEncodedObject(o)); return ziplistCompare(entry->zi,o->ptr,sdslen(o->ptr)); } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) { return equalStringObjects(o,listNodeValue(entry->ln)); diff --git a/src/t_set.c b/src/t_set.c index a522cd88a..ab65e23f3 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -495,11 +495,8 @@ void srandmemberWithCountCommand(redisClient *c) { if (encoding == REDIS_ENCODING_INTSET) { retval = dictAdd(d,createStringObjectFromLongLong(llele),NULL); - } else if (ele->encoding == REDIS_ENCODING_RAW) { + } else { retval = dictAdd(d,dupStringObject(ele),NULL); - } else if (ele->encoding == REDIS_ENCODING_INT) { - retval = dictAdd(d, - createStringObjectFromLongLong((long)ele->ptr),NULL); } redisAssert(retval == DICT_OK); } @@ -527,10 +524,8 @@ void srandmemberWithCountCommand(redisClient *c) { encoding = setTypeRandomElement(set,&ele,&llele); if (encoding == REDIS_ENCODING_INTSET) { ele = createStringObjectFromLongLong(llele); - } else if (ele->encoding == REDIS_ENCODING_RAW) { + } else { ele = dupStringObject(ele); - } else if (ele->encoding == REDIS_ENCODING_INT) { - ele = createStringObjectFromLongLong((long)ele->ptr); } /* Try to add the object to the dictionary. If it already exists * free it, otherwise increment the number of objects we have diff --git a/src/t_string.c b/src/t_string.c index cbd069d3c..3645ae7c5 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -217,7 +217,7 @@ void setrangeCommand(redisClient *c) { /* Create a copy when the object is shared or encoded. */ if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) { robj *decoded = getDecodedObject(o); - o = createStringObject(decoded->ptr, sdslen(decoded->ptr)); + o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr)); decrRefCount(decoded); dbOverwrite(c->db,c->argv[1],o); } @@ -436,7 +436,7 @@ void appendCommand(redisClient *c) { /* If the object is shared or encoded, we have to make a copy */ if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) { robj *decoded = getDecodedObject(o); - o = createStringObject(decoded->ptr, sdslen(decoded->ptr)); + o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr)); decrRefCount(decoded); dbOverwrite(c->db,c->argv[1],o); } diff --git a/src/t_zset.c b/src/t_zset.c index 8ef9c5376..291a7eacf 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -646,7 +646,7 @@ unsigned char *zzlInsertAt(unsigned char *zl, unsigned char *eptr, robj *ele, do int scorelen; size_t offset; - redisAssertWithInfo(NULL,ele,ele->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(NULL,ele,sdsEncodedObject(ele)); scorelen = d2string(scorebuf,sizeof(scorebuf),score); if (eptr == NULL) { zl = ziplistPush(zl,ele->ptr,sdslen(ele->ptr),ZIPLIST_TAIL); @@ -1363,7 +1363,7 @@ int zuiLongLongFromValue(zsetopval *val) { if (val->ele->encoding == REDIS_ENCODING_INT) { val->ell = (long)val->ele->ptr; val->flags |= OPVAL_VALID_LL; - } else if (val->ele->encoding == REDIS_ENCODING_RAW) { + } else if (sdsEncodedObject(val->ele)) { if (string2ll(val->ele->ptr,sdslen(val->ele->ptr),&val->ell)) val->flags |= OPVAL_VALID_LL; } else { @@ -1398,7 +1398,7 @@ int zuiBufferFromValue(zsetopval *val) { if (val->ele->encoding == REDIS_ENCODING_INT) { val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),(long)val->ele->ptr); val->estr = val->_buf; - } else if (val->ele->encoding == REDIS_ENCODING_RAW) { + } else if (sdsEncodedObject(val->ele)) { val->elen = sdslen(val->ele->ptr); val->estr = val->ele->ptr; } else { @@ -1624,9 +1624,10 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) { dictAdd(dstzset->dict,tmp,&znode->score); incrRefCount(tmp); /* added to dictionary */ - if (tmp->encoding == REDIS_ENCODING_RAW) + if (sdsEncodedObject(tmp)) { if (sdslen(tmp->ptr) > maxelelen) maxelelen = sdslen(tmp->ptr); + } } } } @@ -1666,9 +1667,10 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) { dictAdd(dstzset->dict,tmp,&znode->score); incrRefCount(zval.ele); /* added to dictionary */ - if (tmp->encoding == REDIS_ENCODING_RAW) + if (sdsEncodedObject(tmp)) { if (sdslen(tmp->ptr) > maxelelen) maxelelen = sdslen(tmp->ptr); + } } } } else { @@ -2146,7 +2148,8 @@ void zrankGenericCommand(redisClient *c, int reverse) { checkType(c,zobj,REDIS_ZSET)) return; llen = zsetLength(zobj); - redisAssertWithInfo(c,ele,ele->encoding == REDIS_ENCODING_RAW); + redisAssertWithInfo(c,ele,sdsEncodedObject(ele)); + if (zobj->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *zl = zobj->ptr; unsigned char *eptr, *sptr;