Start of MVCC support (and more C++)

Former-commit-id: c4621a5ed2a7d8ca5034f2fbe8b71550f290ea64
This commit is contained in:
John Sully 2019-04-16 23:16:03 -04:00
parent 98c30dfac1
commit 0e10e4f6f5
36 changed files with 488 additions and 333 deletions

View File

@ -21,7 +21,7 @@ NODEPS:=clean distclean
# Default settings # Default settings
STD=-std=c99 -pedantic -DREDIS_STATIC='' STD=-std=c99 -pedantic -DREDIS_STATIC=''
CXX_STD=-std=c++14 -pedantic -fno-rtti CXX_STD=-std=c++14 -pedantic -fno-rtti -fno-exceptions
ifneq (,$(findstring clang,$(CC))) ifneq (,$(findstring clang,$(CC)))
ifneq (,$(findstring FreeBSD,$(uname_S))) ifneq (,$(findstring FreeBSD,$(uname_S)))
STD+=-Wno-c11-extensions STD+=-Wno-c11-extensions

View File

@ -161,7 +161,7 @@ int ACLListMatchSds(void *a, void *b) {
} }
/* Method to free list elements from ACL users password/ptterns lists. */ /* Method to free list elements from ACL users password/ptterns lists. */
void ACLListFreeSds(void *item) { void ACLListFreeSds(const void *item) {
sdsfree((sds)item); sdsfree((sds)item);
} }

View File

@ -52,7 +52,7 @@ typedef struct list {
listNode *head; listNode *head;
listNode *tail; listNode *tail;
void *(*dup)(void *ptr); void *(*dup)(void *ptr);
void (*free)(void *ptr); void (*free)(const void *ptr);
int (*match)(void *ptr, void *key); int (*match)(void *ptr, void *key);
unsigned long len; unsigned long len;
} list; } list;

View File

