提交 894eba07 编写于 作者: A antirez

Introduction of a new string encoding: EMBSTR

Previously two string encodings were used for string objects:

1) REDIS_ENCODING_RAW: a string object with obj->ptr pointing to an sds
stirng.

2) REDIS_ENCODING_INT: a string object where the obj->ptr void pointer
is casted to a long.

This commit introduces a experimental new encoding called
REDIS_ENCODING_EMBSTR that implements an object represented by an sds
string that is not modifiable but allocated in the same memory chunk as
the robj structure itself.

The chunk looks like the following:

+--------------+-----------+------------+--------+----+
| robj data... | robj->ptr | sds header | string | \0 |
+--------------+-----+-----+------------+--------+----+
                     |                       ^
                     +-----------------------+

The robj->ptr points to the contiguous sds string data, so the object
can be manipulated with the same functions used to manipulate plan
string objects, however we need just on malloc and one free in order to
allocate or release this kind of objects. Moreover it has better cache
locality.

This new allocation strategy should benefit both the memory usage and
the performances. A performance gain between 60 and 70% was observed
during micro-benchmarks, however there is more work to do to evaluate
the performance impact and the memory usage behavior.
上级 b9cc90a1
......@@ -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");
......
......@@ -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);
......
......@@ -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));
......
......@@ -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);
......
......@@ -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));
......
......@@ -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));
......
......@@ -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";
}
}
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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));
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册