mirror of
https://github.com/fluencelabs/redis
synced 2025-04-12 04:06:04 +00:00
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.
This commit is contained in:
parent
b9cc90a119
commit
894eba07c8
@ -591,7 +591,7 @@ int rioWriteBulkObject(rio *r, robj *obj) {
|
|||||||
* in a child process when this function is called). */
|
* in a child process when this function is called). */
|
||||||
if (obj->encoding == REDIS_ENCODING_INT) {
|
if (obj->encoding == REDIS_ENCODING_INT) {
|
||||||
return rioWriteBulkLongLong(r,(long)obj->ptr);
|
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));
|
return rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr));
|
||||||
} else {
|
} else {
|
||||||
redisPanic("Unknown string encoding");
|
redisPanic("Unknown string encoding");
|
||||||
|
10
src/bitops.c
10
src/bitops.c
@ -133,7 +133,7 @@ void setbitCommand(redisClient *c) {
|
|||||||
/* Create a copy when the object is shared or encoded. */
|
/* Create a copy when the object is shared or encoded. */
|
||||||
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
||||||
robj *decoded = getDecodedObject(o);
|
robj *decoded = getDecodedObject(o);
|
||||||
o = createStringObject(decoded->ptr, sdslen(decoded->ptr));
|
o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));
|
||||||
decrRefCount(decoded);
|
decrRefCount(decoded);
|
||||||
dbOverwrite(c->db,c->argv[1],o);
|
dbOverwrite(c->db,c->argv[1],o);
|
||||||
}
|
}
|
||||||
@ -174,12 +174,12 @@ void getbitCommand(redisClient *c) {
|
|||||||
|
|
||||||
byte = bitoffset >> 3;
|
byte = bitoffset >> 3;
|
||||||
bit = 7 - (bitoffset & 0x7);
|
bit = 7 - (bitoffset & 0x7);
|
||||||
if (o->encoding != REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr))
|
|
||||||
bitval = llbuf[byte] & (1 << bit);
|
|
||||||
} else {
|
|
||||||
if (byte < sdslen(o->ptr))
|
if (byte < sdslen(o->ptr))
|
||||||
bitval = ((uint8_t*)o->ptr)[byte] & (1 << bit);
|
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);
|
addReply(c, bitval ? shared.cone : shared.czero);
|
||||||
|
@ -2691,7 +2691,7 @@ try_again:
|
|||||||
rioWriteBulkString(&cmd,"RESTORE-ASKING",14));
|
rioWriteBulkString(&cmd,"RESTORE-ASKING",14));
|
||||||
else
|
else
|
||||||
redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"RESTORE",7));
|
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,rioWriteBulkString(&cmd,c->argv[3]->ptr,sdslen(c->argv[3]->ptr)));
|
||||||
redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));
|
redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));
|
||||||
|
|
||||||
|
@ -550,8 +550,8 @@ void loadServerConfig(char *filename, char *options) {
|
|||||||
void configSetCommand(redisClient *c) {
|
void configSetCommand(redisClient *c) {
|
||||||
robj *o;
|
robj *o;
|
||||||
long long ll;
|
long long ll;
|
||||||
redisAssertWithInfo(c,c->argv[2],c->argv[2]->encoding == REDIS_ENCODING_RAW);
|
redisAssertWithInfo(c,c->argv[2],sdsEncodedObject(c->argv[2]));
|
||||||
redisAssertWithInfo(c,c->argv[2],c->argv[3]->encoding == REDIS_ENCODING_RAW);
|
redisAssertWithInfo(c,c->argv[3],sdsEncodedObject(c->argv[3]));
|
||||||
o = c->argv[3];
|
o = c->argv[3];
|
||||||
|
|
||||||
if (!strcasecmp(c->argv[2]->ptr,"dbfilename")) {
|
if (!strcasecmp(c->argv[2]->ptr,"dbfilename")) {
|
||||||
@ -918,7 +918,7 @@ void configGetCommand(redisClient *c) {
|
|||||||
char *pattern = o->ptr;
|
char *pattern = o->ptr;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
int matches = 0;
|
int matches = 0;
|
||||||
redisAssertWithInfo(c,o,o->encoding == REDIS_ENCODING_RAW);
|
redisAssertWithInfo(c,o,sdsEncodedObject(o));
|
||||||
|
|
||||||
/* String values */
|
/* String values */
|
||||||
config_get_string_field("dbfilename",server.rdb_filename);
|
config_get_string_field("dbfilename",server.rdb_filename);
|
||||||
|
@ -373,9 +373,7 @@ void _redisAssertPrintClientInfo(redisClient *c) {
|
|||||||
char buf[128];
|
char buf[128];
|
||||||
char *arg;
|
char *arg;
|
||||||
|
|
||||||
if (c->argv[j]->type == REDIS_STRING &&
|
if (c->argv[j]->type == REDIS_STRING && sdsEncodedObject(c->argv[j])) {
|
||||||
c->argv[j]->encoding == REDIS_ENCODING_RAW)
|
|
||||||
{
|
|
||||||
arg = (char*) c->argv[j]->ptr;
|
arg = (char*) c->argv[j]->ptr;
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf,sizeof(buf),"Object type: %d, encoding: %d",
|
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 type: %d", o->type);
|
||||||
redisLog(REDIS_WARNING,"Object encoding: %d", o->encoding);
|
redisLog(REDIS_WARNING,"Object encoding: %d", o->encoding);
|
||||||
redisLog(REDIS_WARNING,"Object refcount: %d", o->refcount);
|
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));
|
redisLog(REDIS_WARNING,"Object raw string len: %zu", sdslen(o->ptr));
|
||||||
if (sdslen(o->ptr) < 4096) {
|
if (sdslen(o->ptr) < 4096) {
|
||||||
sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));
|
sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));
|
||||||
|
@ -184,12 +184,15 @@ void _addReplyObjectToList(redisClient *c, robj *o) {
|
|||||||
if (listLength(c->reply) == 0) {
|
if (listLength(c->reply) == 0) {
|
||||||
incrRefCount(o);
|
incrRefCount(o);
|
||||||
listAddNodeTail(c->reply,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 {
|
} else {
|
||||||
tail = listNodeValue(listLast(c->reply));
|
tail = listNodeValue(listLast(c->reply));
|
||||||
|
|
||||||
/* Append to this object when possible. */
|
/* Append to this object when possible. */
|
||||||
if (tail->ptr != NULL &&
|
if (tail->ptr != NULL &&
|
||||||
|
tail->encoding == REDIS_ENCODING_RAW &&
|
||||||
sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES)
|
sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES)
|
||||||
{
|
{
|
||||||
c->reply_bytes -= zmalloc_size_sds(tail->ptr);
|
c->reply_bytes -= zmalloc_size_sds(tail->ptr);
|
||||||
@ -199,7 +202,9 @@ void _addReplyObjectToList(redisClient *c, robj *o) {
|
|||||||
} else {
|
} else {
|
||||||
incrRefCount(o);
|
incrRefCount(o);
|
||||||
listAddNodeTail(c->reply,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);
|
asyncCloseClientOnOutputBufferLimitReached(c);
|
||||||
@ -222,7 +227,7 @@ void _addReplySdsToList(redisClient *c, sds s) {
|
|||||||
tail = listNodeValue(listLast(c->reply));
|
tail = listNodeValue(listLast(c->reply));
|
||||||
|
|
||||||
/* Append to this object when possible. */
|
/* 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)
|
sdslen(tail->ptr)+sdslen(s) <= REDIS_REPLY_CHUNK_BYTES)
|
||||||
{
|
{
|
||||||
c->reply_bytes -= zmalloc_size_sds(tail->ptr);
|
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);
|
robj *o = createStringObject(s,len);
|
||||||
|
|
||||||
listAddNodeTail(c->reply,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 {
|
} else {
|
||||||
tail = listNodeValue(listLast(c->reply));
|
tail = listNodeValue(listLast(c->reply));
|
||||||
|
|
||||||
/* Append to this object when possible. */
|
/* 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)
|
sdslen(tail->ptr)+len <= REDIS_REPLY_CHUNK_BYTES)
|
||||||
{
|
{
|
||||||
c->reply_bytes -= zmalloc_size_sds(tail->ptr);
|
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);
|
robj *o = createStringObject(s,len);
|
||||||
|
|
||||||
listAddNodeTail(c->reply,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);
|
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
|
* 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
|
* we'll be able to send the object to the client without
|
||||||
* messing with its page. */
|
* messing with its page. */
|
||||||
if (obj->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(obj)) {
|
||||||
if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK)
|
if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK)
|
||||||
_addReplyObjectToList(c,obj);
|
_addReplyObjectToList(c,obj);
|
||||||
} else if (obj->encoding == REDIS_ENCODING_INT) {
|
} else if (obj->encoding == REDIS_ENCODING_INT) {
|
||||||
@ -396,6 +405,7 @@ void setDeferredMultiBulkLength(redisClient *c, void *node, long length) {
|
|||||||
|
|
||||||
len = listNodeValue(ln);
|
len = listNodeValue(ln);
|
||||||
len->ptr = sdscatprintf(sdsempty(),"*%ld\r\n",length);
|
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);
|
c->reply_bytes += zmalloc_size_sds(len->ptr);
|
||||||
if (ln->next != NULL) {
|
if (ln->next != NULL) {
|
||||||
next = listNodeValue(ln->next);
|
next = listNodeValue(ln->next);
|
||||||
@ -468,7 +478,7 @@ void addReplyMultiBulkLen(redisClient *c, long length) {
|
|||||||
void addReplyBulkLen(redisClient *c, robj *obj) {
|
void addReplyBulkLen(redisClient *c, robj *obj) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (obj->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(obj)) {
|
||||||
len = sdslen(obj->ptr);
|
len = sdslen(obj->ptr);
|
||||||
} else {
|
} else {
|
||||||
long n = (long)obj->ptr;
|
long n = (long)obj->ptr;
|
||||||
@ -765,7 +775,9 @@ void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {
|
|||||||
} else {
|
} else {
|
||||||
o = listNodeValue(listFirst(c->reply));
|
o = listNodeValue(listFirst(c->reply));
|
||||||
objlen = sdslen(o->ptr);
|
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) {
|
if (objlen == 0) {
|
||||||
listDelNode(c->reply,listFirst(c->reply));
|
listDelNode(c->reply,listFirst(c->reply));
|
||||||
|
115
src/object.c
115
src/object.c
@ -44,10 +44,47 @@ robj *createObject(int type, void *ptr) {
|
|||||||
return o;
|
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));
|
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 *createStringObjectFromLongLong(long long value) {
|
||||||
robj *o;
|
robj *o;
|
||||||
if (value >= 0 && value < REDIS_SHARED_INTEGERS) {
|
if (value >= 0 && value < REDIS_SHARED_INTEGERS) {
|
||||||
@ -89,9 +126,33 @@ robj *createStringObjectFromLongDouble(long double value) {
|
|||||||
return createStringObject(buf,len);
|
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) {
|
robj *dupStringObject(robj *o) {
|
||||||
redisAssertWithInfo(NULL,o,o->encoding == REDIS_ENCODING_RAW);
|
robj *d;
|
||||||
return createStringObject(o->ptr,sdslen(o->ptr));
|
|
||||||
|
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) {
|
robj *createListObject(void) {
|
||||||
@ -279,7 +340,7 @@ robj *tryObjectEncoding(robj *o) {
|
|||||||
long value;
|
long value;
|
||||||
sds s = o->ptr;
|
sds s = o->ptr;
|
||||||
|
|
||||||
if (o->encoding != REDIS_ENCODING_RAW)
|
if (o->encoding == REDIS_ENCODING_INT)
|
||||||
return o; /* Already encoded */
|
return o; /* Already encoded */
|
||||||
|
|
||||||
/* It's not safe to encode shared objects: shared objects can be shared
|
/* 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);
|
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
||||||
|
|
||||||
/* Check if we can represent this string as a long integer */
|
/* 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...
|
/* Ok, this object can be encoded...
|
||||||
*
|
*
|
||||||
@ -305,8 +376,8 @@ robj *tryObjectEncoding(robj *o) {
|
|||||||
incrRefCount(shared.integers[value]);
|
incrRefCount(shared.integers[value]);
|
||||||
return shared.integers[value];
|
return shared.integers[value];
|
||||||
} else {
|
} else {
|
||||||
|
if (o->encoding == REDIS_ENCODING_RAW) sdsfree(o->ptr);
|
||||||
o->encoding = REDIS_ENCODING_INT;
|
o->encoding = REDIS_ENCODING_INT;
|
||||||
sdsfree(o->ptr);
|
|
||||||
o->ptr = (void*) value;
|
o->ptr = (void*) value;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -317,7 +388,7 @@ robj *tryObjectEncoding(robj *o) {
|
|||||||
robj *getDecodedObject(robj *o) {
|
robj *getDecodedObject(robj *o) {
|
||||||
robj *dec;
|
robj *dec;
|
||||||
|
|
||||||
if (o->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
incrRefCount(o);
|
incrRefCount(o);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -350,21 +421,21 @@ int compareStringObjectsWithFlags(robj *a, robj *b, int flags) {
|
|||||||
int bothsds = 1;
|
int bothsds = 1;
|
||||||
|
|
||||||
if (a == b) return 0;
|
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);
|
alen = ll2string(bufa,sizeof(bufa),(long) a->ptr);
|
||||||
astr = bufa;
|
astr = bufa;
|
||||||
bothsds = 0;
|
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);
|
blen = ll2string(bufb,sizeof(bufb),(long) b->ptr);
|
||||||
bstr = bufb;
|
bstr = bufb;
|
||||||
bothsds = 0;
|
bothsds = 0;
|
||||||
} else {
|
|
||||||
bstr = b->ptr;
|
|
||||||
blen = sdslen(bstr);
|
|
||||||
}
|
}
|
||||||
if (flags & REDIS_COMPARE_COLL) {
|
if (flags & REDIS_COMPARE_COLL) {
|
||||||
return strcoll(astr,bstr);
|
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)
|
* this function is faster then checking for (compareStringObject(a,b) == 0)
|
||||||
* because it can perform some more optimization. */
|
* because it can perform some more optimization. */
|
||||||
int equalStringObjects(robj *a, robj *b) {
|
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;
|
return a->ptr == b->ptr;
|
||||||
} else {
|
} else {
|
||||||
return compareStringObjects(a,b) == 0;
|
return compareStringObjects(a,b) == 0;
|
||||||
@ -402,7 +476,7 @@ int equalStringObjects(robj *a, robj *b) {
|
|||||||
|
|
||||||
size_t stringObjectLen(robj *o) {
|
size_t stringObjectLen(robj *o) {
|
||||||
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
||||||
if (o->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
return sdslen(o->ptr);
|
return sdslen(o->ptr);
|
||||||
} else {
|
} else {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@ -419,7 +493,7 @@ int getDoubleFromObject(robj *o, double *target) {
|
|||||||
value = 0;
|
value = 0;
|
||||||
} else {
|
} else {
|
||||||
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
||||||
if (o->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
value = strtod(o->ptr, &eptr);
|
value = strtod(o->ptr, &eptr);
|
||||||
if (isspace(((char*)o->ptr)[0]) ||
|
if (isspace(((char*)o->ptr)[0]) ||
|
||||||
@ -461,7 +535,7 @@ int getLongDoubleFromObject(robj *o, long double *target) {
|
|||||||
value = 0;
|
value = 0;
|
||||||
} else {
|
} else {
|
||||||
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
||||||
if (o->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
value = strtold(o->ptr, &eptr);
|
value = strtold(o->ptr, &eptr);
|
||||||
if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
|
if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
|
||||||
@ -499,7 +573,7 @@ int getLongLongFromObject(robj *o, long long *target) {
|
|||||||
value = 0;
|
value = 0;
|
||||||
} else {
|
} else {
|
||||||
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
|
||||||
if (o->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
value = strtoll(o->ptr, &eptr, 10);
|
value = strtoll(o->ptr, &eptr, 10);
|
||||||
if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
|
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_ZIPLIST: return "ziplist";
|
||||||
case REDIS_ENCODING_INTSET: return "intset";
|
case REDIS_ENCODING_INTSET: return "intset";
|
||||||
case REDIS_ENCODING_SKIPLIST: return "skiplist";
|
case REDIS_ENCODING_SKIPLIST: return "skiplist";
|
||||||
|
case REDIS_ENCODING_EMBSTR: return "embstr";
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
src/rdb.c
13
src/rdb.c
@ -325,7 +325,7 @@ int rdbSaveStringObject(rio *rdb, robj *obj) {
|
|||||||
if (obj->encoding == REDIS_ENCODING_INT) {
|
if (obj->encoding == REDIS_ENCODING_INT) {
|
||||||
return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr);
|
return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr);
|
||||||
} else {
|
} else {
|
||||||
redisAssertWithInfo(NULL,obj,obj->encoding == REDIS_ENCODING_RAW);
|
redisAssertWithInfo(NULL,obj,sdsEncodedObject(obj));
|
||||||
return rdbSaveRawString(rdb,obj->ptr,sdslen(obj->ptr));
|
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
|
/* If we are using a ziplist and the value is too big, convert
|
||||||
* the object to a real list. */
|
* the object to a real list. */
|
||||||
if (o->encoding == REDIS_ENCODING_ZIPLIST &&
|
if (o->encoding == REDIS_ENCODING_ZIPLIST &&
|
||||||
ele->encoding == REDIS_ENCODING_RAW &&
|
sdsEncodedObject(ele) &&
|
||||||
sdslen(ele->ptr) > server.list_max_ziplist_value)
|
sdslen(ele->ptr) > server.list_max_ziplist_value)
|
||||||
listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);
|
listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);
|
||||||
|
|
||||||
@ -869,9 +869,8 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
|
|||||||
if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL;
|
if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL;
|
||||||
|
|
||||||
/* Don't care about integer-encoded strings. */
|
/* Don't care about integer-encoded strings. */
|
||||||
if (ele->encoding == REDIS_ENCODING_RAW &&
|
if (sdsEncodedObject(ele) && sdslen(ele->ptr) > maxelelen)
|
||||||
sdslen(ele->ptr) > maxelelen)
|
maxelelen = sdslen(ele->ptr);
|
||||||
maxelelen = sdslen(ele->ptr);
|
|
||||||
|
|
||||||
znode = zslInsert(zs->zsl,score,ele);
|
znode = zslInsert(zs->zsl,score,ele);
|
||||||
dictAdd(zs->dict,ele,&znode->score);
|
dictAdd(zs->dict,ele,&znode->score);
|
||||||
@ -903,10 +902,10 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
|
|||||||
/* Load raw strings */
|
/* Load raw strings */
|
||||||
field = rdbLoadStringObject(rdb);
|
field = rdbLoadStringObject(rdb);
|
||||||
if (field == NULL) return NULL;
|
if (field == NULL) return NULL;
|
||||||
redisAssert(field->encoding == REDIS_ENCODING_RAW);
|
redisAssert(sdsEncodedObject(field));
|
||||||
value = rdbLoadStringObject(rdb);
|
value = rdbLoadStringObject(rdb);
|
||||||
if (value == NULL) return NULL;
|
if (value == NULL) return NULL;
|
||||||
redisAssert(field->encoding == REDIS_ENCODING_RAW);
|
redisAssert(sdsEncodedObject(value));
|
||||||
|
|
||||||
/* Add pair to ziplist */
|
/* Add pair to ziplist */
|
||||||
o->ptr = ziplistPush(o->ptr, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);
|
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) {
|
unsigned int dictEncObjHash(const void *key) {
|
||||||
robj *o = (robj*) key;
|
robj *o = (robj*) key;
|
||||||
|
|
||||||
if (o->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(o)) {
|
||||||
return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));
|
return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));
|
||||||
} else {
|
} else {
|
||||||
if (o->encoding == REDIS_ENCODING_INT) {
|
if (o->encoding == REDIS_ENCODING_INT) {
|
||||||
|
@ -174,6 +174,7 @@
|
|||||||
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
|
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
|
||||||
#define REDIS_ENCODING_INTSET 6 /* Encoded as intset */
|
#define REDIS_ENCODING_INTSET 6 /* Encoded as intset */
|
||||||
#define REDIS_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
|
#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
|
/* 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
|
* 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);
|
void freeHashObject(robj *o);
|
||||||
robj *createObject(int type, void *ptr);
|
robj *createObject(int type, void *ptr);
|
||||||
robj *createStringObject(char *ptr, size_t len);
|
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);
|
robj *dupStringObject(robj *o);
|
||||||
int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
|
int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
|
||||||
robj *tryObjectEncoding(robj *o);
|
robj *tryObjectEncoding(robj *o);
|
||||||
@ -1164,6 +1167,7 @@ int compareStringObjects(robj *a, robj *b);
|
|||||||
int collateStringObjects(robj *a, robj *b);
|
int collateStringObjects(robj *a, robj *b);
|
||||||
int equalStringObjects(robj *a, robj *b);
|
int equalStringObjects(robj *a, robj *b);
|
||||||
unsigned long estimateObjectIdleTime(robj *o);
|
unsigned long estimateObjectIdleTime(robj *o);
|
||||||
|
#define sdsEncodedObject(objptr) (objptr->encoding == REDIS_ENCODING_RAW || objptr->encoding == REDIS_ENCODING_EMBSTR)
|
||||||
|
|
||||||
/* Synchronous I/O with timeout */
|
/* Synchronous I/O with timeout */
|
||||||
ssize_t syncWrite(int fd, char *ptr, ssize_t size, long long 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 {
|
} else {
|
||||||
/* Trim too long strings as well... */
|
/* Trim too long strings as well... */
|
||||||
if (argv[j]->type == REDIS_STRING &&
|
if (argv[j]->type == REDIS_STRING &&
|
||||||
argv[j]->encoding == REDIS_ENCODING_RAW &&
|
sdsEncodedObject(argv[j]) &&
|
||||||
sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING)
|
sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING)
|
||||||
{
|
{
|
||||||
sds s = sdsnewlen(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 (alpha) {
|
||||||
if (sortby) vector[j].u.cmpobj = getDecodedObject(byval);
|
if (sortby) vector[j].u.cmpobj = getDecodedObject(byval);
|
||||||
} else {
|
} else {
|
||||||
if (byval->encoding == REDIS_ENCODING_RAW) {
|
if (sdsEncodedObject(byval)) {
|
||||||
char *eptr;
|
char *eptr;
|
||||||
|
|
||||||
vector[j].u.score = strtod(byval->ptr,&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;
|
if (o->encoding != REDIS_ENCODING_ZIPLIST) return;
|
||||||
|
|
||||||
for (i = start; i <= end; i++) {
|
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)
|
sdslen(argv[i]->ptr) > server.hash_max_ziplist_value)
|
||||||
{
|
{
|
||||||
hashTypeConvert(o, REDIS_ENCODING_HT);
|
hashTypeConvert(o, REDIS_ENCODING_HT);
|
||||||
|
@ -40,7 +40,7 @@ void signalListAsReady(redisClient *c, robj *key);
|
|||||||
* objects are never too long. */
|
* objects are never too long. */
|
||||||
void listTypeTryConversion(robj *subject, robj *value) {
|
void listTypeTryConversion(robj *subject, robj *value) {
|
||||||
if (subject->encoding != REDIS_ENCODING_ZIPLIST) return;
|
if (subject->encoding != REDIS_ENCODING_ZIPLIST) return;
|
||||||
if (value->encoding == REDIS_ENCODING_RAW &&
|
if (sdsEncodedObject(value) &&
|
||||||
sdslen(value->ptr) > server.list_max_ziplist_value)
|
sdslen(value->ptr) > server.list_max_ziplist_value)
|
||||||
listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
|
listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ void listTypeInsert(listTypeEntry *entry, robj *value, int where) {
|
|||||||
int listTypeEqual(listTypeEntry *entry, robj *o) {
|
int listTypeEqual(listTypeEntry *entry, robj *o) {
|
||||||
listTypeIterator *li = entry->li;
|
listTypeIterator *li = entry->li;
|
||||||
if (li->encoding == REDIS_ENCODING_ZIPLIST) {
|
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));
|
return ziplistCompare(entry->zi,o->ptr,sdslen(o->ptr));
|
||||||
} else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {
|
} else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {
|
||||||
return equalStringObjects(o,listNodeValue(entry->ln));
|
return equalStringObjects(o,listNodeValue(entry->ln));
|
||||||
|
@ -495,11 +495,8 @@ void srandmemberWithCountCommand(redisClient *c) {
|
|||||||
|
|
||||||
if (encoding == REDIS_ENCODING_INTSET) {
|
if (encoding == REDIS_ENCODING_INTSET) {
|
||||||
retval = dictAdd(d,createStringObjectFromLongLong(llele),NULL);
|
retval = dictAdd(d,createStringObjectFromLongLong(llele),NULL);
|
||||||
} else if (ele->encoding == REDIS_ENCODING_RAW) {
|
} else {
|
||||||
retval = dictAdd(d,dupStringObject(ele),NULL);
|
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);
|
redisAssert(retval == DICT_OK);
|
||||||
}
|
}
|
||||||
@ -527,10 +524,8 @@ void srandmemberWithCountCommand(redisClient *c) {
|
|||||||
encoding = setTypeRandomElement(set,&ele,&llele);
|
encoding = setTypeRandomElement(set,&ele,&llele);
|
||||||
if (encoding == REDIS_ENCODING_INTSET) {
|
if (encoding == REDIS_ENCODING_INTSET) {
|
||||||
ele = createStringObjectFromLongLong(llele);
|
ele = createStringObjectFromLongLong(llele);
|
||||||
} else if (ele->encoding == REDIS_ENCODING_RAW) {
|
} else {
|
||||||
ele = dupStringObject(ele);
|
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
|
/* Try to add the object to the dictionary. If it already exists
|
||||||
* free it, otherwise increment the number of objects we have
|
* 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. */
|
/* Create a copy when the object is shared or encoded. */
|
||||||
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
||||||
robj *decoded = getDecodedObject(o);
|
robj *decoded = getDecodedObject(o);
|
||||||
o = createStringObject(decoded->ptr, sdslen(decoded->ptr));
|
o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));
|
||||||
decrRefCount(decoded);
|
decrRefCount(decoded);
|
||||||
dbOverwrite(c->db,c->argv[1],o);
|
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 the object is shared or encoded, we have to make a copy */
|
||||||
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
|
||||||
robj *decoded = getDecodedObject(o);
|
robj *decoded = getDecodedObject(o);
|
||||||
o = createStringObject(decoded->ptr, sdslen(decoded->ptr));
|
o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));
|
||||||
decrRefCount(decoded);
|
decrRefCount(decoded);
|
||||||
dbOverwrite(c->db,c->argv[1],o);
|
dbOverwrite(c->db,c->argv[1],o);
|
||||||
}
|
}
|
||||||
|
15
src/t_zset.c
15
src/t_zset.c
@ -646,7 +646,7 @@ unsigned char *zzlInsertAt(unsigned char *zl, unsigned char *eptr, robj *ele, do
|
|||||||
int scorelen;
|
int scorelen;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
redisAssertWithInfo(NULL,ele,ele->encoding == REDIS_ENCODING_RAW);
|
redisAssertWithInfo(NULL,ele,sdsEncodedObject(ele));
|
||||||
scorelen = d2string(scorebuf,sizeof(scorebuf),score);
|
scorelen = d2string(scorebuf,sizeof(scorebuf),score);
|
||||||
if (eptr == NULL) {
|
if (eptr == NULL) {
|
||||||
zl = ziplistPush(zl,ele->ptr,sdslen(ele->ptr),ZIPLIST_TAIL);
|
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) {
|
if (val->ele->encoding == REDIS_ENCODING_INT) {
|
||||||
val->ell = (long)val->ele->ptr;
|
val->ell = (long)val->ele->ptr;
|
||||||
val->flags |= OPVAL_VALID_LL;
|
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))
|
if (string2ll(val->ele->ptr,sdslen(val->ele->ptr),&val->ell))
|
||||||
val->flags |= OPVAL_VALID_LL;
|
val->flags |= OPVAL_VALID_LL;
|
||||||
} else {
|
} else {
|
||||||
@ -1398,7 +1398,7 @@ int zuiBufferFromValue(zsetopval *val) {
|
|||||||
if (val->ele->encoding == REDIS_ENCODING_INT) {
|
if (val->ele->encoding == REDIS_ENCODING_INT) {
|
||||||
val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),(long)val->ele->ptr);
|
val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),(long)val->ele->ptr);
|
||||||
val->estr = val->_buf;
|
val->estr = val->_buf;
|
||||||
} else if (val->ele->encoding == REDIS_ENCODING_RAW) {
|
} else if (sdsEncodedObject(val->ele)) {
|
||||||
val->elen = sdslen(val->ele->ptr);
|
val->elen = sdslen(val->ele->ptr);
|
||||||
val->estr = val->ele->ptr;
|
val->estr = val->ele->ptr;
|
||||||
} else {
|
} else {
|
||||||
@ -1624,9 +1624,10 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
|
|||||||
dictAdd(dstzset->dict,tmp,&znode->score);
|
dictAdd(dstzset->dict,tmp,&znode->score);
|
||||||
incrRefCount(tmp); /* added to dictionary */
|
incrRefCount(tmp); /* added to dictionary */
|
||||||
|
|
||||||
if (tmp->encoding == REDIS_ENCODING_RAW)
|
if (sdsEncodedObject(tmp)) {
|
||||||
if (sdslen(tmp->ptr) > maxelelen)
|
if (sdslen(tmp->ptr) > maxelelen)
|
||||||
maxelelen = sdslen(tmp->ptr);
|
maxelelen = sdslen(tmp->ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1666,9 +1667,10 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
|
|||||||
dictAdd(dstzset->dict,tmp,&znode->score);
|
dictAdd(dstzset->dict,tmp,&znode->score);
|
||||||
incrRefCount(zval.ele); /* added to dictionary */
|
incrRefCount(zval.ele); /* added to dictionary */
|
||||||
|
|
||||||
if (tmp->encoding == REDIS_ENCODING_RAW)
|
if (sdsEncodedObject(tmp)) {
|
||||||
if (sdslen(tmp->ptr) > maxelelen)
|
if (sdslen(tmp->ptr) > maxelelen)
|
||||||
maxelelen = sdslen(tmp->ptr);
|
maxelelen = sdslen(tmp->ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2146,7 +2148,8 @@ void zrankGenericCommand(redisClient *c, int reverse) {
|
|||||||
checkType(c,zobj,REDIS_ZSET)) return;
|
checkType(c,zobj,REDIS_ZSET)) return;
|
||||||
llen = zsetLength(zobj);
|
llen = zsetLength(zobj);
|
||||||
|
|
||||||
redisAssertWithInfo(c,ele,ele->encoding == REDIS_ENCODING_RAW);
|
redisAssertWithInfo(c,ele,sdsEncodedObject(ele));
|
||||||
|
|
||||||
if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
|
if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
|
||||||
unsigned char *zl = zobj->ptr;
|
unsigned char *zl = zobj->ptr;
|
||||||
unsigned char *eptr, *sptr;
|
unsigned char *eptr, *sptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user