@ -37,7 +37,7 @@
/* Count number of bits set in the binary array pointed by 's' and long /* Count number of bits set in the binary array pointed by 's' and long
* 'count' bytes. The implementation of this function is required to * 'count' bytes. The implementation of this function is required to
* work with a input string length up to 512 MB. */ * work with a input string length up to 512 MB. */
size_t redisPopcount(void *s, long count) { size_t redisPopcount(const void *s, long count) {
size_t bits = 0; size_t bits = 0;
unsigned char *p = (unsigned char*)s; unsigned char *p = (unsigned char*)s;
uint32_t *p4; uint32_t *p4;
@ -98,7 +98,7 @@ size_t redisPopcount(void *s, long count) {
* no zero bit is found, it returns count*8 assuming the string is zero * no zero bit is found, it returns count*8 assuming the string is zero
* padded on the right. However if 'bit' is 1 it is possible that there is * padded on the right. However if 'bit' is 1 it is possible that there is
* not a single set bit in the bitmap. In this special case -1 is returned. */ * not a single set bit in the bitmap. In this special case -1 is returned. */
long redisBitpos(void *s, unsigned long count, int bit) { long redisBitpos(const void *s, unsigned long count, int bit) {
unsigned long *l; unsigned long *l;
unsigned char *c; unsigned char *c;
unsigned long skipval, word = 0, one; unsigned long skipval, word = 0, one;
@ -503,17 +503,17 @@ robj *lookupStringForBitCommand(client *c, size_t maxbit) {
* *
* If the source object is NULL the function is guaranteed to return NULL * If the source object is NULL the function is guaranteed to return NULL
* and set 'len' to 0. */ * and set 'len' to 0. */
unsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) { const unsigned char *getObjectReadOnlyString(robj_roptr o, long *len, char *llbuf) {
serverAssert(o->type == OBJ_STRING); serverAssert(o->type == OBJ_STRING);
unsigned char *p = NULL; const unsigned char *p = NULL;
/* Set the 'p' pointer to the string, that can be just a stack allocated /* Set the 'p' pointer to the string, that can be just a stack allocated
* array if our string was integer encoded. */ * array if our string was integer encoded. */
if (o && o->encoding == OBJ_ENCODING_INT) { if (o && o->encoding == OBJ_ENCODING_INT) {
p = (unsigned char*) llbuf; p = (const unsigned char*) llbuf;
if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)ptrFromObj(o)); if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)ptrFromObj(o));
} else if (o) { } else if (o) {
p = (unsigned char*) ptrFromObj(o); p = (const unsigned char*) ptrFromObj(o);
if (len) *len = sdslen(szFromObj(o)); if (len) *len = sdslen(szFromObj(o));
} else { } else {
if (len) *len = 0; if (len) *len = 0;
@ -562,7 +562,7 @@ void setbitCommand(client *c) {
/* GETBIT key offset */ /* GETBIT key offset */
void getbitCommand(client *c) { void getbitCommand(client *c) {
robj *o; robj_roptr o;
char llbuf[32]; char llbuf[32];
size_t bitoffset; size_t bitoffset;
size_t byte, bit; size_t byte, bit;
@ -571,7 +571,7 @@ void getbitCommand(client *c) {
if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK) if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)
return; return;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_STRING)) return; checkType(c,o,OBJ_STRING)) return;
byte = bitoffset >> 3; byte = bitoffset >> 3;
@ -590,9 +590,10 @@ void getbitCommand(client *c) {
/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */ /* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */
void bitopCommand(client *c) { void bitopCommand(client *c) {
char *opname = szFromObj(c->argv[1]); char *opname = szFromObj(c->argv[1]);
robj *o, *targetkey = c->argv[2]; robj *targetkey = c->argv[2];
robj_roptr o;
unsigned long op, j, numkeys; unsigned long op, j, numkeys;
robj **objects; /* Array of source objects. */ robj_roptr *objects; /* Array of source objects. */
unsigned char **src; /* Array of source strings pointers. */ unsigned char **src; /* Array of source strings pointers. */
unsigned long *len, maxlen = 0; /* Array of length of src strings, unsigned long *len, maxlen = 0; /* Array of length of src strings,
and max len. */ and max len. */
@ -623,12 +624,12 @@ void bitopCommand(client *c) {
numkeys = c->argc - 3; numkeys = c->argc - 3;
src = (unsigned char**)zmalloc(sizeof(unsigned char*) * numkeys, MALLOC_LOCAL); src = (unsigned char**)zmalloc(sizeof(unsigned char*) * numkeys, MALLOC_LOCAL);
len = (unsigned long*)zmalloc(sizeof(long) * numkeys, MALLOC_LOCAL); len = (unsigned long*)zmalloc(sizeof(long) * numkeys, MALLOC_LOCAL);
objects = (robj**)zmalloc(sizeof(robj*) * numkeys, MALLOC_LOCAL); objects = (robj_roptr*)zmalloc(sizeof(robj_roptr) * numkeys, MALLOC_LOCAL);
for (j = 0; j < numkeys; j++) { for (j = 0; j < numkeys; j++) {
o = lookupKeyRead(c->db,c->argv[j+3]); o = lookupKeyRead(c->db,c->argv[j+3]);
/* Handle non-existing keys as empty strings. */ /* Handle non-existing keys as empty strings. */
if (o == NULL) { if (o == nullptr) {
objects[j] = NULL; objects[j] = nullptr;
src[j] = NULL; src[j] = NULL;
len[j] = 0; len[j] = 0;
minlen = 0; minlen = 0;
@ -753,7 +754,7 @@ void bitopCommand(client *c) {
/* Store the computed value into the target key */ /* Store the computed value into the target key */
if (maxlen) { if (maxlen) {
o = createObject(OBJ_STRING,res); robj *o = createObject(OBJ_STRING,res);
setKey(c->db,targetkey,o); setKey(c->db,targetkey,o);
notifyKeyspaceEvent(NOTIFY_STRING,"set",targetkey,c->db->id); notifyKeyspaceEvent(NOTIFY_STRING,"set",targetkey,c->db->id);
decrRefCount(o); decrRefCount(o);
@ -767,13 +768,13 @@ void bitopCommand(client *c) {
/* BITCOUNT key [start end] */ /* BITCOUNT key [start end] */
void bitcountCommand(client *c) { void bitcountCommand(client *c) {
robj *o; robj_roptr o;
long start, end, strlen; long start, end, strlen;
unsigned char *p; const unsigned char *p;
char llbuf[LONG_STR_SIZE]; char llbuf[LONG_STR_SIZE];
/* Lookup, check for type, and return 0 for non existing keys. */ /* Lookup, check for type, and return 0 for non existing keys. */
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_STRING)) return; checkType(c,o,OBJ_STRING)) return;
p = getObjectReadOnlyString(o,&strlen,llbuf); p = getObjectReadOnlyString(o,&strlen,llbuf);
@ -816,9 +817,9 @@ void bitcountCommand(client *c) {
/* BITPOS key bit [start [end]] */ /* BITPOS key bit [start [end]] */
void bitposCommand(client *c) { void bitposCommand(client *c) {
robj *o; robj_roptr o;
long bit, start, end, strlen; long bit, start, end, strlen;
unsigned char *p; const unsigned char *p;
char llbuf[LONG_STR_SIZE]; char llbuf[LONG_STR_SIZE];
int end_given = 0; int end_given = 0;
@ -834,7 +835,7 @@ void bitposCommand(client *c) {
/* If the key does not exist, from our point of view it is an infinite /* If the key does not exist, from our point of view it is an infinite
* array of 0 bits. If the user is looking for the fist clear bit return 0, * array of 0 bits. If the user is looking for the fist clear bit return 0,
* If the user is looking for the first set bit, return -1. */ * If the user is looking for the first set bit, return -1. */
if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) { if ((o = lookupKeyRead(c->db,c->argv[1])) == nullptr) {
addReplyLongLong(c, bit ? -1 : 0); addReplyLongLong(c, bit ? -1 : 0);
return; return;
} }
@ -912,7 +913,7 @@ struct bitfieldOp {
}; };
void bitfieldCommand(client *c) { void bitfieldCommand(client *c) {
robj *o; robj_roptr o;
size_t bitoffset; size_t bitoffset;
int j, numops = 0, changes = 0; int j, numops = 0, changes = 0;
struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */ struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */
@ -994,12 +995,12 @@ void bitfieldCommand(client *c) {
/* Lookup for read is ok if key doesn't exit, but errors /* Lookup for read is ok if key doesn't exit, but errors
* if it's not a string. */ * if it's not a string. */
o = lookupKeyRead(c->db,c->argv[1]); o = lookupKeyRead(c->db,c->argv[1]);
if (o != NULL && checkType(c,o,OBJ_STRING)) return; if (o != nullptr && checkType(c,o,OBJ_STRING)) return;
} else { } else {
/* Lookup by making room up to the farest bit reached by /* Lookup by making room up to the farest bit reached by
* this operation. */ * this operation. */
if ((o = lookupStringForBitCommand(c, if ((o = lookupStringForBitCommand(c,
highest_write_offset)) == NULL) return; highest_write_offset)) == nullptr) return;
} }
addReplyArrayLen(c,numops); addReplyArrayLen(c,numops);
@ -1084,10 +1085,10 @@ void bitfieldCommand(client *c) {
/* GET */ /* GET */
unsigned char buf[9]; unsigned char buf[9];
long strlen = 0; long strlen = 0;
unsigned char *src = NULL; const unsigned char *src = NULL;
char llbuf[LONG_STR_SIZE]; char llbuf[LONG_STR_SIZE];
if (o != NULL) if (o != nullptr)
src = getObjectReadOnlyString(o,&strlen,llbuf); src = getObjectReadOnlyString(o,&strlen,llbuf);
/* For GET we use a trick: before executing the operation /* For GET we use a trick: before executing the operation

View File

@ -4797,7 +4797,7 @@ NULL
/* Generates a DUMP-format representation of the object 'o', adding it to the /* Generates a DUMP-format representation of the object 'o', adding it to the
* io stream pointed by 'rio'. This function can't fail. */ * io stream pointed by 'rio'. This function can't fail. */
void createDumpPayload(rio *payload, robj *o, robj *key) { void createDumpPayload(rio *payload, robj_roptr o, robj *key) {
unsigned char buf[2]; unsigned char buf[2];
uint64_t crc; uint64_t crc;
@ -4853,11 +4853,11 @@ int verifyDumpPayload(unsigned char *p, size_t len) {
* DUMP is actually not used by Redis Cluster but it is the obvious * DUMP is actually not used by Redis Cluster but it is the obvious
* complement of RESTORE and can be useful for different applications. */ * complement of RESTORE and can be useful for different applications. */
void dumpCommand(client *c) { void dumpCommand(client *c) {
robj *o, *dumpobj; robj_roptr o, dumpobj;
rio payload; rio payload;
/* Check if the key is here. */ /* Check if the key is here. */
if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) { if ((o = lookupKeyRead(c->db,c->argv[1])) == nullptr) {
addReplyNull(c); addReplyNull(c);
return; return;
} }
@ -5086,7 +5086,7 @@ void migrateCommand(client *c) {
char *password = NULL; char *password = NULL;
long timeout; long timeout;
long dbid; long dbid;
robj **ov = NULL; /* Objects to migrate. */ robj_roptr *ov = NULL; /* Objects to migrate. */
robj **kv = NULL; /* Key names. */ robj **kv = NULL; /* Key names. */
robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */ robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */
rio cmd, payload; rio cmd, payload;
@ -5141,12 +5141,12 @@ void migrateCommand(client *c) {
* the caller there was nothing to migrate. We don't return an error in * the caller there was nothing to migrate. We don't return an error in
* this case, since often this is due to a normal condition like the key * this case, since often this is due to a normal condition like the key
* expiring in the meantime. */ * expiring in the meantime. */
ov = (robj**)zrealloc(ov,sizeof(robj*)*num_keys, MALLOC_LOCAL); ov = (robj_roptr*)zrealloc(ov,sizeof(robj_roptr)*num_keys, MALLOC_LOCAL);
kv = (robj**)zrealloc(kv,sizeof(robj*)*num_keys, MALLOC_LOCAL); kv = (robj**)zrealloc(kv,sizeof(robj*)*num_keys, MALLOC_LOCAL);
int oi = 0; int oi = 0;
for (j = 0; j < num_keys; j++) { for (j = 0; j < num_keys; j++) {
if ((ov[oi] = lookupKeyRead(c->db,c->argv[first_key+j])) != NULL) { if ((ov[oi] = lookupKeyRead(c->db,c->argv[first_key+j])) != nullptr) {
kv[oi] = c->argv[first_key+j]; kv[oi] = c->argv[first_key+j];
oi++; oi++;
} }
@ -5583,7 +5583,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
/* Migarting / Improrting slot? Count keys we don't have. */ /* Migarting / Improrting slot? Count keys we don't have. */
if ((migrating_slot || importing_slot) && if ((migrating_slot || importing_slot) &&
lookupKeyRead(&server.db[0],thiskey) == NULL) lookupKeyRead(&server.db[0],thiskey) == nullptr)
{ {
missing_keys++; missing_keys++;
} }

View File

@ -52,7 +52,7 @@ void updateLFU(robj *val) {
/* Low level key lookup API, not actually called directly from commands /* Low level key lookup API, not actually called directly from commands
* implementations that should instead rely on lookupKeyRead(), * implementations that should instead rely on lookupKeyRead(),
* lookupKeyWrite() and lookupKeyReadWithFlags(). */ * lookupKeyWrite() and lookupKeyReadWithFlags(). */
robj *lookupKey(redisDb *db, robj *key, int flags) { static robj *lookupKey(redisDb *db, robj *key, int flags) {
dictEntry *de = dictFind(db->pdict,ptrFromObj(key)); dictEntry *de = dictFind(db->pdict,ptrFromObj(key));
if (de) { if (de) {
robj *val = (robj*)dictGetVal(de); robj *val = (robj*)dictGetVal(de);
@ -98,7 +98,7 @@ robj *lookupKey(redisDb *db, robj *key, int flags) {
* for read operations. Even if the key expiry is master-driven, we can * for read operations. Even if the key expiry is master-driven, we can
* correctly report a key is expired on slaves even if the master is lagging * correctly report a key is expired on slaves even if the master is lagging
* expiring our key via DELs in the replication link. */ * expiring our key via DELs in the replication link. */
robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) { robj_roptr lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
robj *val; robj *val;
serverAssert(GlobalLocksAcquired()); serverAssert(GlobalLocksAcquired());
@ -146,7 +146,7 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
/* Like lookupKeyReadWithFlags(), but does not use any flag, which is the /* Like lookupKeyReadWithFlags(), but does not use any flag, which is the
* common case. */ * common case. */
robj *lookupKeyRead(redisDb *db, robj *key) { robj_roptr lookupKeyRead(redisDb *db, robj *key) {
return lookupKeyReadWithFlags(db,key,LOOKUP_NONE); return lookupKeyReadWithFlags(db,key,LOOKUP_NONE);
} }
@ -160,8 +160,8 @@ robj *lookupKeyWrite(redisDb *db, robj *key) {
return lookupKey(db,key,LOOKUP_NONE); return lookupKey(db,key,LOOKUP_NONE);
} }
robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) { robj_roptr lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
robj *o = lookupKeyRead(c->db, key); robj_roptr o = lookupKeyRead(c->db, key);
if (!o) addReply(c,reply); if (!o) addReply(c,reply);
return o; return o;
} }
@ -175,6 +175,9 @@ robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply) {
int dbAddCore(redisDb *db, robj *key, robj *val) { int dbAddCore(redisDb *db, robj *key, robj *val) {
sds copy = sdsdup(szFromObj(key)); sds copy = sdsdup(szFromObj(key));
int retval = dictAdd(db->pdict, copy, val); int retval = dictAdd(db->pdict, copy, val);
#ifdef ENABLE_MVCC
val->mvcc_tstamp = key->mvcc_tstamp = getMvccTstamp();
#endif
if (retval == DICT_OK) if (retval == DICT_OK)
{ {
@ -229,6 +232,9 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) {
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
val->lru = old->lru; val->lru = old->lru;
} }
#ifdef ENABLE_MVCC
val->mvcc_tstamp = getMvccTstamp();
#endif
dictSetVal(db->pdict, de, val); dictSetVal(db->pdict, de, val);
if (server.lazyfree_lazy_server_del) { if (server.lazyfree_lazy_server_del) {
@ -652,7 +658,7 @@ int parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor) {
* *
* In the case of a Hash object the function returns both the field and value * In the case of a Hash object the function returns both the field and value
* of every element on the Hash. */ * of every element on the Hash. */
void scanGenericCommand(client *c, robj *o, unsigned long cursor) { void scanGenericCommand(client *c, robj_roptr o, unsigned long cursor) {
int i, j; int i, j;
list *keys = listCreate(); list *keys = listCreate();
listNode *node, *nextnode; listNode *node, *nextnode;
@ -663,11 +669,11 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
/* Object must be NULL (to iterate keys names), or the type of the object /* Object must be NULL (to iterate keys names), or the type of the object
* must be Set, Sorted Set, or Hash. */ * must be Set, Sorted Set, or Hash. */
serverAssert(o == NULL || o->type == OBJ_SET || o->type == OBJ_HASH || serverAssert(o == nullptr || o->type == OBJ_SET || o->type == OBJ_HASH ||
o->type == OBJ_ZSET); o->type == OBJ_ZSET);
/* Set i to the first option argument. The previous one is the cursor. */ /* Set i to the first option argument. The previous one is the cursor. */
i = (o == NULL) ? 2 : 3; /* Skip the key argument if needed. */ i = (o == nullptr) ? 2 : 3; /* Skip the key argument if needed. */
/* Step 1: Parse options. */ /* Step 1: Parse options. */
while (i < c->argc) { while (i < c->argc) {
@ -710,7 +716,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
/* Handle the case of a hash table. */ /* Handle the case of a hash table. */
ht = NULL; ht = NULL;
if (o == NULL) { if (o == nullptr) {
ht = c->db->pdict; ht = c->db->pdict;
} else if (o->type == OBJ_SET && o->encoding == OBJ_ENCODING_HT) { } else if (o->type == OBJ_SET && o->encoding == OBJ_ENCODING_HT) {
ht = (dict*)ptrFromObj(o); ht = (dict*)ptrFromObj(o);
@ -735,7 +741,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
* add new elements, and the object containing the dictionary so that * add new elements, and the object containing the dictionary so that
* it is possible to fetch more data in a type-dependent way. */ * it is possible to fetch more data in a type-dependent way. */
privdata[0] = keys; privdata[0] = keys;
privdata[1] = o; privdata[1] = o.unsafe_robjcast();
do { do {
cursor = dictScan(ht, cursor, scanCallback, NULL, privdata); cursor = dictScan(ht, cursor, scanCallback, NULL, privdata);
} while (cursor && } while (cursor &&
@ -789,7 +795,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
} }
/* Filter element if it is an expired key. */ /* Filter element if it is an expired key. */
if (!filter && o == NULL && expireIfNeeded(c->db, kobj)) filter = 1; if (!filter && o == nullptr && expireIfNeeded(c->db, kobj)) filter = 1;
/* Remove the element and its associted value if needed. */ /* Remove the element and its associted value if needed. */
if (filter) { if (filter) {
@ -833,7 +839,7 @@ cleanup:
void scanCommand(client *c) { void scanCommand(client *c) {
unsigned long cursor; unsigned long cursor;
if (parseScanCursorOrReply(c,c->argv[1],&cursor) == C_ERR) return; if (parseScanCursorOrReply(c,c->argv[1],&cursor) == C_ERR) return;
scanGenericCommand(c,NULL,cursor); scanGenericCommand(c,nullptr,cursor);
} }
void dbsizeCommand(client *c) { void dbsizeCommand(client *c) {
@ -845,11 +851,10 @@ void lastsaveCommand(client *c) {
} }
void typeCommand(client *c) { void typeCommand(client *c) {
robj *o;
const char *type; const char *type;
o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH); robj_roptr o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH);
if (o == NULL) { if (o == nullptr) {
type = "none"; type = "none";
} else { } else {
switch(o->type) { switch(o->type) {
@ -1121,7 +1126,7 @@ void setExpire(client *c, redisDb *db, robj *key, long long when) {
/* Return the expire time of the specified key, or -1 if no expire /* Return the expire time of the specified key, or -1 if no expire
* is associated with this key (i.e. the key is non volatile) */ * is associated with this key (i.e. the key is non volatile) */
long long getExpire(redisDb *db, robj *key) { long long getExpire(redisDb *db, robj_roptr key) {
dictEntry *de; dictEntry *de;
/* No expire? return ASAP */ /* No expire? return ASAP */

View File

@ -45,6 +45,7 @@ typedef ucontext_t sigcontext_t;
#include <fcntl.h> #include <fcntl.h>
#include "bio.h" #include "bio.h"
#include <unistd.h> #include <unistd.h>
#include <cxxabi.h>
#endif /* HAVE_BACKTRACE */ #endif /* HAVE_BACKTRACE */
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@ -61,7 +62,7 @@ typedef ucontext_t sigcontext_t;
* "add" digests relative to unordered elements. * "add" digests relative to unordered elements.
* *
* So digest(a,b,c,d) will be the same of digest(b,a,c,d) */ * So digest(a,b,c,d) will be the same of digest(b,a,c,d) */
extern "C" void xorDigest(unsigned char *digest, const void *ptr, size_t len) { void xorDigest(unsigned char *digest, const void *ptr, size_t len) {
SHA1_CTX ctx; SHA1_CTX ctx;
unsigned char hash[20]; unsigned char hash[20];
const unsigned char *s = (const unsigned char*)ptr; const unsigned char *s = (const unsigned char*)ptr;
@ -95,9 +96,9 @@ void xorStringObjectDigest(unsigned char *digest, robj *o) {
* Also note that mixdigest("foo") followed by mixdigest("bar") * Also note that mixdigest("foo") followed by mixdigest("bar")
* will lead to a different digest compared to "fo", "obar". * will lead to a different digest compared to "fo", "obar".
*/ */
void mixDigest(unsigned char *digest, void *ptr, size_t len) { void mixDigest(unsigned char *digest, const void *ptr, size_t len) {
SHA1_CTX ctx; SHA1_CTX ctx;
char *s = (char*)ptr; const char *s = (const char*)ptr;
xorDigest(digest,s,len); xorDigest(digest,s,len);
SHA1Init(&ctx); SHA1Init(&ctx);
@ -105,7 +106,7 @@ void mixDigest(unsigned char *digest, void *ptr, size_t len) {
SHA1Final(digest,&ctx); SHA1Final(digest,&ctx);
} }
void mixStringObjectDigest(unsigned char *digest, robj *o) { void mixStringObjectDigest(unsigned char *digest, robj_roptr o) {
o = getDecodedObject(o); o = getDecodedObject(o);
mixDigest(digest,ptrFromObj(o),sdslen(szFromObj(o))); mixDigest(digest,ptrFromObj(o),sdslen(szFromObj(o)));
decrRefCount(o); decrRefCount(o);
@ -119,7 +120,7 @@ void mixStringObjectDigest(unsigned char *digest, robj *o) {
* Note that this function does not reset the initial 'digest' passed, it * Note that this function does not reset the initial 'digest' passed, it
* will continue mixing this object digest to anything that was already * will continue mixing this object digest to anything that was already
* present. */ * present. */
void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o) { void xorObjectDigest(redisDb *db, robj_roptr keyobj, unsigned char *digest, robj_roptr o) {
uint32_t aux = htonl(o->type); uint32_t aux = htonl(o->type);
mixDigest(digest,&aux,sizeof(aux)); mixDigest(digest,&aux,sizeof(aux));
long long expiretime = getExpire(db,keyobj); long long expiretime = getExpire(db,keyobj);
@ -523,7 +524,7 @@ NULL
for (int j = 2; j < c->argc; j++) { for (int j = 2; j < c->argc; j++) {
unsigned char digest[20]; unsigned char digest[20];
memset(digest,0,20); /* Start with a clean result */ memset(digest,0,20); /* Start with a clean result */
robj *o = lookupKeyReadWithFlags(c->db,c->argv[j],LOOKUP_NOTOUCH); robj_roptr o = lookupKeyReadWithFlags(c->db,c->argv[j],LOOKUP_NOTOUCH);
if (o) xorObjectDigest(c->db,c->argv[j],digest,o); if (o) xorObjectDigest(c->db,c->argv[j],digest,o);
sds d = sdsempty(); sds d = sdsempty();
@ -723,7 +724,7 @@ void _serverAssertPrintClientInfo(const client *c) {
} }
} }
void serverLogObjectDebugInfo(const robj *o) { void serverLogObjectDebugInfo(robj_roptr o) {
serverLog(LL_WARNING,"Object type: %d", o->type); serverLog(LL_WARNING,"Object type: %d", o->type);
serverLog(LL_WARNING,"Object encoding: %d", o->encoding); serverLog(LL_WARNING,"Object encoding: %d", o->encoding);
serverLog(LL_WARNING,"Object refcount: %d", o->refcount); serverLog(LL_WARNING,"Object refcount: %d", o->refcount);
@ -747,13 +748,13 @@ void serverLogObjectDebugInfo(const robj *o) {
} }
} }
void _serverAssertPrintObject(const robj *o) { void _serverAssertPrintObject(robj_roptr o) {
bugReportStart(); bugReportStart();
serverLog(LL_WARNING,"=== ASSERTION FAILED OBJECT CONTEXT ==="); serverLog(LL_WARNING,"=== ASSERTION FAILED OBJECT CONTEXT ===");
serverLogObjectDebugInfo(o); serverLogObjectDebugInfo(o);
} }
void _serverAssertWithInfo(const client *c, const robj *o, const char *estr, const char *file, int line) { void _serverAssertWithInfo(const client *c, robj_roptr o, const char *estr, const char *file, int line) {
if (c) _serverAssertPrintClientInfo(c); if (c) _serverAssertPrintClientInfo(c);
if (o) _serverAssertPrintObject(o); if (o) _serverAssertPrintObject(o);
_serverAssert(estr,file,line); _serverAssert(estr,file,line);
@ -1138,6 +1139,61 @@ void closeDirectLogFiledes(int fd) {
if (!log_to_stdout) close(fd); if (!log_to_stdout) close(fd);
} }
void safe_write(int fd, const void *pv, ssize_t cb)
{
ssize_t offset = 0;
do
{
ssize_t cbWrite = write(fd, reinterpret_cast<const char*>(pv)+offset, cb-offset);
if (cbWrite <= 0)
return;
offset += cbWrite;
} while (offset < cb);
}
void backtrace_symbols_demangle_fd(void **trace, size_t csym, int fd)
{
char **syms = backtrace_symbols(trace, csym);
char symbuf[1024];
for (size_t itrace = 0; itrace < csym; ++itrace)
{
int status = 0;
// First find the symbol (preceded by a '(')
char *pchSymStart = syms[itrace];
while (*pchSymStart != '(' && *pchSymStart != '\0')
++pchSymStart;
if (*pchSymStart != '\0')
++pchSymStart; // skip the '('
char *pchSymEnd = pchSymStart;
while (*pchSymEnd != '+' && *pchSymEnd != '\0')
++pchSymEnd;
if ((pchSymEnd - pchSymStart) < 1023)
{
memcpy(symbuf, pchSymStart, pchSymEnd - pchSymStart);
symbuf[pchSymEnd - pchSymStart] = '\0';
char *sz = abi::__cxa_demangle(symbuf, nullptr, nullptr, &status);
if (status == 0)
{
safe_write(fd, syms[itrace], pchSymStart - syms[itrace]);
safe_write(fd, sz, strlen(sz));
safe_write(fd, pchSymEnd, (syms[itrace] + strlen(syms[itrace])-pchSymEnd));
}
else
{
safe_write(fd, syms[itrace], strlen(syms[itrace]));
}
free(sz);
}
else {
safe_write(fd, syms[itrace], strlen(syms[itrace]));
}
safe_write(fd, "\n", 1);
}
free(syms);
}
/* Logs the stack trace using the backtrace() call. This function is designed /* Logs the stack trace using the backtrace() call. This function is designed
* to be called from signal handlers safely. */ * to be called from signal handlers safely. */
void logStackTrace(ucontext_t *uc) { void logStackTrace(ucontext_t *uc) {
@ -1154,12 +1210,12 @@ void logStackTrace(ucontext_t *uc) {
const char *msg2 = "\nBacktrace:\n"; const char *msg2 = "\nBacktrace:\n";
if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */}; if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */};
trace[0] = getMcontextEip(uc); trace[0] = getMcontextEip(uc);
backtrace_symbols_fd(trace, 1, fd); backtrace_symbols_demangle_fd(trace, 1, fd);
if (write(fd,msg2,strlen(msg2)) == -1) {/* Avoid warning. */}; if (write(fd,msg2,strlen(msg2)) == -1) {/* Avoid warning. */};
} }
/* Write symbols to log file */ /* Write symbols to log file */
backtrace_symbols_fd(trace+1, trace_size, fd); backtrace_symbols_demangle_fd(trace+1, trace_size, fd);
/* Cleanup */ /* Cleanup */
closeDirectLogFiledes(fd); closeDirectLogFiledes(fd);

View File

@ -474,7 +474,7 @@ void ttlGenericCommand(client *c, int output_ms) {
long long expire, ttl = -1; long long expire, ttl = -1;
/* If the key does not exist at all, return -2 */ /* If the key does not exist at all, return -2 */
if (lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH) == NULL) { if (lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH) == nullptr) {
addReplyLongLong(c,-2); addReplyLongLong(c,-2);
return; return;
} }
@ -520,7 +520,7 @@ void persistCommand(client *c) {
void touchCommand(client *c) { void touchCommand(client *c) {
int touched = 0; int touched = 0;
for (int j = 1; j < c->argc; j++) for (int j = 1; j < c->argc; j++)
if (lookupKeyRead(c->db,c->argv[j]) != NULL) touched++; if (lookupKeyRead(c->db,c->argv[j]) != nullptr) touched++;
addReplyLongLong(c,touched); addReplyLongLong(c,touched);
} }

View File

@ -110,7 +110,7 @@ int extractLongLatOrReply(client *c, robj **argv, double *xy) {
/* Input Argument Helper */ /* Input Argument Helper */
/* Decode lat/long from a zset member's score. /* Decode lat/long from a zset member's score.
* Returns C_OK on successful decoding, otherwise C_ERR is returned. */ * Returns C_OK on successful decoding, otherwise C_ERR is returned. */
int longLatFromMember(robj *zobj, robj *member, double *xy) { int longLatFromMember(robj_roptr zobj, robj *member, double *xy) {
double score = 0; double score = 0;
if (zsetScore(zobj, szFromObj(member), &score) == C_ERR) return C_ERR; if (zsetScore(zobj, szFromObj(member), &score) == C_ERR) return C_ERR;
@ -222,7 +222,7 @@ int geoAppendIfWithinRadius(geoArray *ga, double lon, double lat, double radius,
* using multiple queries to the sorted set, that we later need to sort * using multiple queries to the sorted set, that we later need to sort
* via qsort. Similarly we need to be able to reject points outside the search * via qsort. Similarly we need to be able to reject points outside the search
* radius area ASAP in order to allocate and process more points than needed. */ * radius area ASAP in order to allocate and process more points than needed. */
int geoGetPointsInRange(robj *zobj, double min, double max, double lon, double lat, double radius, geoArray *ga) { int geoGetPointsInRange(robj_roptr zobj, double min, double max, double lon, double lat, double radius, geoArray *ga) {
/* minex 0 = include min in range; maxex 1 = exclude max in range */ /* minex 0 = include min in range; maxex 1 = exclude max in range */
/* That's: min <= val < max */ /* That's: min <= val < max */
zrangespec range = { min, max, 0, 1 }; zrangespec range = { min, max, 0, 1 };
@ -315,7 +315,7 @@ void scoresOfGeoHashBox(GeoHashBits hash, GeoHashFix52Bits *min, GeoHashFix52Bit
/* Obtain all members between the min/max of this geohash bounding box. /* Obtain all members between the min/max of this geohash bounding box.
* Populate a geoArray of GeoPoints by calling geoGetPointsInRange(). * Populate a geoArray of GeoPoints by calling geoGetPointsInRange().
* Return the number of points added to the array. */ * Return the number of points added to the array. */
int membersOfGeoHashBox(robj *zobj, GeoHashBits hash, geoArray *ga, double lon, double lat, double radius) { int membersOfGeoHashBox(robj_roptr zobj, GeoHashBits hash, geoArray *ga, double lon, double lat, double radius) {
GeoHashFix52Bits min, max; GeoHashFix52Bits min, max;
scoresOfGeoHashBox(hash,&min,&max); scoresOfGeoHashBox(hash,&min,&max);
@ -323,7 +323,7 @@ int membersOfGeoHashBox(robj *zobj, GeoHashBits hash, geoArray *ga, double lon,
} }
/* Search all eight neighbors + self geohash box */ /* Search all eight neighbors + self geohash box */
int membersOfAllNeighbors(robj *zobj, GeoHashRadius n, double lon, double lat, double radius, geoArray *ga) { int membersOfAllNeighbors(robj_roptr zobj, GeoHashRadius n, double lon, double lat, double radius, geoArray *ga) {
GeoHashBits neighbors[9]; GeoHashBits neighbors[9];
unsigned int i, count = 0, last_processed = 0; unsigned int i, count = 0, last_processed = 0;
int debugmsg = 0; int debugmsg = 0;
@ -465,8 +465,8 @@ void georadiusGeneric(client *c, int flags) {
int storedist = 0; /* 0 for STORE, 1 for STOREDIST. */ int storedist = 0; /* 0 for STORE, 1 for STOREDIST. */
/* Look up the requested zset */ /* Look up the requested zset */
robj *zobj = NULL; robj_roptr zobj;
if ((zobj = lookupKeyReadOrReply(c, key, shared.null[c->resp])) == NULL || if ((zobj = lookupKeyReadOrReply(c, key, shared.null[c->resp])) == nullptr ||
checkType(c, zobj, OBJ_ZSET)) { checkType(c, zobj, OBJ_ZSET)) {
return; return;
} }
@ -701,7 +701,7 @@ void geohashCommand(client *c) {
int j; int j;
/* Look up the requested zset */ /* Look up the requested zset */
robj *zobj = lookupKeyRead(c->db, c->argv[1]); robj_roptr zobj = lookupKeyRead(c->db, c->argv[1]);
if (zobj && checkType(c, zobj, OBJ_ZSET)) return; if (zobj && checkType(c, zobj, OBJ_ZSET)) return;
/* Geohash elements one after the other, using a null bulk reply for /* Geohash elements one after the other, using a null bulk reply for
@ -754,7 +754,7 @@ void geoposCommand(client *c) {
int j; int j;
/* Look up the requested zset */ /* Look up the requested zset */
robj *zobj = lookupKeyRead(c->db, c->argv[1]); robj_roptr zobj = lookupKeyRead(c->db, c->argv[1]);
if (zobj && checkType(c, zobj, OBJ_ZSET)) return; if (zobj && checkType(c, zobj, OBJ_ZSET)) return;
/* Report elements one after the other, using a null bulk reply for /* Report elements one after the other, using a null bulk reply for
@ -796,9 +796,9 @@ void geodistCommand(client *c) {
} }
/* Look up the requested zset */ /* Look up the requested zset */
robj *zobj = NULL; robj_roptr zobj = NULL;
if ((zobj = lookupKeyReadOrReply(c, c->argv[1], shared.null[c->resp])) if ((zobj = lookupKeyReadOrReply(c, c->argv[1], shared.null[c->resp]))
== NULL || checkType(c, zobj, OBJ_ZSET)) return; == nullptr || checkType(c, zobj, OBJ_ZSET)) return;
/* Get the scores. We need both otherwise NULL is returned. */ /* Get the scores. We need both otherwise NULL is returned. */
double score1, score2, xyxy[4]; double score1, score2, xyxy[4];

View File

@ -1073,7 +1073,7 @@ int hllAdd(robj *o, unsigned char *ele, size_t elesize) {
* *
* If the HyperLogLog is sparse and is found to be invalid, C_ERR * If the HyperLogLog is sparse and is found to be invalid, C_ERR
* is returned, otherwise the function always succeeds. */ * is returned, otherwise the function always succeeds. */
int hllMerge(uint8_t *max, size_t cmax, robj *hll) { int hllMerge(uint8_t *max, size_t cmax, robj_roptr hll) {
struct hllhdr *hdr = (hllhdr*)ptrFromObj(hll); struct hllhdr *hdr = (hllhdr*)ptrFromObj(hll);
int i; int i;
@ -1085,7 +1085,7 @@ int hllMerge(uint8_t *max, size_t cmax, robj *hll) {
if (val > max[i]) max[i] = val; if (val > max[i]) max[i] = val;
} }
} else { } else {
uint8_t *p = (uint8_t*)ptrFromObj(hll), *end = p + sdslen(szFromObj(hll)); const uint8_t *p = (const uint8_t*)ptrFromObj(hll), *end = p + sdslen(szFromObj(hll));
long runlen, regval; long runlen, regval;
p += HLL_HDR_SIZE; p += HLL_HDR_SIZE;
@ -1156,7 +1156,7 @@ robj *createHLLObject(void) {
/* Check if the object is a String with a valid HLL representation. /* Check if the object is a String with a valid HLL representation.
* Return C_OK if this is true, otherwise reply to the client * Return C_OK if this is true, otherwise reply to the client
* with an error and return C_ERR. */ * with an error and return C_ERR. */
int isHLLObjectOrReply(client *c, robj *o) { int isHLLObjectOrReply(client *c, robj_roptr o) {
struct hllhdr *hdr; struct hllhdr *hdr;
/* Key exists, check type */ /* Key exists, check type */
@ -1248,8 +1248,8 @@ void pfcountCommand(client *c) {
registers = max + HLL_HDR_SIZE; registers = max + HLL_HDR_SIZE;
for (j = 1; j < c->argc; j++) { for (j = 1; j < c->argc; j++) {
/* Check type and size. */ /* Check type and size. */
robj *o = lookupKeyRead(c->db,c->argv[j]); robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
if (o == NULL) continue; /* Assume empty HLL for non existing var.*/ if (o == nullptr) continue; /* Assume empty HLL for non existing var.*/
if (isHLLObjectOrReply(c,o) != C_OK) return; if (isHLLObjectOrReply(c,o) != C_OK) return;
/* Merge with this HLL with our 'max' HHL by setting max[i] /* Merge with this HLL with our 'max' HHL by setting max[i]
@ -1330,8 +1330,8 @@ void pfmergeCommand(client *c) {
memset(max,0,sizeof(max)); memset(max,0,sizeof(max));
for (j = 1; j < c->argc; j++) { for (j = 1; j < c->argc; j++) {
/* Check type and size. */ /* Check type and size. */
robj *o = lookupKeyRead(c->db,c->argv[j]); robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
if (o == NULL) continue; /* Assume empty HLL for non existing var. */ if (o == nullptr) continue; /* Assume empty HLL for non existing var. */
if (isHLLObjectOrReply(c,o) != C_OK) return; if (isHLLObjectOrReply(c,o) != C_OK) return;
/* If at least one involved HLL is dense, use the dense representation /* If at least one involved HLL is dense, use the dense representation

View File

@ -44,6 +44,10 @@
#define LP_AFTER 1 #define LP_AFTER 1
#define LP_REPLACE 2 #define LP_REPLACE 2
#ifdef __cplusplus
extern "C" {
#endif
unsigned char *lpNew(void); unsigned char *lpNew(void);
void lpFree(unsigned char *lp); void lpFree(unsigned char *lp);
unsigned char *lpInsert(unsigned char *lp, unsigned char *ele, uint32_t size, unsigned char *p, int where, unsigned char **newp); unsigned char *lpInsert(unsigned char *lp, unsigned char *ele, uint32_t size, unsigned char *p, int where, unsigned char **newp);
@ -58,4 +62,8 @@ unsigned char *lpPrev(unsigned char *lp, unsigned char *p);
uint32_t lpBytes(unsigned char *lp); uint32_t lpBytes(unsigned char *lp);
unsigned char *lpSeek(unsigned char *lp, long index); unsigned char *lpSeek(unsigned char *lp, long index);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -1525,7 +1525,7 @@ void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
if (mode & REDISMODULE_WRITE) { if (mode & REDISMODULE_WRITE) {
value = lookupKeyWrite(ctx->client->db,keyname); value = lookupKeyWrite(ctx->client->db,keyname);
} else { } else {
value = lookupKeyRead(ctx->client->db,keyname); value = lookupKeyRead(ctx->client->db,keyname).unsafe_robjcast();
if (value == NULL) { if (value == NULL) {
return NULL; return NULL;
} }

View File

@ -122,7 +122,7 @@ void *dupClientReplyValue(void *o) {
return buf; return buf;
} }
void freeClientReplyValue(void *o) { void freeClientReplyValue(const void *o) {
zfree(o); zfree(o);
} }
@ -405,7 +405,7 @@ void _addReplyProtoToList(client *c, const char *s, size_t len) {
* Higher level functions to queue data on the client output buffer. * Higher level functions to queue data on the client output buffer.
* The following functions are the ones that commands implementations will call. * The following functions are the ones that commands implementations will call.
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
void addReplyCore(client *c, robj *obj, bool fAsync) { void addReplyCore(client *c, robj_roptr obj, bool fAsync) {
if (prepareClientToWrite(c, fAsync) != C_OK) return; if (prepareClientToWrite(c, fAsync) != C_OK) return;
if (sdsEncodedObject(obj)) { if (sdsEncodedObject(obj)) {
@ -425,11 +425,11 @@ void addReplyCore(client *c, robj *obj, bool fAsync) {
} }
/* Add the object 'obj' string representation to the client output buffer. */ /* Add the object 'obj' string representation to the client output buffer. */
void addReply(client *c, robj *obj) void addReply(client *c, robj_roptr obj)
{ {
addReplyCore(c, obj, false); addReplyCore(c, obj, false);
} }
void addReplyAsync(client *c, robj *obj) void addReplyAsync(client *c, robj_roptr obj)
{ {
addReplyCore(c, obj, true); addReplyCore(c, obj, true);
} }
@ -867,7 +867,7 @@ void addReplyNullArray(client *c) {
} }
/* Create the length prefix of a bulk reply, example: $2234 */ /* Create the length prefix of a bulk reply, example: $2234 */
void addReplyBulkLenCore(client *c, robj *obj, bool fAsync) { void addReplyBulkLenCore(client *c, robj_roptr obj, bool fAsync) {
size_t len = stringObjectLen(obj); size_t len = stringObjectLen(obj);
if (len < OBJ_SHARED_BULKHDR_LEN) if (len < OBJ_SHARED_BULKHDR_LEN)
@ -882,18 +882,18 @@ void addReplyBulkLen(client *c, robj *obj)
} }
/* Add a Redis Object as a bulk reply */ /* Add a Redis Object as a bulk reply */
void addReplyBulkCore(client *c, robj *obj, bool fAsync) { void addReplyBulkCore(client *c, robj_roptr obj, bool fAsync) {
addReplyBulkLenCore(c,obj,fAsync); addReplyBulkLenCore(c,obj,fAsync);
addReplyCore(c,obj,fAsync); addReplyCore(c,obj,fAsync);
addReplyCore(c,shared.crlf,fAsync); addReplyCore(c,shared.crlf,fAsync);
} }
void addReplyBulk(client *c, robj *obj) void addReplyBulk(client *c, robj_roptr obj)
{ {
addReplyBulkCore(c, obj, false); addReplyBulkCore(c, obj, false);
} }
void addReplyBulkAsync(client *c, robj *obj) void addReplyBulkAsync(client *c, robj_roptr obj)
{ {
addReplyBulkCore(c, obj, true); addReplyBulkCore(c, obj, true);
} }

View File

@ -44,6 +44,9 @@ robj *createObject(int type, void *ptr) {
o->encoding = OBJ_ENCODING_RAW; o->encoding = OBJ_ENCODING_RAW;
o->m_ptr = ptr; o->m_ptr = ptr;
o->refcount = 1; o->refcount = 1;
#ifdef ENABLE_MVCC
o->mvcc_tstamp = OBJ_MVCC_INVALID;
#endif
/* Set the LRU to the current lruclock (minutes resolution), or /* Set the LRU to the current lruclock (minutes resolution), or
* alternatively the LFU counter. */ * alternatively the LFU counter. */
@ -91,6 +94,9 @@ robj *createEmbeddedStringObject(const char *ptr, size_t len) {
o->type = OBJ_STRING; o->type = OBJ_STRING;
o->encoding = OBJ_ENCODING_EMBSTR; o->encoding = OBJ_ENCODING_EMBSTR;
o->refcount = 1; o->refcount = 1;
#ifdef ENABLE_MVCC
o->mvcc_tstamp = OBJ_MVCC_INVALID;
#endif
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL; o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;
} else { } else {
@ -280,13 +286,13 @@ robj *createModuleObject(moduleType *mt, void *value) {
return createObject(OBJ_MODULE,mv); return createObject(OBJ_MODULE,mv);
} }
void freeStringObject(robj *o) { void freeStringObject(robj_roptr o) {
if (o->encoding == OBJ_ENCODING_RAW) { if (o->encoding == OBJ_ENCODING_RAW) {
sdsfree(szFromObj(o)); sdsfree(szFromObj(o));
} }
} }
void freeListObject(robj *o) { void freeListObject(robj_roptr o) {
if (o->encoding == OBJ_ENCODING_QUICKLIST) { if (o->encoding == OBJ_ENCODING_QUICKLIST) {
quicklistRelease((quicklist*)ptrFromObj(o)); quicklistRelease((quicklist*)ptrFromObj(o));
} else { } else {
@ -294,7 +300,7 @@ void freeListObject(robj *o) {
} }
} }
void freeSetObject(robj *o) { void freeSetObject(robj_roptr o) {
switch (o->encoding) { switch (o->encoding) {
case OBJ_ENCODING_HT: case OBJ_ENCODING_HT:
dictRelease((dict*) ptrFromObj(o)); dictRelease((dict*) ptrFromObj(o));
@ -307,7 +313,7 @@ void freeSetObject(robj *o) {
} }
} }
void freeZsetObject(robj *o) { void freeZsetObject(robj_roptr o) {
zset *zs; zset *zs;
switch (o->encoding) { switch (o->encoding) {
case OBJ_ENCODING_SKIPLIST: case OBJ_ENCODING_SKIPLIST:
@ -324,7 +330,7 @@ void freeZsetObject(robj *o) {
} }
} }
void freeHashObject(robj *o) { void freeHashObject(robj_roptr o) {
switch (o->encoding) { switch (o->encoding) {
case OBJ_ENCODING_HT: case OBJ_ENCODING_HT:
dictRelease((dict*) ptrFromObj(o)); dictRelease((dict*) ptrFromObj(o));
@ -338,21 +344,21 @@ void freeHashObject(robj *o) {
} }
} }
void freeModuleObject(robj *o) { void freeModuleObject(robj_roptr o) {
moduleValue *mv = (moduleValue*)ptrFromObj(o); moduleValue *mv = (moduleValue*)ptrFromObj(o);
mv->type->free(mv->value); mv->type->free(mv->value);
zfree(mv); zfree(mv);
} }
void freeStreamObject(robj *o) { void freeStreamObject(robj_roptr o) {
freeStream((stream*)ptrFromObj(o)); freeStream((stream*)ptrFromObj(o));
} }
void incrRefCount(robj *o) { void incrRefCount(robj_roptr o) {
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount++; if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount++;
} }
void decrRefCount(robj *o) { void decrRefCount(robj_roptr o) {
if (o->refcount == 1) { if (o->refcount == 1) {
switch(o->type) { switch(o->type) {
case OBJ_STRING: freeStringObject(o); break; case OBJ_STRING: freeStringObject(o); break;
@ -364,7 +370,7 @@ void decrRefCount(robj *o) {
case OBJ_STREAM: freeStreamObject(o); break; case OBJ_STREAM: freeStreamObject(o); break;
default: serverPanic("Unknown object type"); break; default: serverPanic("Unknown object type"); break;
} }
zfree(o); zfree(o.unsafe_robjcast());
} else { } else {
if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0"); if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--; if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--;
@ -374,7 +380,7 @@ void decrRefCount(robj *o) {
/* This variant of decrRefCount() gets its argument as void, and is useful /* This variant of decrRefCount() gets its argument as void, and is useful
* as free method in data structures that expect a 'void free_object(void*)' * as free method in data structures that expect a 'void free_object(void*)'
* prototype for the free method. */ * prototype for the free method. */
void decrRefCountVoid(void *o) { void decrRefCountVoid(const void *o) {
decrRefCount((robj*)o); decrRefCount((robj*)o);
} }
@ -395,7 +401,7 @@ robj *resetRefCount(robj *obj) {
return obj; return obj;
} }
int checkType(client *c, robj *o, int type) { int checkType(client *c, robj_roptr o, int type) {
if (o->type != type) { if (o->type != type) {
addReplyAsync(c,shared.wrongtypeerr); addReplyAsync(c,shared.wrongtypeerr);
return 1; return 1;
@ -403,7 +409,7 @@ int checkType(client *c, robj *o, int type) {
return 0; return 0;
} }
int isSdsRepresentableAsLongLong(sds s, long long *llval) { int isSdsRepresentableAsLongLong(const char *s, long long *llval) {
return string2ll(s,sdslen(s),llval) ? C_OK : C_ERR; return string2ll(s,sdslen(s),llval) ? C_OK : C_ERR;
} }
@ -524,6 +530,10 @@ robj *getDecodedObject(robj *o) {
} }
} }
robj_roptr getDecodedObject(robj_roptr o) {
return getDecodedObject(o.unsafe_robjcast());
}
/* Compare two string objects via strcmp() or strcoll() depending on flags. /* Compare two string objects via strcmp() or strcoll() depending on flags.
* Note that the objects may be integer-encoded. In such a case we * Note that the objects may be integer-encoded. In such a case we
* use ll2string() to get a string representation of the numbers on the stack * use ll2string() to get a string representation of the numbers on the stack
@ -592,7 +602,7 @@ int equalStringObjects(robj *a, robj *b) {
} }
} }
size_t stringObjectLen(robj *o) { size_t stringObjectLen(robj_roptr o) {
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING); serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
if (sdsEncodedObject(o)) { if (sdsEncodedObject(o)) {
return sdslen(szFromObj(o)); return sdslen(szFromObj(o));

View File

@ -120,7 +120,7 @@ void addReplyPubsubPatUnsubscribed(client *c, robj *pattern) {
* Pubsub low level API * Pubsub low level API
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void freePubsubPattern(void *p) { void freePubsubPattern(const void *p) {
pubsubPattern *pat = (pubsubPattern *)p; pubsubPattern *pat = (pubsubPattern *)p;
decrRefCount(pat->pattern); decrRefCount(pat->pattern);

View File

@ -6,7 +6,7 @@ extern "C" {
#include <sys/wait.h> #include <sys/wait.h>
/* Save the DB on disk. Return C_ERR on error, C_OK on success. */ /* Save the DB on disk. Return C_ERR on error, C_OK on success. */
extern "C" int rdbSaveS3(char *s3bucket, rdbSaveInfo *rsi) int rdbSaveS3(char *s3bucket, rdbSaveInfo *rsi)
{ {
int status = EXIT_FAILURE; int status = EXIT_FAILURE;
int fd[2]; int fd[2];

View File

@ -455,7 +455,7 @@ ssize_t rdbSaveLongLongAsStringObject(rio *rdb, long long value) {
} }
/* Like rdbSaveRawString() gets a Redis object instead. */ /* Like rdbSaveRawString() gets a Redis object instead. */
ssize_t rdbSaveStringObject(rio *rdb, robj *obj) { ssize_t rdbSaveStringObject(rio *rdb, robj_roptr obj) {
/* Avoid to decode the object, then encode it again, if the /* Avoid to decode the object, then encode it again, if the
* object is already integer encoded. */ * object is already integer encoded. */
if (obj->encoding == OBJ_ENCODING_INT) { if (obj->encoding == OBJ_ENCODING_INT) {
@ -623,7 +623,7 @@ int rdbLoadBinaryFloatValue(rio *rdb, float *val) {
} }
/* Save the object type of object "o". */ /* Save the object type of object "o". */
int rdbSaveObjectType(rio *rdb, robj *o) { int rdbSaveObjectType(rio *rdb, robj_roptr o) {
switch (o->type) { switch (o->type) {
case OBJ_STRING: case OBJ_STRING:
return rdbSaveType(rdb,RDB_TYPE_STRING); return rdbSaveType(rdb,RDB_TYPE_STRING);
@ -752,7 +752,7 @@ size_t rdbSaveStreamConsumers(rio *rdb, streamCG *cg) {
/* Save a Redis object. /* Save a Redis object.
* Returns -1 on error, number of bytes written on success. */ * Returns -1 on error, number of bytes written on success. */
ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) { ssize_t rdbSaveObject(rio *rdb, robj_roptr o, robj *key) {
ssize_t n = 0, nwritten = 0; ssize_t n = 0, nwritten = 0;
if (o->type == OBJ_STRING) { if (o->type == OBJ_STRING) {

View File

@ -133,7 +133,7 @@ int rdbSaveMillisecondTime(rio *rdb, long long t);
long long rdbLoadMillisecondTime(rio *rdb, int rdbver); long long rdbLoadMillisecondTime(rio *rdb, int rdbver);
uint64_t rdbLoadLen(rio *rdb, int *isencoded); uint64_t rdbLoadLen(rio *rdb, int *isencoded);
int rdbLoadLenByRef(rio *rdb, int *isencoded, uint64_t *lenptr); int rdbLoadLenByRef(rio *rdb, int *isencoded, uint64_t *lenptr);
int rdbSaveObjectType(rio *rdb, robj *o); int rdbSaveObjectType(rio *rdb, robj_roptr o);
int rdbLoadObjectType(rio *rdb); int rdbLoadObjectType(rio *rdb);
int rdbLoad(rdbSaveInfo *rsi); int rdbLoad(rdbSaveInfo *rsi);
int rdbSaveBackground(rdbSaveInfo *rsi); int rdbSaveBackground(rdbSaveInfo *rsi);
@ -144,13 +144,13 @@ int rdbSaveFile(char *filename, rdbSaveInfo *rsi);
int rdbSaveFd(int fd, rdbSaveInfo *rsi); int rdbSaveFd(int fd, rdbSaveInfo *rsi);
int rdbSaveS3(char *path, rdbSaveInfo *rsi); int rdbSaveS3(char *path, rdbSaveInfo *rsi);
int rdbLoadS3(char *path, rdbSaveInfo *rsi); int rdbLoadS3(char *path, rdbSaveInfo *rsi);
ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key); ssize_t rdbSaveObject(rio *rdb, robj_roptr o, robj *key);
size_t rdbSavedObjectLen(robj *o); size_t rdbSavedObjectLen(robj *o);
robj *rdbLoadObject(int type, rio *rdb, robj *key); robj *rdbLoadObject(int type, rio *rdb, robj *key);
void backgroundSaveDoneHandler(int exitcode, int bysignal); void backgroundSaveDoneHandler(int exitcode, int bysignal);
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime); int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime);
robj *rdbLoadStringObject(rio *rdb); robj *rdbLoadStringObject(rio *rdb);
ssize_t rdbSaveStringObject(rio *rdb, robj *obj); ssize_t rdbSaveStringObject(rio *rdb, robj_roptr obj);
ssize_t rdbSaveRawString(rio *rdb, const unsigned char *s, size_t len); ssize_t rdbSaveRawString(rio *rdb, const unsigned char *s, size_t len);
void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr); void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr);
int rdbSaveBinaryDoubleValue(rio *rdb, double val); int rdbSaveBinaryDoubleValue(rio *rdb, double val);

View File

@ -889,29 +889,28 @@ void syncCommand(client *c) {
void processReplconfUuid(client *c, robj *arg) void processReplconfUuid(client *c, robj *arg)
{ {
try const char *remoteUUID = nullptr;
{
if (arg->type != OBJ_STRING)
throw "Invalid UUID";
const char *remoteUUID = (const char*)ptrFromObj(arg); if (arg->type != OBJ_STRING)
if (strlen(remoteUUID) != 36) goto LError;
throw "Invalid UUID";
if (uuid_parse(remoteUUID, c->uuid) != 0) remoteUUID = (const char*)ptrFromObj(arg);
throw "Invalid UUID"; if (strlen(remoteUUID) != 36)
goto LError;
char szServerUUID[36 + 2]; // 1 for the '+', another for '\0' if (uuid_parse(remoteUUID, c->uuid) != 0)
szServerUUID[0] = '+'; goto LError;
uuid_unparse(server.uuid, szServerUUID+1);
addReplyProto(c, szServerUUID, 37); char szServerUUID[36 + 2]; // 1 for the '+', another for '\0'
addReplyProto(c, "\r\n", 2); szServerUUID[0] = '+';
} uuid_unparse(server.uuid, szServerUUID+1);
catch (const char *szErr) addReplyProto(c, szServerUUID, 37);
{ addReplyProto(c, "\r\n", 2);
addReplyError(c, szErr); return;
return;
} LError:
addReplyError(c, "Invalid UUID");
return;
} }
/* REPLCONF <option> <value> <option> <value> ... /* REPLCONF <option> <value> <option> <value> ...

View File

@ -1616,7 +1616,7 @@ void ldbInit(void) {
ldb.fd = -1; ldb.fd = -1;
ldb.active = 0; ldb.active = 0;
ldb.logs = listCreate(); ldb.logs = listCreate();
listSetFreeMethod(ldb.logs,(void (*)(void*))sdsfree); listSetFreeMethod(ldb.logs,(void (*)(const void*))sdsfree);
ldb.children = listCreate(); ldb.children = listCreate();
ldb.src = NULL; ldb.src = NULL;
ldb.lines = 0; ldb.lines = 0;

View File

@ -157,12 +157,12 @@ sds sdsnew(const char *init) {
} }
/* Duplicate an sds string. */ /* Duplicate an sds string. */
sds sdsdup(const sds s) { sds sdsdup(const char *s) {
return sdsnewlen(s, sdslen(s)); return sdsnewlen(s, sdslen(s));
} }
/* Free an sds string. No operation is performed if 's' is NULL. */ /* Free an sds string. No operation is performed if 's' is NULL. */
void sdsfree(sds s) { void sdsfree(const char *s) {
if (s == NULL) return; if (s == NULL) return;
s_free((char*)s-sdsHdrSize(s[-1])); s_free((char*)s-sdsHdrSize(s[-1]));
} }

View File

@ -102,7 +102,7 @@ struct __attribute__ ((__packed__)) sdshdr64 {
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) #define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) #define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
static inline size_t sdslen(const sds s) { static inline size_t sdslen(const char *s) {
unsigned char flags = s[-1]; unsigned char flags = s[-1];
int type = flags & SDS_TYPE_MASK; int type = flags & SDS_TYPE_MASK;
@ -126,7 +126,7 @@ static inline size_t sdslen(const sds s) {
return 0; return 0;
} }
static inline size_t sdsavail(const sds s) { static inline size_t sdsavail(const char * s) {
unsigned char flags = s[-1]; unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) { switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5: { case SDS_TYPE_5: {
@ -243,8 +243,8 @@ static inline void sdssetalloc(sds s, size_t newlen) {
sds sdsnewlen(const void *init, size_t initlen); sds sdsnewlen(const void *init, size_t initlen);
sds sdsnew(const char *init); sds sdsnew(const char *init);
sds sdsempty(void); sds sdsempty(void);
sds sdsdup(const sds s); sds sdsdup(const char *s);
void sdsfree(sds s); void sdsfree(const char *s);
sds sdsgrowzero(sds s, size_t len); sds sdsgrowzero(sds s, size_t len);
sds sdscatlen(sds s, const void *t, size_t len); sds sdscatlen(sds s, const void *t, size_t len);
sds sdscat(sds s, const char *t); sds sdscat(sds s, const char *t);

View File

@ -3132,7 +3132,7 @@ void redisOpArrayFree(redisOpArray *oa) {
/* ====================== Commands lookup and execution ===================== */ /* ====================== Commands lookup and execution ===================== */
extern "C" struct redisCommand *lookupCommand(sds name) { struct redisCommand *lookupCommand(sds name) {
return (struct redisCommand*)dictFetchValue(server.commands, name); return (struct redisCommand*)dictFetchValue(server.commands, name);
} }
@ -3930,7 +3930,7 @@ void bytesToHuman(char *s, unsigned long long n) {
/* Create the string returned by the INFO command. This is decoupled /* Create the string returned by the INFO command. This is decoupled
* by the INFO command itself as we need to report the same information * by the INFO command itself as we need to report the same information
* on memory corruption problems. */ * on memory corruption problems. */
extern "C" sds genRedisInfoString(const char *section) { sds genRedisInfoString(const char *section) {
sds info = sdsempty(); sds info = sdsempty();
time_t uptime = server.unixtime-server.stat_starttime; time_t uptime = server.unixtime-server.stat_starttime;
int j; int j;
@ -4876,6 +4876,11 @@ int redisIsSupervised(int mode) {
return 0; return 0;
} }
uint64_t getMvccTstamp()
{
return (server.mstime << 16);
}
void *workerThreadMain(void *parg) void *workerThreadMain(void *parg)
{ {
int iel = (int)((int64_t)parg); int iel = (int)((int64_t)parg);

View File

@ -84,9 +84,57 @@ typedef long long mstime_t; /* millisecond time type. */
#include "endianconv.h" #include "endianconv.h"
#include "crc64.h" #include "crc64.h"
#ifdef __cplusplus struct redisObject;
extern "C" { class robj_roptr
#endif {
const redisObject *m_ptr;
public:
robj_roptr()
: m_ptr(nullptr)
{}
robj_roptr(const redisObject *ptr)
: m_ptr(ptr)
{}
robj_roptr(const robj_roptr&) = default;
robj_roptr(robj_roptr&&) = default;
robj_roptr &operator=(const robj_roptr&) = default;
robj_roptr &operator=(const redisObject *ptr)
{
m_ptr = ptr;
return *this;
}
bool operator==(const robj_roptr &other) const
{
return m_ptr == other.m_ptr;
}
bool operator!=(const robj_roptr &other) const
{
return m_ptr != other.m_ptr;
}
const redisObject* operator->() const
{
return m_ptr;
}
bool operator!() const
{
return !m_ptr;
}
operator bool() const{
return !!m_ptr;
}
redisObject *unsafe_robjcast()
{
return (redisObject*)m_ptr;
}
};
/* Error codes */ /* Error codes */
#define C_OK 0 #define C_OK 0
@ -654,16 +702,28 @@ typedef struct RedisModuleDigest {
#define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */ #define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */
#define OBJ_SHARED_REFCOUNT INT_MAX #define OBJ_SHARED_REFCOUNT INT_MAX
#define OBJ_MVCC_INVALID (0xFFFFFFFFFFFFFFFFULL)
typedef struct redisObject { typedef struct redisObject {
unsigned type:4; unsigned type:4;
unsigned encoding:4; unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency * LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */ * and most significant 16 bits access time). */
int refcount; #ifdef ENABLE_MVCC
uint64_t mvcc_tstamp;
#endif
mutable int refcount;
void *m_ptr; void *m_ptr;
} robj; } robj;
__attribute__((always_inline)) inline const void *ptrFromObj(robj_roptr &o)
{
if (o->encoding == OBJ_ENCODING_EMBSTR)
return ((char*)&(o)->m_ptr) + sizeof(struct sdshdr8);
return o->m_ptr;
}
__attribute__((always_inline)) inline void *ptrFromObj(const robj *o) __attribute__((always_inline)) inline void *ptrFromObj(const robj *o)
{ {
if (o->encoding == OBJ_ENCODING_EMBSTR) if (o->encoding == OBJ_ENCODING_EMBSTR)
@ -671,6 +731,11 @@ __attribute__((always_inline)) inline void *ptrFromObj(const robj *o)
return o->m_ptr; return o->m_ptr;
} }
__attribute__((always_inline)) inline const char *szFromObj(robj_roptr o)
{
return (const char*)ptrFromObj(o);
}
__attribute__((always_inline)) inline char *szFromObj(const robj *o) __attribute__((always_inline)) inline char *szFromObj(const robj *o)
{ {
return (char*)ptrFromObj(o); return (char*)ptrFromObj(o);
@ -1511,7 +1576,7 @@ typedef struct _redisSortOperation {
/* Structure to hold list iteration abstraction. */ /* Structure to hold list iteration abstraction. */
typedef struct { typedef struct {
robj *subject; robj_roptr subject;
unsigned char encoding; unsigned char encoding;
unsigned char direction; /* Iteration direction */ unsigned char direction; /* Iteration direction */
quicklistIter *iter; quicklistIter *iter;
@ -1525,7 +1590,7 @@ typedef struct {
/* Structure to hold set iteration abstraction. */ /* Structure to hold set iteration abstraction. */
typedef struct { typedef struct {
robj *subject; robj_roptr subject;
int encoding; int encoding;
int ii; /* intset iterator */ int ii; /* intset iterator */
dictIterator *di; dictIterator *di;
@ -1536,7 +1601,7 @@ typedef struct {
* not both are required, store pointers in the iterator to avoid * not both are required, store pointers in the iterator to avoid
* unnecessary memory allocation for fields/values. */ * unnecessary memory allocation for fields/values. */
typedef struct { typedef struct {
robj *subject; robj_roptr subject;
int encoding; int encoding;
unsigned char *fptr, *vptr; unsigned char *fptr, *vptr;
@ -1596,11 +1661,11 @@ void moduleCallCommandFilters(client *c);
/* Utils */ /* Utils */
long long ustime(void); long long ustime(void);
long long mstime(void); long long mstime(void);
void getRandomHexChars(char *p, size_t len); extern "C" void getRandomHexChars(char *p, size_t len);
void getRandomBytes(unsigned char *p, size_t len); extern "C" void getRandomBytes(unsigned char *p, size_t len);
uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l); uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
void exitFromChild(int retcode); void exitFromChild(int retcode);
size_t redisPopcount(void *s, long count); size_t redisPopcount(const void *s, long count);
void redisSetProcTitle(const char *title); void redisSetProcTitle(const char *title);
/* networking.c -- Networking and Client related operations */ /* networking.c -- Networking and Client related operations */
@ -1627,11 +1692,11 @@ void addReplyNullArray(client *c);
void addReplyBool(client *c, int b); void addReplyBool(client *c, int b);
void addReplyVerbatim(client *c, const char *s, size_t len, const char *ext); void addReplyVerbatim(client *c, const char *s, size_t len, const char *ext);
void addReplyProto(client *c, const char *s, size_t len); void addReplyProto(client *c, const char *s, size_t len);
void addReplyBulk(client *c, robj *obj); void addReplyBulk(client *c, robj_roptr obj);
void addReplyBulkCString(client *c, const char *s); void addReplyBulkCString(client *c, const char *s);
void addReplyBulkCBuffer(client *c, const void *p, size_t len); void addReplyBulkCBuffer(client *c, const void *p, size_t len);
void addReplyBulkLongLong(client *c, long long ll); void addReplyBulkLongLong(client *c, long long ll);
void addReply(client *c, robj *obj); void addReply(client *c, robj_roptr obj);
void addReplySds(client *c, sds s); void addReplySds(client *c, sds s);
void addReplyBulkSds(client *c, sds s); void addReplyBulkSds(client *c, sds s);
void addReplyError(client *c, const char *err); void addReplyError(client *c, const char *err);
@ -1653,7 +1718,7 @@ void addReplyLoadedModules(client *c);
void copyClientOutputBuffer(client *dst, client *src); void copyClientOutputBuffer(client *dst, client *src);
size_t sdsZmallocSize(sds s); size_t sdsZmallocSize(sds s);
size_t getStringObjectSdsUsedMemory(robj *o); size_t getStringObjectSdsUsedMemory(robj *o);
void freeClientReplyValue(void *o); void freeClientReplyValue(const void *o);
void *dupClientReplyValue(void *o); void *dupClientReplyValue(void *o);
void getClientsMaxBuffers(unsigned long *longest_output_list, void getClientsMaxBuffers(unsigned long *longest_output_list,
unsigned long *biggest_input_buffer); unsigned long *biggest_input_buffer);
@ -1685,10 +1750,10 @@ void protectClient(client *c);
void unprotectClient(client *c); void unprotectClient(client *c);
// Special Thread-safe addReply() commands for posting messages to clients from a different thread // Special Thread-safe addReply() commands for posting messages to clients from a different thread
void addReplyAsync(client *c, robj *obj); void addReplyAsync(client *c, robj_roptr obj);
void addReplyArrayLenAsync(client *c, long length); void addReplyArrayLenAsync(client *c, long length);
void addReplyProtoAsync(client *c, const char *s, size_t len); void addReplyProtoAsync(client *c, const char *s, size_t len);
void addReplyBulkAsync(client *c, robj *obj); void addReplyBulkAsync(client *c, robj_roptr obj);
void addReplyBulkCBufferAsync(client *c, const void *p, size_t len); void addReplyBulkCBufferAsync(client *c, const void *p, size_t len);
void addReplyErrorAsync(client *c, const char *err); void addReplyErrorAsync(client *c, const char *err);
void addReplyMapLenAsync(client *c, long length); void addReplyMapLenAsync(client *c, long length);
@ -1717,8 +1782,8 @@ void addReplyStatusFormat(client *c, const char *fmt, ...);
void listTypeTryConversion(robj *subject, robj *value); void listTypeTryConversion(robj *subject, robj *value);
void listTypePush(robj *subject, robj *value, int where); void listTypePush(robj *subject, robj *value, int where);
robj *listTypePop(robj *subject, int where); robj *listTypePop(robj *subject, int where);
unsigned long listTypeLength(const robj *subject); unsigned long listTypeLength(robj_roptr subject);
listTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction); listTypeIterator *listTypeInitIterator(robj_roptr subject, long index, unsigned char direction);
void listTypeReleaseIterator(listTypeIterator *li); void listTypeReleaseIterator(listTypeIterator *li);
int listTypeNext(listTypeIterator *li, listTypeEntry *entry); int listTypeNext(listTypeIterator *li, listTypeEntry *entry);
robj *listTypeGet(listTypeEntry *entry); robj *listTypeGet(listTypeEntry *entry);
@ -1741,9 +1806,9 @@ void flagTransaction(client *c);
void execCommandPropagateMulti(client *c); void execCommandPropagateMulti(client *c);
/* Redis object implementation */ /* Redis object implementation */
void decrRefCount(robj *o); void decrRefCount(robj_roptr o);
void decrRefCountVoid(void *o); void decrRefCountVoid(const void *o);
void incrRefCount(robj *o); void incrRefCount(robj_roptr o);
robj *makeObjectShared(robj *o); robj *makeObjectShared(robj *o);
robj *resetRefCount(robj *obj); robj *resetRefCount(robj *obj);
void freeStringObject(robj *o); void freeStringObject(robj *o);
@ -1756,11 +1821,12 @@ robj *createStringObject(const char *ptr, size_t len);
robj *createRawStringObject(const char *ptr, size_t len); robj *createRawStringObject(const char *ptr, size_t len);
robj *createEmbeddedStringObject(const char *ptr, size_t len); robj *createEmbeddedStringObject(const char *ptr, size_t len);
robj *dupStringObject(const robj *o); robj *dupStringObject(const robj *o);
int isSdsRepresentableAsLongLong(sds s, long long *llval); int isSdsRepresentableAsLongLong(const char *s, long long *llval);
int isObjectRepresentableAsLongLong(robj *o, long long *llongval); int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
robj *tryObjectEncoding(robj *o); robj *tryObjectEncoding(robj *o);
robj *getDecodedObject(robj *o); robj *getDecodedObject(robj *o);
size_t stringObjectLen(robj *o); robj_roptr getDecodedObject(robj_roptr o);
size_t stringObjectLen(robj_roptr o);
robj *createStringObjectFromLongLong(long long value); robj *createStringObjectFromLongLong(long long value);
robj *createStringObjectFromLongLongForValue(long long value); robj *createStringObjectFromLongLongForValue(long long value);
robj *createStringObjectFromLongDouble(long double value, int humanfriendly); robj *createStringObjectFromLongDouble(long double value, int humanfriendly);
@ -1774,7 +1840,7 @@ robj *createZsetZiplistObject(void);
robj *createStreamObject(void); robj *createStreamObject(void);
robj *createModuleObject(moduleType *mt, void *value); robj *createModuleObject(moduleType *mt, void *value);
int getLongFromObjectOrReply(client *c, robj *o, long *target, const char *msg); int getLongFromObjectOrReply(client *c, robj *o, long *target, const char *msg);
int checkType(client *c, robj *o, int type); int checkType(client *c, robj_roptr o, int type);
int getLongLongFromObjectOrReply(client *c, robj *o, long long *target, const char *msg); int getLongLongFromObjectOrReply(client *c, robj *o, long long *target, const char *msg);
int getDoubleFromObjectOrReply(client *c, robj *o, double *target, const char *msg); int getDoubleFromObjectOrReply(client *c, robj *o, double *target, const char *msg);
int getDoubleFromObject(const robj *o, double *target); int getDoubleFromObject(const robj *o, double *target);
@ -1925,13 +1991,13 @@ void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);
void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr); void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);
unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range); unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range);
unsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range); unsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range);
unsigned long zsetLength(const robj *zobj); unsigned long zsetLength(robj_roptr zobj);
void zsetConvert(robj *zobj, int encoding); void zsetConvert(robj *zobj, int encoding);
void zsetConvertToZiplistIfNeeded(robj *zobj, size_t maxelelen); void zsetConvertToZiplistIfNeeded(robj *zobj, size_t maxelelen);
int zsetScore(robj *zobj, sds member, double *score); int zsetScore(robj_roptr zobj, sds member, double *score);
unsigned long zslGetRank(zskiplist *zsl, double score, sds o); unsigned long zslGetRank(zskiplist *zsl, double score, sds o);
int zsetAdd(robj *zobj, double score, sds ele, int *flags, double *newscore); int zsetAdd(robj *zobj, double score, sds ele, int *flags, double *newscore);
long zsetRank(robj *zobj, sds ele, int reverse); long zsetRank(robj_roptr zobj, sds ele, int reverse);
int zsetDel(robj *zobj, sds ele); int zsetDel(robj *zobj, sds ele);
void genericZpopCommand(client *c, robj **keyv, int keyc, int where, int emitkey, robj *countarg); void genericZpopCommand(client *c, robj **keyv, int keyc, int where, int emitkey, robj *countarg);
sds ziplistGetObject(unsigned char *sptr); sds ziplistGetObject(unsigned char *sptr);
@ -1996,17 +2062,17 @@ void freeMemoryOverheadData(struct redisMemOverhead *mh);
int restartServer(int flags, mstime_t delay); int restartServer(int flags, mstime_t delay);
/* Set data type */ /* Set data type */
robj *setTypeCreate(sds value); robj *setTypeCreate(const char *value);
int setTypeAdd(robj *subject, sds value); int setTypeAdd(robj *subject, const char *value);
int setTypeRemove(robj *subject, sds value); int setTypeRemove(robj *subject, const char *value);
int setTypeIsMember(robj *subject, sds value); int setTypeIsMember(robj_roptr subject, const char *value);
setTypeIterator *setTypeInitIterator(robj *subject); setTypeIterator *setTypeInitIterator(robj_roptr subject);
void setTypeReleaseIterator(setTypeIterator *si); void setTypeReleaseIterator(setTypeIterator *si);
int setTypeNext(setTypeIterator *si, sds *sdsele, int64_t *llele); int setTypeNext(setTypeIterator *si, const char **sdsele, int64_t *llele);
sds setTypeNextObject(setTypeIterator *si); sds setTypeNextObject(setTypeIterator *si);
int setTypeRandomElement(robj *setobj, sds *sdsele, int64_t *llele); int setTypeRandomElement(robj *setobj, sds *sdsele, int64_t *llele);
unsigned long setTypeRandomElements(robj *set, unsigned long count, robj *aux_set); unsigned long setTypeRandomElements(robj *set, unsigned long count, robj *aux_set);
unsigned long setTypeSize(const robj *subject); unsigned long setTypeSize(robj_roptr subject);
void setTypeConvert(robj *subject, int enc); void setTypeConvert(robj *subject, int enc);
/* Hash data type */ /* Hash data type */
@ -2016,10 +2082,10 @@ void setTypeConvert(robj *subject, int enc);
void hashTypeConvert(robj *o, int enc); void hashTypeConvert(robj *o, int enc);
void hashTypeTryConversion(robj *subject, robj **argv, int start, int end); void hashTypeTryConversion(robj *subject, robj **argv, int start, int end);
int hashTypeExists(robj *o, sds key); int hashTypeExists(robj_roptr o, const char *key);
int hashTypeDelete(robj *o, sds key); int hashTypeDelete(robj *o, sds key);
unsigned long hashTypeLength(const robj *o); unsigned long hashTypeLength(robj_roptr o);
hashTypeIterator *hashTypeInitIterator(robj *subject); hashTypeIterator *hashTypeInitIterator(robj_roptr subject);
void hashTypeReleaseIterator(hashTypeIterator *hi); void hashTypeReleaseIterator(hashTypeIterator *hi);
int hashTypeNext(hashTypeIterator *hi); int hashTypeNext(hashTypeIterator *hi);
void hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what, void hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what,
@ -2030,13 +2096,13 @@ sds hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what);
void hashTypeCurrentObject(hashTypeIterator *hi, int what, unsigned char **vstr, unsigned int *vlen, long long *vll); void hashTypeCurrentObject(hashTypeIterator *hi, int what, unsigned char **vstr, unsigned int *vlen, long long *vll);
sds hashTypeCurrentObjectNewSds(hashTypeIterator *hi, int what); sds hashTypeCurrentObjectNewSds(hashTypeIterator *hi, int what);
robj *hashTypeLookupWriteOrCreate(client *c, robj *key); robj *hashTypeLookupWriteOrCreate(client *c, robj *key);
robj *hashTypeGetValueObject(robj *o, sds field); robj *hashTypeGetValueObject(robj_roptr o, sds field);
int hashTypeSet(robj *o, sds field, sds value, int flags); int hashTypeSet(robj *o, sds field, sds value, int flags);
/* Pub / Sub */ /* Pub / Sub */
int pubsubUnsubscribeAllChannels(client *c, int notify); int pubsubUnsubscribeAllChannels(client *c, int notify);
int pubsubUnsubscribeAllPatterns(client *c, int notify); int pubsubUnsubscribeAllPatterns(client *c, int notify);
void freePubsubPattern(void *p); void freePubsubPattern(const void *p);
int listMatchPubsubPattern(void *a, void *b); int listMatchPubsubPattern(void *a, void *b);
int pubsubPublishMessage(robj *channel, robj *message); int pubsubPublishMessage(robj *channel, robj *message);
@ -2057,14 +2123,13 @@ int rewriteConfig(char *path);
int removeExpire(redisDb *db, robj *key); int removeExpire(redisDb *db, robj *key);
void propagateExpire(redisDb *db, robj *key, int lazy); void propagateExpire(redisDb *db, robj *key, int lazy);
int expireIfNeeded(redisDb *db, robj *key); int expireIfNeeded(redisDb *db, robj *key);
long long getExpire(redisDb *db, robj *key); long long getExpire(redisDb *db, robj_roptr key);
void setExpire(client *c, redisDb *db, robj *key, long long when); void setExpire(client *c, redisDb *db, robj *key, long long when);
robj *lookupKey(redisDb *db, robj *key, int flags); robj_roptr lookupKeyRead(redisDb *db, robj *key);
robj *lookupKeyRead(redisDb *db, robj *key);
robj *lookupKeyWrite(redisDb *db, robj *key); robj *lookupKeyWrite(redisDb *db, robj *key);
robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply); robj_roptr lookupKeyReadOrReply(client *c, robj *key, robj *reply);
robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply); robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply);
robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags); robj_roptr lookupKeyReadWithFlags(redisDb *db, robj *key, int flags);
robj *objectCommandLookup(client *c, robj *key); robj *objectCommandLookup(client *c, robj *key);
robj *objectCommandLookupOrReply(client *c, robj *key, robj *reply); robj *objectCommandLookupOrReply(client *c, robj *key, robj *reply);
void objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle, void objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
@ -2092,7 +2157,7 @@ unsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int coun
unsigned int countKeysInSlot(unsigned int hashslot); unsigned int countKeysInSlot(unsigned int hashslot);
unsigned int delKeysInSlot(unsigned int hashslot); unsigned int delKeysInSlot(unsigned int hashslot);
int verifyClusterConfigWithData(void); int verifyClusterConfigWithData(void);
void scanGenericCommand(client *c, robj *o, unsigned long cursor); void scanGenericCommand(client *c, robj_roptr o, unsigned long cursor);
int parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor); int parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor);
void slotToKeyAdd(robj *key); void slotToKeyAdd(robj *key);
void slotToKeyDel(robj *key); void slotToKeyDel(robj *key);
@ -2115,7 +2180,7 @@ int *xreadGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys)
/* Cluster */ /* Cluster */
void clusterInit(void); void clusterInit(void);
unsigned short crc16(const char *buf, int len); extern "C" unsigned short crc16(const char *buf, int len);
unsigned int keyHashSlot(char *key, int keylen); unsigned int keyHashSlot(char *key, int keylen);
void clusterCron(void); void clusterCron(void);
void clusterPropagatePublish(robj *channel, robj *message); void clusterPropagatePublish(robj *channel, robj *message);
@ -2174,9 +2239,9 @@ int dictSdsKeyCompare(void *privdata, const void *key1, const void *key2);
void dictSdsDestructor(void *privdata, void *val); void dictSdsDestructor(void *privdata, void *val);
/* Git SHA1 */ /* Git SHA1 */
char *redisGitSHA1(void); extern "C" char *redisGitSHA1(void);
char *redisGitDirty(void); extern "C" char *redisGitDirty(void);
uint64_t redisBuildId(void); extern "C" uint64_t redisBuildId(void);
/* Commands prototypes */ /* Commands prototypes */
void authCommand(client *c); void authCommand(client *c);
@ -2380,6 +2445,9 @@ int FBrokenLinkToMaster();
int FActiveMaster(client *c); int FActiveMaster(client *c);
struct redisMaster *MasterInfoFromClient(client *c); struct redisMaster *MasterInfoFromClient(client *c);
/* MVCC */
uint64_t getMvccTstamp();
#if defined(__GNUC__) #if defined(__GNUC__)
#ifndef __cplusplus #ifndef __cplusplus
void *calloc(size_t count, size_t size) __attribute__ ((deprecated)); void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
@ -2390,19 +2458,19 @@ void *realloc(void *ptr, size_t size) __attribute__ ((deprecated));
#endif #endif
/* Debugging stuff */ /* Debugging stuff */
void _serverAssertWithInfo(const client *c, const robj *o, const char *estr, const char *file, int line); void _serverAssertWithInfo(const client *c, robj_roptr o, const char *estr, const char *file, int line);
void _serverAssert(const char *estr, const char *file, int line); extern "C" void _serverAssert(const char *estr, const char *file, int line);
void _serverPanic(const char *file, int line, const char *msg, ...); extern "C" void _serverPanic(const char *file, int line, const char *msg, ...);
void bugReportStart(void); void bugReportStart(void);
void serverLogObjectDebugInfo(const robj *o); void serverLogObjectDebugInfo(robj_roptr o);
void sigsegvHandler(int sig, siginfo_t *info, void *secret); void sigsegvHandler(int sig, siginfo_t *info, void *secret);
sds genRedisInfoString(const char *section); sds genRedisInfoString(const char *section);
void enableWatchdog(int period); void enableWatchdog(int period);
void disableWatchdog(void); void disableWatchdog(void);
void watchdogScheduleSignal(int period); void watchdogScheduleSignal(int period);
void serverLogHexDump(int level, const char *descr, void *value, size_t len); void serverLogHexDump(int level, const char *descr, void *value, size_t len);
int memtest_preserving_test(unsigned long *m, size_t bytes, int passes); extern "C" int memtest_preserving_test(unsigned long *m, size_t bytes, int passes);
void mixDigest(unsigned char *digest, void *ptr, size_t len); void mixDigest(unsigned char *digest, const void *ptr, size_t len);
void xorDigest(unsigned char *digest, const void *ptr, size_t len); void xorDigest(unsigned char *digest, const void *ptr, size_t len);
int populateCommandTableParseFlags(struct redisCommand *c, const char *strflags); int populateCommandTableParseFlags(struct redisCommand *c, const char *strflags);
@ -2437,8 +2505,4 @@ inline int FCorrectThread(client *c)
#define redisDebugMark() \ #define redisDebugMark() \
printf("-- MARK %s:%d --\n", __FILE__, __LINE__) printf("-- MARK %s:%d --\n", __FILE__, __LINE__)
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -97,7 +97,7 @@ slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long dur
* function matches the one of the 'free' method of adlist.c. * function matches the one of the 'free' method of adlist.c.
* *
* This function will take care to release all the retained object. */ * This function will take care to release all the retained object. */
void slowlogFreeEntry(void *septr) { void slowlogFreeEntry(const void *septr) {
slowlogEntry *se = (slowlogEntry*)septr; slowlogEntry *se = (slowlogEntry*)septr;
int j; int j;

View File

@ -61,7 +61,8 @@ redisSortOperation *createSortOperation(int type, robj *pattern) {
robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst, int writeflag) { robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst, int writeflag) {
char *p, *f, *k; char *p, *f, *k;
sds spat, ssub; sds spat, ssub;
robj *keyobj, *fieldobj = NULL, *o; robj *keyobj, *fieldobj = NULL;
robj_roptr o;
int prefixlen, sublen, postfixlen, fieldlen; int prefixlen, sublen, postfixlen, fieldlen;
/* If the pattern is "#" return the substitution object itself in order /* If the pattern is "#" return the substitution object itself in order
@ -110,7 +111,7 @@ robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst, int writeflag)
o = lookupKeyRead(db,keyobj); o = lookupKeyRead(db,keyobj);
else else
o = lookupKeyWrite(db,keyobj); o = lookupKeyWrite(db,keyobj);
if (o == NULL) goto noobj; if (o == nullptr) goto noobj;
if (fieldobj) { if (fieldobj) {
if (o->type != OBJ_HASH) goto noobj; if (o->type != OBJ_HASH) goto noobj;
@ -127,7 +128,7 @@ robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst, int writeflag)
} }
decrRefCount(keyobj); decrRefCount(keyobj);
if (fieldobj) decrRefCount(fieldobj); if (fieldobj) decrRefCount(fieldobj);
return o; return o.unsafe_robjcast();
noobj: noobj:
decrRefCount(keyobj); decrRefCount(keyobj);
@ -271,7 +272,7 @@ void sortCommand(client *c) {
/* Lookup the key to sort. It must be of the right types */ /* Lookup the key to sort. It must be of the right types */
if (storekey) if (storekey)
sortval = lookupKeyRead(c->db,c->argv[1]); sortval = lookupKeyRead(c->db,c->argv[1]).unsafe_robjcast();
else else
sortval = lookupKeyWrite(c->db,c->argv[1]); sortval = lookupKeyWrite(c->db,c->argv[1]);
if (sortval && sortval->type != OBJ_SET && if (sortval && sortval->type != OBJ_SET &&

View File

@ -54,8 +54,8 @@ void hashTypeTryConversion(robj *o, robj **argv, int start, int end) {
/* Get the value from a ziplist encoded hash, identified by field. /* Get the value from a ziplist encoded hash, identified by field.
* Returns -1 when the field cannot be found. */ * Returns -1 when the field cannot be found. */
int hashTypeGetFromZiplist(robj *o, sds field, int hashTypeGetFromZiplist(robj_roptr o, const char *field,
unsigned char **vstr, const unsigned char **vstr,
unsigned int *vlen, unsigned int *vlen,
long long *vll) long long *vll)
{ {
@ -64,7 +64,7 @@ int hashTypeGetFromZiplist(robj *o, sds field,
serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST); serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);
zl = (unsigned char*)ptrFromObj(o); zl = (unsigned char*)(ptrFromObj(o));
fptr = ziplistIndex(zl, ZIPLIST_HEAD); fptr = ziplistIndex(zl, ZIPLIST_HEAD);
if (fptr != NULL) { if (fptr != NULL) {
fptr = ziplistFind(fptr, (unsigned char*)field, sdslen(field), 1); fptr = ziplistFind(fptr, (unsigned char*)field, sdslen(field), 1);
@ -76,7 +76,7 @@ int hashTypeGetFromZiplist(robj *o, sds field,
} }
if (vptr != NULL) { if (vptr != NULL) {
ret = ziplistGet(vptr, vstr, vlen, vll); ret = ziplistGet(vptr, (unsigned char**)vstr, vlen, vll);
serverAssert(ret); serverAssert(ret);
return 0; return 0;
} }
@ -87,7 +87,7 @@ int hashTypeGetFromZiplist(robj *o, sds field,
/* Get the value from a hash table encoded hash, identified by field. /* Get the value from a hash table encoded hash, identified by field.
* Returns NULL when the field cannot be found, otherwise the SDS value * Returns NULL when the field cannot be found, otherwise the SDS value
* is returned. */ * is returned. */
sds hashTypeGetFromHashTable(robj *o, sds field) { const char *hashTypeGetFromHashTable(robj_roptr o, const char *field) {
dictEntry *de; dictEntry *de;
serverAssert(o->encoding == OBJ_ENCODING_HT); serverAssert(o->encoding == OBJ_ENCODING_HT);
@ -106,15 +106,15 @@ sds hashTypeGetFromHashTable(robj *o, sds field) {
* If *vll is populated *vstr is set to NULL, so the caller * If *vll is populated *vstr is set to NULL, so the caller
* can always check the function return by checking the return value * can always check the function return by checking the return value
* for C_OK and checking if vll (or vstr) is NULL. */ * for C_OK and checking if vll (or vstr) is NULL. */
int hashTypeGetValue(robj *o, sds field, unsigned char **vstr, unsigned int *vlen, long long *vll) { int hashTypeGetValue(robj_roptr o, sds field, const unsigned char **vstr, unsigned int *vlen, long long *vll) {
if (o->encoding == OBJ_ENCODING_ZIPLIST) { if (o->encoding == OBJ_ENCODING_ZIPLIST) {
*vstr = NULL; *vstr = NULL;
if (hashTypeGetFromZiplist(o, field, vstr, vlen, vll) == 0) if (hashTypeGetFromZiplist(o, field, vstr, vlen, vll) == 0)
return C_OK; return C_OK;
} else if (o->encoding == OBJ_ENCODING_HT) { } else if (o->encoding == OBJ_ENCODING_HT) {
sds value; const char *value;
if ((value = hashTypeGetFromHashTable(o, field)) != NULL) { if ((value = hashTypeGetFromHashTable(o, field)) != NULL) {
*vstr = (unsigned char*) value; *vstr = (const unsigned char*) value;
*vlen = sdslen(value); *vlen = sdslen(value);
return C_OK; return C_OK;
} }
@ -128,8 +128,8 @@ int hashTypeGetValue(robj *o, sds field, unsigned char **vstr, unsigned int *vle
* interaction with the hash type outside t_hash.c. * interaction with the hash type outside t_hash.c.
* The function returns NULL if the field is not found in the hash. Otherwise * The function returns NULL if the field is not found in the hash. Otherwise
* a newly allocated string object with the value is returned. */ * a newly allocated string object with the value is returned. */
robj *hashTypeGetValueObject(robj *o, sds field) { robj *hashTypeGetValueObject(robj_roptr o, sds field) {
unsigned char *vstr; const unsigned char *vstr;
unsigned int vlen; unsigned int vlen;
long long vll; long long vll;
@ -141,17 +141,17 @@ robj *hashTypeGetValueObject(robj *o, sds field) {
/* Higher level function using hashTypeGet*() to return the length of the /* Higher level function using hashTypeGet*() to return the length of the
* object associated with the requested field, or 0 if the field does not * object associated with the requested field, or 0 if the field does not
* exist. */ * exist. */
size_t hashTypeGetValueLength(robj *o, sds field) { size_t hashTypeGetValueLength(robj_roptr o, const char *field) {
size_t len = 0; size_t len = 0;
if (o->encoding == OBJ_ENCODING_ZIPLIST) { if (o->encoding == OBJ_ENCODING_ZIPLIST) {
unsigned char *vstr = NULL; const unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX; unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX; long long vll = LLONG_MAX;
if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0)
len = vstr ? vlen : sdigits10(vll); len = vstr ? vlen : sdigits10(vll);
} else if (o->encoding == OBJ_ENCODING_HT) { } else if (o->encoding == OBJ_ENCODING_HT) {
sds aux; const char *aux;
if ((aux = hashTypeGetFromHashTable(o, field)) != NULL) if ((aux = hashTypeGetFromHashTable(o, field)) != NULL)
len = sdslen(aux); len = sdslen(aux);
@ -163,9 +163,9 @@ size_t hashTypeGetValueLength(robj *o, sds field) {
/* Test if the specified field exists in the given hash. Returns 1 if the field /* Test if the specified field exists in the given hash. Returns 1 if the field
* exists, and 0 when it doesn't. */ * exists, and 0 when it doesn't. */
int hashTypeExists(robj *o, sds field) { int hashTypeExists(robj_roptr o, const char *field) {
if (o->encoding == OBJ_ENCODING_ZIPLIST) { if (o->encoding == OBJ_ENCODING_ZIPLIST) {
unsigned char *vstr = NULL; const unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX; unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX; long long vll = LLONG_MAX;
@ -308,7 +308,7 @@ int hashTypeDelete(robj *o, sds field) {
} }
/* Return the number of elements in a hash. */ /* Return the number of elements in a hash. */
unsigned long hashTypeLength(const robj *o) { unsigned long hashTypeLength(robj_roptr o) {
unsigned long length = ULONG_MAX; unsigned long length = ULONG_MAX;
if (o->encoding == OBJ_ENCODING_ZIPLIST) { if (o->encoding == OBJ_ENCODING_ZIPLIST) {
@ -321,7 +321,7 @@ unsigned long hashTypeLength(const robj *o) {
return length; return length;
} }
hashTypeIterator *hashTypeInitIterator(robj *subject) { hashTypeIterator *hashTypeInitIterator(robj_roptr subject) {
hashTypeIterator *hi = (hashTypeIterator*)zmalloc(sizeof(hashTypeIterator), MALLOC_LOCAL); hashTypeIterator *hi = (hashTypeIterator*)zmalloc(sizeof(hashTypeIterator), MALLOC_LOCAL);
hi->subject = subject; hi->subject = subject;
hi->encoding = subject->encoding; hi->encoding = subject->encoding;
@ -560,7 +560,7 @@ void hincrbyCommand(client *c) {
long long value, incr, oldvalue; long long value, incr, oldvalue;
robj *o; robj *o;
sds newstr; sds newstr;
unsigned char *vstr; const unsigned char *vstr;
unsigned int vlen; unsigned int vlen;
if (getLongLongFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return; if (getLongLongFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;
@ -596,7 +596,7 @@ void hincrbyfloatCommand(client *c) {
long long ll; long long ll;
robj *o; robj *o;
sds newstr; sds newstr;
unsigned char *vstr; const unsigned char *vstr;
unsigned int vlen; unsigned int vlen;
if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return; if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;
@ -641,16 +641,16 @@ void hincrbyfloatCommand(client *c) {
decrRefCount(newobj); decrRefCount(newobj);
} }
static void addHashFieldToReply(client *c, robj *o, sds field) { static void addHashFieldToReply(client *c, robj_roptr o, sds field) {
int ret; int ret;
if (o == NULL) { if (o == nullptr) {
addReplyNull(c); addReplyNull(c);
return; return;
} }
if (o->encoding == OBJ_ENCODING_ZIPLIST) { if (o->encoding == OBJ_ENCODING_ZIPLIST) {
unsigned char *vstr = NULL; const unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX; unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX; long long vll = LLONG_MAX;
@ -666,7 +666,7 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
} }
} else if (o->encoding == OBJ_ENCODING_HT) { } else if (o->encoding == OBJ_ENCODING_HT) {
sds value = hashTypeGetFromHashTable(o, field); const char* value = hashTypeGetFromHashTable(o, field);
if (value == NULL) if (value == NULL)
addReplyNull(c); addReplyNull(c);
else else
@ -677,22 +677,22 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
} }
void hgetCommand(client *c) { void hgetCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == nullptr ||
checkType(c,o,OBJ_HASH)) return; checkType(c,o,OBJ_HASH)) return;
addHashFieldToReply(c, o, szFromObj(c->argv[2])); addHashFieldToReply(c, o, szFromObj(c->argv[2]));
} }
void hmgetCommand(client *c) { void hmgetCommand(client *c) {
robj *o; robj_roptr o;
int i; int i;
/* Don't abort when the key cannot be found. Non-existing keys are empty /* Don't abort when the key cannot be found. Non-existing keys are empty
* hashes, where HMGET should respond with a series of null bulks. */ * hashes, where HMGET should respond with a series of null bulks. */
o = lookupKeyRead(c->db, c->argv[1]); o = lookupKeyRead(c->db, c->argv[1]);
if (o != NULL && o->type != OBJ_HASH) { if (o != nullptr && o->type != OBJ_HASH) {
addReply(c, shared.wrongtypeerr); addReply(c, shared.wrongtypeerr);
return; return;
} }
@ -732,18 +732,18 @@ void hdelCommand(client *c) {
} }
void hlenCommand(client *c) { void hlenCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_HASH)) return; checkType(c,o,OBJ_HASH)) return;
addReplyLongLong(c,hashTypeLength(o)); addReplyLongLong(c,hashTypeLength(o));
} }
void hstrlenCommand(client *c) { void hstrlenCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_HASH)) return; checkType(c,o,OBJ_HASH)) return;
addReplyLongLong(c,hashTypeGetValueLength(o,szFromObj(c->argv[2]))); addReplyLongLong(c,hashTypeGetValueLength(o,szFromObj(c->argv[2])));
} }
@ -768,11 +768,11 @@ static void addHashIteratorCursorToReply(client *c, hashTypeIterator *hi, int wh
} }
void genericHgetallCommand(client *c, int flags) { void genericHgetallCommand(client *c, int flags) {
robj *o; robj_roptr o;
hashTypeIterator *hi; hashTypeIterator *hi;
int length, count = 0; int length, count = 0;
if ((o = lookupKeyReadOrReply(c,c->argv[1],(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == NULL if ((o = lookupKeyReadOrReply(c,c->argv[1],(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == nullptr
|| checkType(c,o,OBJ_HASH)) return; || checkType(c,o,OBJ_HASH)) return;
/* We return a map if the user requested keys and values, like in the /* We return a map if the user requested keys and values, like in the
@ -816,19 +816,19 @@ void hgetallCommand(client *c) {
} }
void hexistsCommand(client *c) { void hexistsCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_HASH)) return; checkType(c,o,OBJ_HASH)) return;
addReply(c, hashTypeExists(o,szFromObj(c->argv[2])) ? shared.cone : shared.czero); addReply(c, hashTypeExists(o,szFromObj(c->argv[2])) ? shared.cone : shared.czero);
} }
void hscanCommand(client *c) { void hscanCommand(client *c) {
robj *o; robj_roptr o;
unsigned long cursor; unsigned long cursor;
if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return; if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == nullptr ||
checkType(c,o,OBJ_HASH)) return; checkType(c,o,OBJ_HASH)) return;
scanGenericCommand(c,o,cursor); scanGenericCommand(c,o,cursor);
} }

View File

@ -71,16 +71,16 @@ robj *listTypePop(robj *subject, int where) {
return value; return value;
} }
unsigned long listTypeLength(const robj *subject) { unsigned long listTypeLength(robj_roptr subject) {
if (subject->encoding == OBJ_ENCODING_QUICKLIST) { if (subject->encoding == OBJ_ENCODING_QUICKLIST) {
return quicklistCount((quicklist*)ptrFromObj(subject)); return quicklistCount((const quicklist*)ptrFromObj(subject));
} else { } else {
serverPanic("Unknown list encoding"); serverPanic("Unknown list encoding");
} }
} }
/* Initialize an iterator at the specified index. */ /* Initialize an iterator at the specified index. */
listTypeIterator *listTypeInitIterator(robj *subject, long index, listTypeIterator *listTypeInitIterator(robj_roptr subject, long index,
unsigned char direction) { unsigned char direction) {
listTypeIterator *li = (listTypeIterator*)zmalloc(sizeof(listTypeIterator), MALLOC_LOCAL); listTypeIterator *li = (listTypeIterator*)zmalloc(sizeof(listTypeIterator), MALLOC_LOCAL);
li->subject = subject; li->subject = subject;
@ -306,14 +306,14 @@ void linsertCommand(client *c) {
} }
void llenCommand(client *c) { void llenCommand(client *c) {
robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.czero); robj_roptr o = lookupKeyReadOrReply(c,c->argv[1],shared.czero);
if (o == NULL || checkType(c,o,OBJ_LIST)) return; if (o == nullptr || checkType(c,o,OBJ_LIST)) return;
addReplyLongLong(c,listTypeLength(o)); addReplyLongLong(c,listTypeLength(o));
} }
void lindexCommand(client *c) { void lindexCommand(client *c) {
robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]); robj_roptr o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]);
if (o == NULL || checkType(c,o,OBJ_LIST)) return; if (o == nullptr || checkType(c,o,OBJ_LIST)) return;
long index; long index;
robj *value = NULL; robj *value = NULL;
@ -396,13 +396,13 @@ void rpopCommand(client *c) {
} }
void lrangeCommand(client *c) { void lrangeCommand(client *c) {
robj *o; robj_roptr o;
long start, end, llen, rangelen; long start, end, llen, rangelen;
if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) || if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||
(getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return; (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return;
if ((o = lookupKeyReadOrReply(c,c->argv[1],(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == NULL if ((o = lookupKeyReadOrReply(c,c->argv[1],(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == nullptr
|| checkType(c,o,OBJ_LIST)) return; || checkType(c,o,OBJ_LIST)) return;
llen = listTypeLength(o); llen = listTypeLength(o);

View File

@ -39,7 +39,7 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
/* Factory method to return a set that *can* hold "value". When the object has /* Factory method to return a set that *can* hold "value". When the object has
* an integer-encodable value, an intset will be returned. Otherwise a regular * an integer-encodable value, an intset will be returned. Otherwise a regular
* hash table. */ * hash table. */
robj *setTypeCreate(sds value) { robj *setTypeCreate(const char *value) {
if (isSdsRepresentableAsLongLong(value,NULL) == C_OK) if (isSdsRepresentableAsLongLong(value,NULL) == C_OK)
return createIntsetObject(); return createIntsetObject();
return createSetObject(); return createSetObject();
@ -49,11 +49,11 @@ robj *setTypeCreate(sds value) {
* *
* If the value was already member of the set, nothing is done and 0 is * If the value was already member of the set, nothing is done and 0 is
* returned, otherwise the new element is added and 1 is returned. */ * returned, otherwise the new element is added and 1 is returned. */
int setTypeAdd(robj *subject, sds value) { int setTypeAdd(robj *subject, const char *value) {
long long llval; long long llval;
if (subject->encoding == OBJ_ENCODING_HT) { if (subject->encoding == OBJ_ENCODING_HT) {
dict *ht = (dict*)subject->m_ptr; dict *ht = (dict*)subject->m_ptr;
dictEntry *de = dictAddRaw(ht,value,NULL); dictEntry *de = dictAddRaw(ht,(char*)value,NULL);
if (de) { if (de) {
dictSetKey(ht,de,sdsdup(value)); dictSetKey(ht,de,sdsdup(value));
dictSetVal(ht,de,NULL); dictSetVal(ht,de,NULL);
@ -85,7 +85,7 @@ int setTypeAdd(robj *subject, sds value) {
return 0; return 0;
} }
int setTypeRemove(robj *setobj, sds value) { int setTypeRemove(robj *setobj, const char *value) {
long long llval; long long llval;
if (setobj->encoding == OBJ_ENCODING_HT) { if (setobj->encoding == OBJ_ENCODING_HT) {
if (dictDelete((dict*)setobj->m_ptr,value) == DICT_OK) { if (dictDelete((dict*)setobj->m_ptr,value) == DICT_OK) {
@ -104,7 +104,7 @@ int setTypeRemove(robj *setobj, sds value) {
return 0; return 0;
} }
int setTypeIsMember(robj *subject, sds value) { int setTypeIsMember(robj_roptr subject, const char *value) {
long long llval; long long llval;
if (subject->encoding == OBJ_ENCODING_HT) { if (subject->encoding == OBJ_ENCODING_HT) {
return dictFind((dict*)subject->m_ptr,value) != NULL; return dictFind((dict*)subject->m_ptr,value) != NULL;
@ -118,7 +118,7 @@ int setTypeIsMember(robj *subject, sds value) {
return 0; return 0;
} }
setTypeIterator *setTypeInitIterator(robj *subject) { setTypeIterator *setTypeInitIterator(robj_roptr subject) {
setTypeIterator *si = (setTypeIterator*)zmalloc(sizeof(setTypeIterator), MALLOC_LOCAL); setTypeIterator *si = (setTypeIterator*)zmalloc(sizeof(setTypeIterator), MALLOC_LOCAL);
si->subject = subject; si->subject = subject;
si->encoding = subject->encoding; si->encoding = subject->encoding;
@ -151,7 +151,7 @@ void setTypeReleaseIterator(setTypeIterator *si) {
* used field with values which are easy to trap if misused. * used field with values which are easy to trap if misused.
* *
* When there are no longer elements -1 is returned. */ * When there are no longer elements -1 is returned. */
int setTypeNext(setTypeIterator *si, sds *sdsele, int64_t *llele) { int setTypeNext(setTypeIterator *si, const char **sdsele, int64_t *llele) {
if (si->encoding == OBJ_ENCODING_HT) { if (si->encoding == OBJ_ENCODING_HT) {
dictEntry *de = dictNext(si->di); dictEntry *de = dictNext(si->di);
if (de == NULL) return -1; if (de == NULL) return -1;
@ -176,7 +176,7 @@ int setTypeNext(setTypeIterator *si, sds *sdsele, int64_t *llele) {
* an issue. */ * an issue. */
sds setTypeNextObject(setTypeIterator *si) { sds setTypeNextObject(setTypeIterator *si) {
int64_t intele; int64_t intele;
sds sdsele; const char *sdsele;
int encoding; int encoding;
encoding = setTypeNext(si,&sdsele,&intele); encoding = setTypeNext(si,&sdsele,&intele);
@ -219,7 +219,12 @@ int setTypeRandomElement(robj *setobj, sds *sdsele, int64_t *llele) {
return setobj->encoding; return setobj->encoding;
} }
unsigned long setTypeSize(const robj *subject) { int setTypeRandomElement(robj_roptr setobj, const char **sdsele, const int64_t *llele)
{
return setTypeRandomElement(setobj.unsafe_robjcast(), (sds*)sdsele, const_cast<int64_t*>(llele));
}
unsigned long setTypeSize(robj_roptr subject) {
if (subject->encoding == OBJ_ENCODING_HT) { if (subject->encoding == OBJ_ENCODING_HT) {
return dictSize((const dict*)subject->m_ptr); return dictSize((const dict*)subject->m_ptr);
} else if (subject->encoding == OBJ_ENCODING_INTSET) { } else if (subject->encoding == OBJ_ENCODING_INTSET) {
@ -240,7 +245,7 @@ void setTypeConvert(robj *setobj, int enc) {
if (enc == OBJ_ENCODING_HT) { if (enc == OBJ_ENCODING_HT) {
int64_t intele; int64_t intele;
dict *d = dictCreate(&setDictType,NULL); dict *d = dictCreate(&setDictType,NULL);
sds element; const char *element;
/* Presize the dict to avoid rehashing */ /* Presize the dict to avoid rehashing */
dictExpand(d,intsetLen((intset*)setobj->m_ptr)); dictExpand(d,intsetLen((intset*)setobj->m_ptr));
@ -248,8 +253,8 @@ void setTypeConvert(robj *setobj, int enc) {
/* To add the elements we extract integers and create redis objects */ /* To add the elements we extract integers and create redis objects */
si = setTypeInitIterator(setobj); si = setTypeInitIterator(setobj);
while (setTypeNext(si,&element,&intele) != -1) { while (setTypeNext(si,&element,&intele) != -1) {
element = sdsfromlonglong(intele); sds elementNew = sdsfromlonglong(intele);
serverAssert(dictAdd(d,element,NULL) == DICT_OK); serverAssert(dictAdd(d,elementNew,NULL) == DICT_OK);
} }
setTypeReleaseIterator(si); setTypeReleaseIterator(si);
@ -371,9 +376,9 @@ void smoveCommand(client *c) {
} }
void sismemberCommand(client *c) { void sismemberCommand(client *c) {
robj *set; robj_roptr set;
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,set,OBJ_SET)) return; checkType(c,set,OBJ_SET)) return;
if (setTypeIsMember(set,szFromObj(c->argv[2]))) if (setTypeIsMember(set,szFromObj(c->argv[2])))
@ -383,9 +388,9 @@ void sismemberCommand(client *c) {
} }
void scardCommand(client *c) { void scardCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_SET)) return; checkType(c,o,OBJ_SET)) return;
addReplyLongLong(c,setTypeSize(o)); addReplyLongLong(c,setTypeSize(o));
@ -458,7 +463,7 @@ void spopWithCountCommand(client *c) {
addReplySetLen(c,count); addReplySetLen(c,count);
/* Common iteration vars. */ /* Common iteration vars. */
sds sdsele; const char *sdsele;
robj *objele; robj *objele;
int encoding; int encoding;
int64_t llele; int64_t llele;
@ -615,8 +620,8 @@ void srandmemberWithCountCommand(client *c) {
long l; long l;
unsigned long count, size; unsigned long count, size;
int uniq = 1; int uniq = 1;
robj *set; robj_roptr set;
sds ele; const char *ele;
int64_t llele; int64_t llele;
int encoding; int encoding;
@ -633,7 +638,7 @@ void srandmemberWithCountCommand(client *c) {
} }
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]))
== NULL || checkType(c,set,OBJ_SET)) return; == nullptr || checkType(c,set,OBJ_SET)) return;
size = setTypeSize(set); size = setTypeSize(set);
/* If count is zero, serve it ASAP to avoid special cases later. */ /* If count is zero, serve it ASAP to avoid special cases later. */
@ -747,8 +752,8 @@ void srandmemberWithCountCommand(client *c) {
} }
void srandmemberCommand(client *c) { void srandmemberCommand(client *c) {
robj *set; robj_roptr set;
sds ele; const char *ele;
int64_t llele; int64_t llele;
int encoding; int encoding;
@ -761,7 +766,7 @@ void srandmemberCommand(client *c) {
} }
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]))
== NULL || checkType(c,set,OBJ_SET)) return; == nullptr || checkType(c,set,OBJ_SET)) return;
encoding = setTypeRandomElement(set,&ele,&llele); encoding = setTypeRandomElement(set,&ele,&llele);
if (encoding == OBJ_ENCODING_INTSET) { if (encoding == OBJ_ENCODING_INTSET) {
@ -794,7 +799,7 @@ void sinterGenericCommand(client *c, robj **setkeys,
robj **sets = (robj**)zmalloc(sizeof(robj*)*setnum, MALLOC_SHARED); robj **sets = (robj**)zmalloc(sizeof(robj*)*setnum, MALLOC_SHARED);
setTypeIterator *si; setTypeIterator *si;
robj *dstset = NULL; robj *dstset = NULL;
sds elesds; const char *elesds;
int64_t intobj; int64_t intobj;
void *replylen = NULL; void *replylen = NULL;
unsigned long j, cardinality = 0; unsigned long j, cardinality = 0;
@ -803,7 +808,7 @@ void sinterGenericCommand(client *c, robj **setkeys,
for (j = 0; j < setnum; j++) { for (j = 0; j < setnum; j++) {
robj *setobj = dstkey ? robj *setobj = dstkey ?
lookupKeyWrite(c->db,setkeys[j]) : lookupKeyWrite(c->db,setkeys[j]) :
lookupKeyRead(c->db,setkeys[j]); lookupKeyRead(c->db,setkeys[j]).unsafe_robjcast();
if (!setobj) { if (!setobj) {
zfree(sets); zfree(sets);
if (dstkey) { if (dstkey) {
@ -943,7 +948,7 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
for (j = 0; j < setnum; j++) { for (j = 0; j < setnum; j++) {
robj *setobj = dstkey ? robj *setobj = dstkey ?
lookupKeyWrite(c->db,setkeys[j]) : lookupKeyWrite(c->db,setkeys[j]) :
lookupKeyRead(c->db,setkeys[j]); lookupKeyRead(c->db,setkeys[j]).unsafe_robjcast();
if (!setobj) { if (!setobj) {
sets[j] = NULL; sets[j] = NULL;
continue; continue;
@ -1109,11 +1114,11 @@ void sdiffstoreCommand(client *c) {
} }
void sscanCommand(client *c) { void sscanCommand(client *c) {
robj *set; robj_roptr set;
unsigned long cursor; unsigned long cursor;
if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return; if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return;
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL || if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == nullptr ||
checkType(c,set,OBJ_SET)) return; checkType(c,set,OBJ_SET)) return;
scanGenericCommand(c,set,cursor); scanGenericCommand(c,set,cursor);
} }

View File

@ -1266,7 +1266,7 @@ void xaddCommand(client *c) {
/* XRANGE/XREVRANGE actual implementation. */ /* XRANGE/XREVRANGE actual implementation. */
void xrangeGenericCommand(client *c, int rev) { void xrangeGenericCommand(client *c, int rev) {
robj *o; robj_roptr o;
stream *s; stream *s;
streamID startid, endid; streamID startid, endid;
long long count = -1; long long count = -1;
@ -1293,7 +1293,7 @@ void xrangeGenericCommand(client *c, int rev) {
} }
/* Return the specified range to the user. */ /* Return the specified range to the user. */
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyarray)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyarray)) == nullptr ||
checkType(c,o,OBJ_STREAM)) return; checkType(c,o,OBJ_STREAM)) return;
s = (stream*)ptrFromObj(o); s = (stream*)ptrFromObj(o);
@ -1318,8 +1318,8 @@ void xrevrangeCommand(client *c) {
/* XLEN */ /* XLEN */
void xlenCommand(client *c) { void xlenCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr
|| checkType(c,o,OBJ_STREAM)) return; || checkType(c,o,OBJ_STREAM)) return;
stream *s = (stream*)ptrFromObj(o); stream *s = (stream*)ptrFromObj(o);
addReplyLongLong(c,s->length); addReplyLongLong(c,s->length);
@ -1419,14 +1419,14 @@ void xreadCommand(client *c) {
* starting from now. */ * starting from now. */
int id_idx = i - streams_arg - streams_count; int id_idx = i - streams_arg - streams_count;
robj *key = c->argv[i-streams_count]; robj *key = c->argv[i-streams_count];
robj *o = lookupKeyRead(c->db,key); robj_roptr o = lookupKeyRead(c->db,key);
if (o && checkType(c,o,OBJ_STREAM)) goto cleanup; if (o && checkType(c,o,OBJ_STREAM)) goto cleanup;
streamCG *group = NULL; streamCG *group = NULL;
/* If a group was specified, than we need to be sure that the /* If a group was specified, than we need to be sure that the
* key and group actually exist. */ * key and group actually exist. */
if (groupname) { if (groupname) {
if (o == NULL || if (o == nullptr ||
(group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(groupname))) == NULL) (group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(groupname))) == NULL)
{ {
addReplyErrorFormat(c, "-NOGROUP No such key '%s' or consumer " addReplyErrorFormat(c, "-NOGROUP No such key '%s' or consumer "
@ -1475,8 +1475,8 @@ void xreadCommand(client *c) {
/* Try to serve the client synchronously. */ /* Try to serve the client synchronously. */
for (int i = 0; i < streams_count; i++) { for (int i = 0; i < streams_count; i++) {
robj *o = lookupKeyRead(c->db,c->argv[streams_arg+i]); robj_roptr o = lookupKeyRead(c->db,c->argv[streams_arg+i]);
if (o == NULL) continue; if (o == nullptr) continue;
stream *s = (stream*)ptrFromObj(o); stream *s = (stream*)ptrFromObj(o);
streamID *gt = ids+i; /* ID must be greater than this. */ streamID *gt = ids+i; /* ID must be greater than this. */
int serve_synchronously = 0; int serve_synchronously = 0;
@ -1887,14 +1887,14 @@ void xsetidCommand(client *c) {
*/ */
void xackCommand(client *c) { void xackCommand(client *c) {
streamCG *group = NULL; streamCG *group = NULL;
robj *o = lookupKeyRead(c->db,c->argv[1]); robj_roptr o = lookupKeyRead(c->db,c->argv[1]);
if (o) { if (o) {
if (checkType(c,o,OBJ_STREAM)) return; /* Type error. */ if (checkType(c,o,OBJ_STREAM)) return; /* Type error. */
group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(c->argv[2])); group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(c->argv[2]));
} }
/* No key or group? Nothing to ack. */ /* No key or group? Nothing to ack. */
if (o == NULL || group == NULL) { if (o == nullptr || group == NULL) {
addReply(c,shared.czero); addReply(c,shared.czero);
return; return;
} }
@ -1958,11 +1958,11 @@ void xpendingCommand(client *c) {
} }
/* Lookup the key and the group inside the stream. */ /* Lookup the key and the group inside the stream. */
robj *o = lookupKeyRead(c->db,c->argv[1]); robj_roptr o = lookupKeyRead(c->db,c->argv[1]);
streamCG *group; streamCG *group;
if (o && checkType(c,o,OBJ_STREAM)) return; if (o && checkType(c,o,OBJ_STREAM)) return;
if (o == NULL || if (o == nullptr ||
(group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(groupname))) == NULL) (group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(groupname))) == NULL)
{ {
addReplyErrorFormat(c, "-NOGROUP No such key '%s' or consumer " addReplyErrorFormat(c, "-NOGROUP No such key '%s' or consumer "
@ -2137,7 +2137,7 @@ void xpendingCommand(client *c) {
* what messages it is now in charge of. */ * what messages it is now in charge of. */
void xclaimCommand(client *c) { void xclaimCommand(client *c) {
streamCG *group = NULL; streamCG *group = NULL;
robj *o = lookupKeyRead(c->db,c->argv[1]); robj_roptr o = lookupKeyRead(c->db,c->argv[1]);
long long minidle; /* Minimum idle time argument. */ long long minidle; /* Minimum idle time argument. */
long long retrycount = -1; /* -1 means RETRYCOUNT option not given. */ long long retrycount = -1; /* -1 means RETRYCOUNT option not given. */
mstime_t deliverytime = -1; /* -1 means IDLE/TIME options not given. */ mstime_t deliverytime = -1; /* -1 means IDLE/TIME options not given. */
@ -2151,7 +2151,7 @@ void xclaimCommand(client *c) {
/* No key or group? Send an error given that the group creation /* No key or group? Send an error given that the group creation
* is mandatory. */ * is mandatory. */
if (o == NULL || group == NULL) { if (o == nullptr || group == NULL) {
addReplyErrorFormat(c,"-NOGROUP No such key '%s' or " addReplyErrorFormat(c,"-NOGROUP No such key '%s' or "
"consumer group '%s'", (char*)ptrFromObj(c->argv[1]), "consumer group '%s'", (char*)ptrFromObj(c->argv[1]),
(char*)ptrFromObj(c->argv[2])); (char*)ptrFromObj(c->argv[2]));

View File

@ -155,9 +155,9 @@ void psetexCommand(client *c) {
} }
int getGenericCommand(client *c) { int getGenericCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL) if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == nullptr)
return C_OK; return C_OK;
if (o->type != OBJ_STRING) { if (o->type != OBJ_STRING) {
@ -242,23 +242,24 @@ void setrangeCommand(client *c) {
} }
void getrangeCommand(client *c) { void getrangeCommand(client *c) {
robj *o; robj_roptr o;
long long start, end; long long start, end;
char *str, llbuf[32]; const char *str;
char llbuf[32];
size_t strlen; size_t strlen;
if (getLongLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK) if (getLongLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK)
return; return;
if (getLongLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK) if (getLongLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)
return; return;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptybulk)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptybulk)) == nullptr ||
checkType(c,o,OBJ_STRING)) return; checkType(c,o,OBJ_STRING)) return;
if (o->encoding == OBJ_ENCODING_INT) { if (o->encoding == OBJ_ENCODING_INT) {
str = llbuf; str = llbuf;
strlen = ll2string(llbuf,sizeof(llbuf),(long)ptrFromObj(o)); strlen = ll2string(llbuf,sizeof(llbuf),(long)ptrFromObj(o));
} else { } else {
str = (char*)ptrFromObj(o); str = szFromObj(o);
strlen = sdslen(str); strlen = sdslen(str);
} }
@ -287,8 +288,8 @@ void mgetCommand(client *c) {
addReplyArrayLen(c,c->argc-1); addReplyArrayLen(c,c->argc-1);
for (j = 1; j < c->argc; j++) { for (j = 1; j < c->argc; j++) {
robj *o = lookupKeyRead(c->db,c->argv[j]); robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
if (o == NULL) { if (o == nullptr) {
addReplyNull(c); addReplyNull(c);
} else { } else {
if (o->type != OBJ_STRING) { if (o->type != OBJ_STRING) {
@ -464,8 +465,8 @@ void appendCommand(client *c) {
} }
void strlenCommand(client *c) { void strlenCommand(client *c) {
robj *o; robj_roptr o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
checkType(c,o,OBJ_STRING)) return; checkType(c,o,OBJ_STRING)) return;
addReplyLongLong(c,stringObjectLen(o)); addReplyLongLong(c,stringObjectLen(o));
} }

View File

@ -777,7 +777,7 @@ int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int cl
return cmp; return cmp;
} }
unsigned int zzlLength(unsigned char *zl) { unsigned int zzlLength(const unsigned char *zl) {
return ziplistLen(zl)/2; return ziplistLen(zl)/2;
} }
@ -1153,10 +1153,10 @@ unsigned char *zzlDeleteRangeByRank(unsigned char *zl, unsigned int start, unsig
* Common sorted set API * Common sorted set API
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
unsigned long zsetLength(const robj *zobj) { unsigned long zsetLength(robj_roptr zobj) {
unsigned long length = 0; unsigned long length = 0;
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) { if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
length = zzlLength((unsigned char*)zobj->m_ptr); length = zzlLength((const unsigned char*)zobj->m_ptr);
} else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) { } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {
length = ((const zset*)zobj->m_ptr)->zsl->length; length = ((const zset*)zobj->m_ptr)->zsl->length;
} else { } else {
@ -1252,7 +1252,7 @@ void zsetConvertToZiplistIfNeeded(robj *zobj, size_t maxelelen) {
* storing it into *score. If the element does not exist C_ERR is returned * storing it into *score. If the element does not exist C_ERR is returned
* otherwise C_OK is returned and *score is correctly populated. * otherwise C_OK is returned and *score is correctly populated.
* If 'zobj' or 'member' is NULL, C_ERR is returned. */ * If 'zobj' or 'member' is NULL, C_ERR is returned. */
int zsetScore(robj *zobj, sds member, double *score) { int zsetScore(robj_roptr zobj, sds member, double *score) {
if (!zobj || !member) return C_ERR; if (!zobj || !member) return C_ERR;
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) { if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
@ -1470,7 +1470,7 @@ int zsetDel(robj *zobj, sds ele) {
* the one with the lowest score. Otherwise if 'reverse' is non-zero * the one with the lowest score. Otherwise if 'reverse' is non-zero
* the rank is computed considering as element with rank 0 the one with * the rank is computed considering as element with rank 0 the one with
* the highest score. */ * the highest score. */
long zsetRank(robj *zobj, sds ele, int reverse) { long zsetRank(robj_roptr zobj, sds ele, int reverse) {
unsigned long llen; unsigned long llen;
unsigned long rank; unsigned long rank;
@ -2410,7 +2410,7 @@ void zinterstoreCommand(client *c) {
void zrangeGenericCommand(client *c, int reverse) { void zrangeGenericCommand(client *c, int reverse) {
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
int withscores = 0; int withscores = 0;
long start; long start;
long end; long end;
@ -2427,7 +2427,7 @@ void zrangeGenericCommand(client *c, int reverse) {
return; return;
} }
if ((zobj = lookupKeyReadOrReply(c,key,(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == NULL if ((zobj = lookupKeyReadOrReply(c,key,(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == nullptr
|| checkType(c,zobj,OBJ_ZSET)) return; || checkType(c,zobj,OBJ_ZSET)) return;
/* Sanitize indexes. */ /* Sanitize indexes. */
@ -2527,7 +2527,7 @@ void zrevrangeCommand(client *c) {
void genericZrangebyscoreCommand(client *c, int reverse) { void genericZrangebyscoreCommand(client *c, int reverse) {
zrangespec range; zrangespec range;
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
long offset = 0, limit = -1; long offset = 0, limit = -1;
int withscores = 0; int withscores = 0;
unsigned long rangelen = 0; unsigned long rangelen = 0;
@ -2575,7 +2575,7 @@ void genericZrangebyscoreCommand(client *c, int reverse) {
} }
/* Ok, lookup the key and get the range */ /* Ok, lookup the key and get the range */
if ((zobj = lookupKeyReadOrReply(c,key,(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == NULL || if ((zobj = lookupKeyReadOrReply(c,key,(c->resp < 3) ? shared.emptyarray : shared.null[c->resp])) == nullptr ||
checkType(c,zobj,OBJ_ZSET)) return; checkType(c,zobj,OBJ_ZSET)) return;
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) { if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
@ -2719,7 +2719,7 @@ void zrevrangebyscoreCommand(client *c) {
void zcountCommand(client *c) { void zcountCommand(client *c) {
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
zrangespec range; zrangespec range;
unsigned long count = 0; unsigned long count = 0;
@ -2730,7 +2730,7 @@ void zcountCommand(client *c) {
} }
/* Lookup the sorted set */ /* Lookup the sorted set */
if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL || if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == nullptr ||
checkType(c, zobj, OBJ_ZSET)) return; checkType(c, zobj, OBJ_ZSET)) return;
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) { if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
@ -2796,7 +2796,7 @@ void zcountCommand(client *c) {
void zlexcountCommand(client *c) { void zlexcountCommand(client *c) {
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
zlexrangespec range; zlexrangespec range;
unsigned long count = 0; unsigned long count = 0;
@ -2807,7 +2807,7 @@ void zlexcountCommand(client *c) {
} }
/* Lookup the sorted set */ /* Lookup the sorted set */
if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL || if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == nullptr ||
checkType(c, zobj, OBJ_ZSET)) checkType(c, zobj, OBJ_ZSET))
{ {
zslFreeLexRange(&range); zslFreeLexRange(&range);
@ -2877,7 +2877,7 @@ void zlexcountCommand(client *c) {
void genericZrangebylexCommand(client *c, int reverse) { void genericZrangebylexCommand(client *c, int reverse) {
zlexrangespec range; zlexrangespec range;
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
long offset = 0, limit = -1; long offset = 0, limit = -1;
unsigned long rangelen = 0; unsigned long rangelen = 0;
void *replylen = NULL; void *replylen = NULL;
@ -2920,7 +2920,7 @@ void genericZrangebylexCommand(client *c, int reverse) {
} }
/* Ok, lookup the key and get the range */ /* Ok, lookup the key and get the range */
if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == NULL || if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == nullptr ||
checkType(c,zobj,OBJ_ZSET)) checkType(c,zobj,OBJ_ZSET))
{ {
zslFreeLexRange(&range); zslFreeLexRange(&range);
@ -3063,9 +3063,9 @@ void zrevrangebylexCommand(client *c) {
void zcardCommand(client *c) { void zcardCommand(client *c) {
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
if ((zobj = lookupKeyReadOrReply(c,key,shared.czero)) == NULL || if ((zobj = lookupKeyReadOrReply(c,key,shared.czero)) == nullptr ||
checkType(c,zobj,OBJ_ZSET)) return; checkType(c,zobj,OBJ_ZSET)) return;
addReplyLongLong(c,zsetLength(zobj)); addReplyLongLong(c,zsetLength(zobj));
@ -3073,10 +3073,10 @@ void zcardCommand(client *c) {
void zscoreCommand(client *c) { void zscoreCommand(client *c) {
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *zobj; robj_roptr zobj;
double score; double score;
if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == NULL || if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == nullptr ||
checkType(c,zobj,OBJ_ZSET)) return; checkType(c,zobj,OBJ_ZSET)) return;
if (zsetScore(zobj,szFromObj(c->argv[2]),&score) == C_ERR) { if (zsetScore(zobj,szFromObj(c->argv[2]),&score) == C_ERR) {
@ -3089,10 +3089,10 @@ void zscoreCommand(client *c) {
void zrankGenericCommand(client *c, int reverse) { void zrankGenericCommand(client *c, int reverse) {
robj *key = c->argv[1]; robj *key = c->argv[1];
robj *ele = c->argv[2]; robj *ele = c->argv[2];
robj *zobj; robj_roptr zobj;
long rank; long rank;
if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == NULL || if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == nullptr ||
checkType(c,zobj,OBJ_ZSET)) return; checkType(c,zobj,OBJ_ZSET)) return;
serverAssertWithInfo(c,ele,sdsEncodedObject(ele)); serverAssertWithInfo(c,ele,sdsEncodedObject(ele));
@ -3113,11 +3113,11 @@ void zrevrankCommand(client *c) {
} }
void zscanCommand(client *c) { void zscanCommand(client *c) {
robj *o; robj_roptr o;
unsigned long cursor; unsigned long cursor;
if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return; if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL || if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == nullptr ||
checkType(c,o,OBJ_ZSET)) return; checkType(c,o,OBJ_ZSET)) return;
scanGenericCommand(c,o,cursor); scanGenericCommand(c,o,cursor);
} }

View File

@ -468,7 +468,7 @@ int zipPrevLenByteDiff(unsigned char *p, unsigned int len) {
} }
/* Return the total number of bytes used by the entry pointed to by 'p'. */ /* Return the total number of bytes used by the entry pointed to by 'p'. */
unsigned int zipRawEntryLength(unsigned char *p) { unsigned int zipRawEntryLength(const unsigned char *p) {
unsigned int prevlensize, encoding, lensize, len; unsigned int prevlensize, encoding, lensize, len;
ZIP_DECODE_PREVLENSIZE(p, prevlensize); ZIP_DECODE_PREVLENSIZE(p, prevlensize);
ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len); ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len);
@ -1165,12 +1165,12 @@ unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int v
} }
/* Return length of ziplist. */ /* Return length of ziplist. */
unsigned int ziplistLen(unsigned char *zl) { unsigned int ziplistLen(const unsigned char *zl) {
unsigned int len = 0; unsigned int len = 0;
if (intrev16ifbe(ZIPLIST_LENGTH(zl)) < UINT16_MAX) { if (intrev16ifbe(ZIPLIST_LENGTH(zl)) < UINT16_MAX) {
len = intrev16ifbe(ZIPLIST_LENGTH(zl)); len = intrev16ifbe(ZIPLIST_LENGTH(zl));
} else { } else {
unsigned char *p = zl+ZIPLIST_HEADER_SIZE; const unsigned char *p = zl+ZIPLIST_HEADER_SIZE;
while (*p != ZIP_END) { while (*p != ZIP_END) {
p += zipRawEntryLength(p); p += zipRawEntryLength(p);
len++; len++;

View File

@ -50,7 +50,7 @@ unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p);
unsigned char *ziplistDeleteRange(unsigned char *zl, int index, unsigned int num); unsigned char *ziplistDeleteRange(unsigned char *zl, int index, unsigned int num);
unsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int slen); unsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int slen);
unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip); unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip);
unsigned int ziplistLen(unsigned char *zl); unsigned int ziplistLen(const unsigned char *zl);
size_t ziplistBlobLen(unsigned char *zl); size_t ziplistBlobLen(unsigned char *zl);
void ziplistRepr(unsigned char *zl); void ziplistRepr(unsigned char *zl);

View File

@ -205,7 +205,7 @@ size_t zmalloc_usable(void *ptr) {
} }
#endif #endif
void zfree(void *ptr) { void zfree(const void *ptr) {
#ifndef HAVE_MALLOC_SIZE #ifndef HAVE_MALLOC_SIZE
void *realptr; void *realptr;
size_t oldsize; size_t oldsize;
@ -213,8 +213,8 @@ void zfree(void *ptr) {
if (ptr == NULL) return; if (ptr == NULL) return;
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_free(zmalloc_size(ptr)); update_zmalloc_stat_free(zmalloc_size((void*)ptr));
free(ptr); free((void*)ptr);
#else #else
realptr = (char*)ptr-PREFIX_SIZE; realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr); oldsize = *((size_t*)realptr);

View File

@ -89,7 +89,7 @@ extern "C" {
void *zmalloc(size_t size, enum MALLOC_CLASS mclass); void *zmalloc(size_t size, enum MALLOC_CLASS mclass);
void *zcalloc(size_t size, enum MALLOC_CLASS mclass); void *zcalloc(size_t size, enum MALLOC_CLASS mclass);
void *zrealloc(void *ptr, size_t size, enum MALLOC_CLASS mclass); void *zrealloc(void *ptr, size_t size, enum MALLOC_CLASS mclass);
void zfree(void *ptr); void zfree(const void *ptr);
char *zstrdup(const char *s); char *zstrdup(const char *s);
size_t zmalloc_used_memory(void); size_t zmalloc_used_memory(void);
void zmalloc_set_oom_handler(void (*oom_handler)(size_t)); void zmalloc_set_oom_handler(void (*oom_handler)(size_t));