Start of MVCC support (and more C++)
Former-commit-id: c4621a5ed2a7d8ca5034f2fbe8b71550f290ea64
This commit is contained in:
parent
98c30dfac1
commit
0e10e4f6f5
@ -21,7 +21,7 @@ NODEPS:=clean distclean
|
||||
|
||||
# Default settings
|
||||
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 FreeBSD,$(uname_S)))
|
||||
STD+=-Wno-c11-extensions
|
||||
|
@ -161,7 +161,7 @@ int ACLListMatchSds(void *a, void *b) {
|
||||
}
|
||||
|
||||
/* Method to free list elements from ACL users password/ptterns lists. */
|
||||
void ACLListFreeSds(void *item) {
|
||||
void ACLListFreeSds(const void *item) {
|
||||
sdsfree((sds)item);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ typedef struct list {
|
||||
listNode *head;
|
||||
listNode *tail;
|
||||
void *(*dup)(void *ptr);
|
||||
void (*free)(void *ptr);
|
||||
void (*free)(const void *ptr);
|
||||
int (*match)(void *ptr, void *key);
|
||||
unsigned long len;
|
||||
} list;
|
||||
|
@ -37,7 +37,7 @@
|
||||
/* Count number of bits set in the binary array pointed by 's' and long
|
||||
* 'count' bytes. The implementation of this function is required to
|
||||
* 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;
|
||||
unsigned char *p = (unsigned char*)s;
|
||||
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
|
||||
* 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. */
|
||||
long redisBitpos(void *s, unsigned long count, int bit) {
|
||||
long redisBitpos(const void *s, unsigned long count, int bit) {
|
||||
unsigned long *l;
|
||||
unsigned char *c;
|
||||
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
|
||||
* 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);
|
||||
unsigned char *p = NULL;
|
||||
const unsigned char *p = NULL;
|
||||
|
||||
/* Set the 'p' pointer to the string, that can be just a stack allocated
|
||||
* array if our string was integer encoded. */
|
||||
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));
|
||||
} else if (o) {
|
||||
p = (unsigned char*) ptrFromObj(o);
|
||||
p = (const unsigned char*) ptrFromObj(o);
|
||||
if (len) *len = sdslen(szFromObj(o));
|
||||
} else {
|
||||
if (len) *len = 0;
|
||||
@ -562,7 +562,7 @@ void setbitCommand(client *c) {
|
||||
|
||||
/* GETBIT key offset */
|
||||
void getbitCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
char llbuf[32];
|
||||
size_t bitoffset;
|
||||
size_t byte, bit;
|
||||
@ -571,7 +571,7 @@ void getbitCommand(client *c) {
|
||||
if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)
|
||||
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;
|
||||
|
||||
byte = bitoffset >> 3;
|
||||
@ -590,9 +590,10 @@ void getbitCommand(client *c) {
|
||||
/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */
|
||||
void bitopCommand(client *c) {
|
||||
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;
|
||||
robj **objects; /* Array of source objects. */
|
||||
robj_roptr *objects; /* Array of source objects. */
|
||||
unsigned char **src; /* Array of source strings pointers. */
|
||||
unsigned long *len, maxlen = 0; /* Array of length of src strings,
|
||||
and max len. */
|
||||
@ -623,12 +624,12 @@ void bitopCommand(client *c) {
|
||||
numkeys = c->argc - 3;
|
||||
src = (unsigned char**)zmalloc(sizeof(unsigned char*) * 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++) {
|
||||
o = lookupKeyRead(c->db,c->argv[j+3]);
|
||||
/* Handle non-existing keys as empty strings. */
|
||||
if (o == NULL) {
|
||||
objects[j] = NULL;
|
||||
if (o == nullptr) {
|
||||
objects[j] = nullptr;
|
||||
src[j] = NULL;
|
||||
len[j] = 0;
|
||||
minlen = 0;
|
||||
@ -753,7 +754,7 @@ void bitopCommand(client *c) {
|
||||
|
||||
/* Store the computed value into the target key */
|
||||
if (maxlen) {
|
||||
o = createObject(OBJ_STRING,res);
|
||||
robj *o = createObject(OBJ_STRING,res);
|
||||
setKey(c->db,targetkey,o);
|
||||
notifyKeyspaceEvent(NOTIFY_STRING,"set",targetkey,c->db->id);
|
||||
decrRefCount(o);
|
||||
@ -767,13 +768,13 @@ void bitopCommand(client *c) {
|
||||
|
||||
/* BITCOUNT key [start end] */
|
||||
void bitcountCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
long start, end, strlen;
|
||||
unsigned char *p;
|
||||
const unsigned char *p;
|
||||
char llbuf[LONG_STR_SIZE];
|
||||
|
||||
/* 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;
|
||||
p = getObjectReadOnlyString(o,&strlen,llbuf);
|
||||
|
||||
@ -816,9 +817,9 @@ void bitcountCommand(client *c) {
|
||||
|
||||
/* BITPOS key bit [start [end]] */
|
||||
void bitposCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
long bit, start, end, strlen;
|
||||
unsigned char *p;
|
||||
const unsigned char *p;
|
||||
char llbuf[LONG_STR_SIZE];
|
||||
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
|
||||
* 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 ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {
|
||||
if ((o = lookupKeyRead(c->db,c->argv[1])) == nullptr) {
|
||||
addReplyLongLong(c, bit ? -1 : 0);
|
||||
return;
|
||||
}
|
||||
@ -912,7 +913,7 @@ struct bitfieldOp {
|
||||
};
|
||||
|
||||
void bitfieldCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
size_t bitoffset;
|
||||
int j, numops = 0, changes = 0;
|
||||
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
|
||||
* if it's not a string. */
|
||||
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 {
|
||||
/* Lookup by making room up to the farest bit reached by
|
||||
* this operation. */
|
||||
if ((o = lookupStringForBitCommand(c,
|
||||
highest_write_offset)) == NULL) return;
|
||||
highest_write_offset)) == nullptr) return;
|
||||
}
|
||||
|
||||
addReplyArrayLen(c,numops);
|
||||
@ -1084,10 +1085,10 @@ void bitfieldCommand(client *c) {
|
||||
/* GET */
|
||||
unsigned char buf[9];
|
||||
long strlen = 0;
|
||||
unsigned char *src = NULL;
|
||||
const unsigned char *src = NULL;
|
||||
char llbuf[LONG_STR_SIZE];
|
||||
|
||||
if (o != NULL)
|
||||
if (o != nullptr)
|
||||
src = getObjectReadOnlyString(o,&strlen,llbuf);
|
||||
|
||||
/* For GET we use a trick: before executing the operation
|
||||
|
@ -4797,7 +4797,7 @@ NULL
|
||||
|
||||
/* Generates a DUMP-format representation of the object 'o', adding it to the
|
||||
* 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];
|
||||
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
|
||||
* complement of RESTORE and can be useful for different applications. */
|
||||
void dumpCommand(client *c) {
|
||||
robj *o, *dumpobj;
|
||||
robj_roptr o, dumpobj;
|
||||
rio payload;
|
||||
|
||||
/* 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);
|
||||
return;
|
||||
}
|
||||
@ -5086,7 +5086,7 @@ void migrateCommand(client *c) {
|
||||
char *password = NULL;
|
||||
long timeout;
|
||||
long dbid;
|
||||
robj **ov = NULL; /* Objects to migrate. */
|
||||
robj_roptr *ov = NULL; /* Objects to migrate. */
|
||||
robj **kv = NULL; /* Key names. */
|
||||
robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */
|
||||
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
|
||||
* this case, since often this is due to a normal condition like the key
|
||||
* 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);
|
||||
int oi = 0;
|
||||
|
||||
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];
|
||||
oi++;
|
||||
}
|
||||
@ -5583,7 +5583,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
||||
|
||||
/* Migarting / Improrting slot? Count keys we don't have. */
|
||||
if ((migrating_slot || importing_slot) &&
|
||||
lookupKeyRead(&server.db[0],thiskey) == NULL)
|
||||
lookupKeyRead(&server.db[0],thiskey) == nullptr)
|
||||
{
|
||||
missing_keys++;
|
||||
}
|
||||
|
37
src/db.cpp
37
src/db.cpp
@ -52,7 +52,7 @@ void updateLFU(robj *val) {
|
||||
/* Low level key lookup API, not actually called directly from commands
|
||||
* implementations that should instead rely on lookupKeyRead(),
|
||||
* 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));
|
||||
if (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
|
||||
* correctly report a key is expired on slaves even if the master is lagging
|
||||
* 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;
|
||||
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
|
||||
* common case. */
|
||||
robj *lookupKeyRead(redisDb *db, robj *key) {
|
||||
robj_roptr lookupKeyRead(redisDb *db, robj *key) {
|
||||
return lookupKeyReadWithFlags(db,key,LOOKUP_NONE);
|
||||
}
|
||||
|
||||
@ -160,8 +160,8 @@ robj *lookupKeyWrite(redisDb *db, robj *key) {
|
||||
return lookupKey(db,key,LOOKUP_NONE);
|
||||
}
|
||||
|
||||
robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
|
||||
robj *o = lookupKeyRead(c->db, key);
|
||||
robj_roptr lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
|
||||
robj_roptr o = lookupKeyRead(c->db, key);
|
||||
if (!o) addReply(c,reply);
|
||||
return o;
|
||||
}
|
||||
@ -175,6 +175,9 @@ robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply) {
|
||||
int dbAddCore(redisDb *db, robj *key, robj *val) {
|
||||
sds copy = sdsdup(szFromObj(key));
|
||||
int retval = dictAdd(db->pdict, copy, val);
|
||||
#ifdef ENABLE_MVCC
|
||||
val->mvcc_tstamp = key->mvcc_tstamp = getMvccTstamp();
|
||||
#endif
|
||||
|
||||
if (retval == DICT_OK)
|
||||
{
|
||||
@ -229,6 +232,9 @@ void dbOverwrite(redisDb *db, robj *key, robj *val) {
|
||||
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
|
||||
val->lru = old->lru;
|
||||
}
|
||||
#ifdef ENABLE_MVCC
|
||||
val->mvcc_tstamp = getMvccTstamp();
|
||||
#endif
|
||||
dictSetVal(db->pdict, de, val);
|
||||
|
||||
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
|
||||
* 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;
|
||||
list *keys = listCreate();
|
||||
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
|
||||
* 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);
|
||||
|
||||
/* 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. */
|
||||
while (i < c->argc) {
|
||||
@ -710,7 +716,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
|
||||
|
||||
/* Handle the case of a hash table. */
|
||||
ht = NULL;
|
||||
if (o == NULL) {
|
||||
if (o == nullptr) {
|
||||
ht = c->db->pdict;
|
||||
} else if (o->type == OBJ_SET && o->encoding == OBJ_ENCODING_HT) {
|
||||
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
|
||||
* it is possible to fetch more data in a type-dependent way. */
|
||||
privdata[0] = keys;
|
||||
privdata[1] = o;
|
||||
privdata[1] = o.unsafe_robjcast();
|
||||
do {
|
||||
cursor = dictScan(ht, cursor, scanCallback, NULL, privdata);
|
||||
} while (cursor &&
|
||||
@ -789,7 +795,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
if (filter) {
|
||||
@ -833,7 +839,7 @@ cleanup:
|
||||
void scanCommand(client *c) {
|
||||
unsigned long cursor;
|
||||
if (parseScanCursorOrReply(c,c->argv[1],&cursor) == C_ERR) return;
|
||||
scanGenericCommand(c,NULL,cursor);
|
||||
scanGenericCommand(c,nullptr,cursor);
|
||||
}
|
||||
|
||||
void dbsizeCommand(client *c) {
|
||||
@ -845,11 +851,10 @@ void lastsaveCommand(client *c) {
|
||||
}
|
||||
|
||||
void typeCommand(client *c) {
|
||||
robj *o;
|
||||
const char *type;
|
||||
|
||||
o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH);
|
||||
if (o == NULL) {
|
||||
robj_roptr o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH);
|
||||
if (o == nullptr) {
|
||||
type = "none";
|
||||
} else {
|
||||
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
|
||||
* 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;
|
||||
|
||||
/* No expire? return ASAP */
|
||||
|
@ -45,6 +45,7 @@ typedef ucontext_t sigcontext_t;
|
||||
#include <fcntl.h>
|
||||
#include "bio.h"
|
||||
#include <unistd.h>
|
||||
#include <cxxabi.h>
|
||||
#endif /* HAVE_BACKTRACE */
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
@ -61,7 +62,7 @@ typedef ucontext_t sigcontext_t;
|
||||
* "add" digests relative to unordered elements.
|
||||
*
|
||||
* 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;
|
||||
unsigned char hash[20];
|
||||
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")
|
||||
* 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;
|
||||
char *s = (char*)ptr;
|
||||
const char *s = (const char*)ptr;
|
||||
|
||||
xorDigest(digest,s,len);
|
||||
SHA1Init(&ctx);
|
||||
@ -105,7 +106,7 @@ void mixDigest(unsigned char *digest, void *ptr, size_t len) {
|
||||
SHA1Final(digest,&ctx);
|
||||
}
|
||||
|
||||
void mixStringObjectDigest(unsigned char *digest, robj *o) {
|
||||
void mixStringObjectDigest(unsigned char *digest, robj_roptr o) {
|
||||
o = getDecodedObject(o);
|
||||
mixDigest(digest,ptrFromObj(o),sdslen(szFromObj(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
|
||||
* will continue mixing this object digest to anything that was already
|
||||
* 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);
|
||||
mixDigest(digest,&aux,sizeof(aux));
|
||||
long long expiretime = getExpire(db,keyobj);
|
||||
@ -523,7 +524,7 @@ NULL
|
||||
for (int j = 2; j < c->argc; j++) {
|
||||
unsigned char digest[20];
|
||||
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);
|
||||
|
||||
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 encoding: %d", o->encoding);
|
||||
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();
|
||||
serverLog(LL_WARNING,"=== ASSERTION FAILED OBJECT CONTEXT ===");
|
||||
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 (o) _serverAssertPrintObject(o);
|
||||
_serverAssert(estr,file,line);
|
||||
@ -1138,6 +1139,61 @@ void closeDirectLogFiledes(int 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
|
||||
* to be called from signal handlers safely. */
|
||||
void logStackTrace(ucontext_t *uc) {
|
||||
@ -1154,12 +1210,12 @@ void logStackTrace(ucontext_t *uc) {
|
||||
const char *msg2 = "\nBacktrace:\n";
|
||||
if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */};
|
||||
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. */};
|
||||
}
|
||||
|
||||
/* Write symbols to log file */
|
||||
backtrace_symbols_fd(trace+1, trace_size, fd);
|
||||
backtrace_symbols_demangle_fd(trace+1, trace_size, fd);
|
||||
|
||||
/* Cleanup */
|
||||
closeDirectLogFiledes(fd);
|
||||
|
@ -474,7 +474,7 @@ void ttlGenericCommand(client *c, int output_ms) {
|
||||
long long expire, ttl = -1;
|
||||
|
||||
/* 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);
|
||||
return;
|
||||
}
|
||||
@ -520,7 +520,7 @@ void persistCommand(client *c) {
|
||||
void touchCommand(client *c) {
|
||||
int touched = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
|
20
src/geo.cpp
20
src/geo.cpp
@ -110,7 +110,7 @@ int extractLongLatOrReply(client *c, robj **argv, double *xy) {
|
||||
/* Input Argument Helper */
|
||||
/* Decode lat/long from a zset member's score.
|
||||
* 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;
|
||||
|
||||
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
|
||||
* 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. */
|
||||
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 */
|
||||
/* That's: min <= val < max */
|
||||
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.
|
||||
* Populate a geoArray of GeoPoints by calling geoGetPointsInRange().
|
||||
* 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;
|
||||
|
||||
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 */
|
||||
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];
|
||||
unsigned int i, count = 0, last_processed = 0;
|
||||
int debugmsg = 0;
|
||||
@ -465,8 +465,8 @@ void georadiusGeneric(client *c, int flags) {
|
||||
int storedist = 0; /* 0 for STORE, 1 for STOREDIST. */
|
||||
|
||||
/* Look up the requested zset */
|
||||
robj *zobj = NULL;
|
||||
if ((zobj = lookupKeyReadOrReply(c, key, shared.null[c->resp])) == NULL ||
|
||||
robj_roptr zobj;
|
||||
if ((zobj = lookupKeyReadOrReply(c, key, shared.null[c->resp])) == nullptr ||
|
||||
checkType(c, zobj, OBJ_ZSET)) {
|
||||
return;
|
||||
}
|
||||
@ -701,7 +701,7 @@ void geohashCommand(client *c) {
|
||||
int j;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Geohash elements one after the other, using a null bulk reply for
|
||||
@ -754,7 +754,7 @@ void geoposCommand(client *c) {
|
||||
int j;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 */
|
||||
robj *zobj = NULL;
|
||||
robj_roptr zobj = NULL;
|
||||
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. */
|
||||
double score1, score2, xyxy[4];
|
||||
|
@ -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
|
||||
* 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);
|
||||
int i;
|
||||
|
||||
@ -1085,7 +1085,7 @@ int hllMerge(uint8_t *max, size_t cmax, robj *hll) {
|
||||
if (val > max[i]) max[i] = val;
|
||||
}
|
||||
} 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;
|
||||
|
||||
p += HLL_HDR_SIZE;
|
||||
@ -1156,7 +1156,7 @@ robj *createHLLObject(void) {
|
||||
/* Check if the object is a String with a valid HLL representation.
|
||||
* Return C_OK if this is true, otherwise reply to the client
|
||||
* with an error and return C_ERR. */
|
||||
int isHLLObjectOrReply(client *c, robj *o) {
|
||||
int isHLLObjectOrReply(client *c, robj_roptr o) {
|
||||
struct hllhdr *hdr;
|
||||
|
||||
/* Key exists, check type */
|
||||
@ -1248,8 +1248,8 @@ void pfcountCommand(client *c) {
|
||||
registers = max + HLL_HDR_SIZE;
|
||||
for (j = 1; j < c->argc; j++) {
|
||||
/* Check type and size. */
|
||||
robj *o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == NULL) continue; /* Assume empty HLL for non existing var.*/
|
||||
robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == nullptr) continue; /* Assume empty HLL for non existing var.*/
|
||||
if (isHLLObjectOrReply(c,o) != C_OK) return;
|
||||
|
||||
/* 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));
|
||||
for (j = 1; j < c->argc; j++) {
|
||||
/* Check type and size. */
|
||||
robj *o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == NULL) continue; /* Assume empty HLL for non existing var. */
|
||||
robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == nullptr) continue; /* Assume empty HLL for non existing var. */
|
||||
if (isHLLObjectOrReply(c,o) != C_OK) return;
|
||||
|
||||
/* If at least one involved HLL is dense, use the dense representation
|
||||
|
@ -44,6 +44,10 @@
|
||||
#define LP_AFTER 1
|
||||
#define LP_REPLACE 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
unsigned char *lpNew(void);
|
||||
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);
|
||||
@ -58,4 +62,8 @@ unsigned char *lpPrev(unsigned char *lp, unsigned char *p);
|
||||
uint32_t lpBytes(unsigned char *lp);
|
||||
unsigned char *lpSeek(unsigned char *lp, long index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1525,7 +1525,7 @@ void *RM_OpenKey(RedisModuleCtx *ctx, robj *keyname, int mode) {
|
||||
if (mode & REDISMODULE_WRITE) {
|
||||
value = lookupKeyWrite(ctx->client->db,keyname);
|
||||
} else {
|
||||
value = lookupKeyRead(ctx->client->db,keyname);
|
||||
value = lookupKeyRead(ctx->client->db,keyname).unsafe_robjcast();
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ void *dupClientReplyValue(void *o) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
void freeClientReplyValue(void *o) {
|
||||
void freeClientReplyValue(const void *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.
|
||||
* 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 (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. */
|
||||
void addReply(client *c, robj *obj)
|
||||
void addReply(client *c, robj_roptr obj)
|
||||
{
|
||||
addReplyCore(c, obj, false);
|
||||
}
|
||||
void addReplyAsync(client *c, robj *obj)
|
||||
void addReplyAsync(client *c, robj_roptr obj)
|
||||
{
|
||||
addReplyCore(c, obj, true);
|
||||
}
|
||||
@ -867,7 +867,7 @@ void addReplyNullArray(client *c) {
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
if (len < OBJ_SHARED_BULKHDR_LEN)
|
||||
@ -882,18 +882,18 @@ void addReplyBulkLen(client *c, robj *obj)
|
||||
}
|
||||
|
||||
/* 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);
|
||||
addReplyCore(c,obj,fAsync);
|
||||
addReplyCore(c,shared.crlf,fAsync);
|
||||
}
|
||||
|
||||
void addReplyBulk(client *c, robj *obj)
|
||||
void addReplyBulk(client *c, robj_roptr obj)
|
||||
{
|
||||
addReplyBulkCore(c, obj, false);
|
||||
}
|
||||
|
||||
void addReplyBulkAsync(client *c, robj *obj)
|
||||
void addReplyBulkAsync(client *c, robj_roptr obj)
|
||||
{
|
||||
addReplyBulkCore(c, obj, true);
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ robj *createObject(int type, void *ptr) {
|
||||
o->encoding = OBJ_ENCODING_RAW;
|
||||
o->m_ptr = ptr;
|
||||
o->refcount = 1;
|
||||
#ifdef ENABLE_MVCC
|
||||
o->mvcc_tstamp = OBJ_MVCC_INVALID;
|
||||
#endif
|
||||
|
||||
/* Set the LRU to the current lruclock (minutes resolution), or
|
||||
* alternatively the LFU counter. */
|
||||
@ -91,6 +94,9 @@ robj *createEmbeddedStringObject(const char *ptr, size_t len) {
|
||||
o->type = OBJ_STRING;
|
||||
o->encoding = OBJ_ENCODING_EMBSTR;
|
||||
o->refcount = 1;
|
||||
#ifdef ENABLE_MVCC
|
||||
o->mvcc_tstamp = OBJ_MVCC_INVALID;
|
||||
#endif
|
||||
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
|
||||
o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;
|
||||
} else {
|
||||
@ -280,13 +286,13 @@ robj *createModuleObject(moduleType *mt, void *value) {
|
||||
return createObject(OBJ_MODULE,mv);
|
||||
}
|
||||
|
||||
void freeStringObject(robj *o) {
|
||||
void freeStringObject(robj_roptr o) {
|
||||
if (o->encoding == OBJ_ENCODING_RAW) {
|
||||
sdsfree(szFromObj(o));
|
||||
}
|
||||
}
|
||||
|
||||
void freeListObject(robj *o) {
|
||||
void freeListObject(robj_roptr o) {
|
||||
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||
quicklistRelease((quicklist*)ptrFromObj(o));
|
||||
} else {
|
||||
@ -294,7 +300,7 @@ void freeListObject(robj *o) {
|
||||
}
|
||||
}
|
||||
|
||||
void freeSetObject(robj *o) {
|
||||
void freeSetObject(robj_roptr o) {
|
||||
switch (o->encoding) {
|
||||
case OBJ_ENCODING_HT:
|
||||
dictRelease((dict*) ptrFromObj(o));
|
||||
@ -307,7 +313,7 @@ void freeSetObject(robj *o) {
|
||||
}
|
||||
}
|
||||
|
||||
void freeZsetObject(robj *o) {
|
||||
void freeZsetObject(robj_roptr o) {
|
||||
zset *zs;
|
||||
switch (o->encoding) {
|
||||
case OBJ_ENCODING_SKIPLIST:
|
||||
@ -324,7 +330,7 @@ void freeZsetObject(robj *o) {
|
||||
}
|
||||
}
|
||||
|
||||
void freeHashObject(robj *o) {
|
||||
void freeHashObject(robj_roptr o) {
|
||||
switch (o->encoding) {
|
||||
case OBJ_ENCODING_HT:
|
||||
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);
|
||||
mv->type->free(mv->value);
|
||||
zfree(mv);
|
||||
}
|
||||
|
||||
void freeStreamObject(robj *o) {
|
||||
void freeStreamObject(robj_roptr o) {
|
||||
freeStream((stream*)ptrFromObj(o));
|
||||
}
|
||||
|
||||
void incrRefCount(robj *o) {
|
||||
void incrRefCount(robj_roptr o) {
|
||||
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount++;
|
||||
}
|
||||
|
||||
void decrRefCount(robj *o) {
|
||||
void decrRefCount(robj_roptr o) {
|
||||
if (o->refcount == 1) {
|
||||
switch(o->type) {
|
||||
case OBJ_STRING: freeStringObject(o); break;
|
||||
@ -364,7 +370,7 @@ void decrRefCount(robj *o) {
|
||||
case OBJ_STREAM: freeStreamObject(o); break;
|
||||
default: serverPanic("Unknown object type"); break;
|
||||
}
|
||||
zfree(o);
|
||||
zfree(o.unsafe_robjcast());
|
||||
} else {
|
||||
if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
|
||||
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
|
||||
* as free method in data structures that expect a 'void free_object(void*)'
|
||||
* prototype for the free method. */
|
||||
void decrRefCountVoid(void *o) {
|
||||
void decrRefCountVoid(const void *o) {
|
||||
decrRefCount((robj*)o);
|
||||
}
|
||||
|
||||
@ -395,7 +401,7 @@ robj *resetRefCount(robj *obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
int checkType(client *c, robj *o, int type) {
|
||||
int checkType(client *c, robj_roptr o, int type) {
|
||||
if (o->type != type) {
|
||||
addReplyAsync(c,shared.wrongtypeerr);
|
||||
return 1;
|
||||
@ -403,7 +409,7 @@ int checkType(client *c, robj *o, int type) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
* 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
|
||||
@ -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);
|
||||
if (sdsEncodedObject(o)) {
|
||||
return sdslen(szFromObj(o));
|
||||
|
@ -120,7 +120,7 @@ void addReplyPubsubPatUnsubscribed(client *c, robj *pattern) {
|
||||
* Pubsub low level API
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void freePubsubPattern(void *p) {
|
||||
void freePubsubPattern(const void *p) {
|
||||
pubsubPattern *pat = (pubsubPattern *)p;
|
||||
|
||||
decrRefCount(pat->pattern);
|
||||
|
@ -6,7 +6,7 @@ extern "C" {
|
||||
#include <sys/wait.h>
|
||||
|
||||
/* 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 fd[2];
|
||||
|
@ -455,7 +455,7 @@ ssize_t rdbSaveLongLongAsStringObject(rio *rdb, long long value) {
|
||||
}
|
||||
|
||||
/* 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
|
||||
* object is already integer encoded. */
|
||||
if (obj->encoding == OBJ_ENCODING_INT) {
|
||||
@ -623,7 +623,7 @@ int rdbLoadBinaryFloatValue(rio *rdb, float *val) {
|
||||
}
|
||||
|
||||
/* Save the object type of object "o". */
|
||||
int rdbSaveObjectType(rio *rdb, robj *o) {
|
||||
int rdbSaveObjectType(rio *rdb, robj_roptr o) {
|
||||
switch (o->type) {
|
||||
case OBJ_STRING:
|
||||
return rdbSaveType(rdb,RDB_TYPE_STRING);
|
||||
@ -752,7 +752,7 @@ size_t rdbSaveStreamConsumers(rio *rdb, streamCG *cg) {
|
||||
|
||||
/* Save a Redis object.
|
||||
* 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;
|
||||
|
||||
if (o->type == OBJ_STRING) {
|
||||
|
@ -133,7 +133,7 @@ int rdbSaveMillisecondTime(rio *rdb, long long t);
|
||||
long long rdbLoadMillisecondTime(rio *rdb, int rdbver);
|
||||
uint64_t rdbLoadLen(rio *rdb, int *isencoded);
|
||||
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 rdbLoad(rdbSaveInfo *rsi);
|
||||
int rdbSaveBackground(rdbSaveInfo *rsi);
|
||||
@ -144,13 +144,13 @@ int rdbSaveFile(char *filename, rdbSaveInfo *rsi);
|
||||
int rdbSaveFd(int fd, rdbSaveInfo *rsi);
|
||||
int rdbSaveS3(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);
|
||||
robj *rdbLoadObject(int type, rio *rdb, robj *key);
|
||||
void backgroundSaveDoneHandler(int exitcode, int bysignal);
|
||||
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime);
|
||||
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);
|
||||
void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr);
|
||||
int rdbSaveBinaryDoubleValue(rio *rdb, double val);
|
||||
|
@ -889,29 +889,28 @@ void syncCommand(client *c) {
|
||||
|
||||
void processReplconfUuid(client *c, robj *arg)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (arg->type != OBJ_STRING)
|
||||
throw "Invalid UUID";
|
||||
const char *remoteUUID = nullptr;
|
||||
|
||||
const char *remoteUUID = (const char*)ptrFromObj(arg);
|
||||
if (strlen(remoteUUID) != 36)
|
||||
throw "Invalid UUID";
|
||||
if (arg->type != OBJ_STRING)
|
||||
goto LError;
|
||||
|
||||
if (uuid_parse(remoteUUID, c->uuid) != 0)
|
||||
throw "Invalid UUID";
|
||||
remoteUUID = (const char*)ptrFromObj(arg);
|
||||
if (strlen(remoteUUID) != 36)
|
||||
goto LError;
|
||||
|
||||
char szServerUUID[36 + 2]; // 1 for the '+', another for '\0'
|
||||
szServerUUID[0] = '+';
|
||||
uuid_unparse(server.uuid, szServerUUID+1);
|
||||
addReplyProto(c, szServerUUID, 37);
|
||||
addReplyProto(c, "\r\n", 2);
|
||||
}
|
||||
catch (const char *szErr)
|
||||
{
|
||||
addReplyError(c, szErr);
|
||||
return;
|
||||
}
|
||||
if (uuid_parse(remoteUUID, c->uuid) != 0)
|
||||
goto LError;
|
||||
|
||||
char szServerUUID[36 + 2]; // 1 for the '+', another for '\0'
|
||||
szServerUUID[0] = '+';
|
||||
uuid_unparse(server.uuid, szServerUUID+1);
|
||||
addReplyProto(c, szServerUUID, 37);
|
||||
addReplyProto(c, "\r\n", 2);
|
||||
return;
|
||||
|
||||
LError:
|
||||
addReplyError(c, "Invalid UUID");
|
||||
return;
|
||||
}
|
||||
|
||||
/* REPLCONF <option> <value> <option> <value> ...
|
||||
|
@ -1616,7 +1616,7 @@ void ldbInit(void) {
|
||||
ldb.fd = -1;
|
||||
ldb.active = 0;
|
||||
ldb.logs = listCreate();
|
||||
listSetFreeMethod(ldb.logs,(void (*)(void*))sdsfree);
|
||||
listSetFreeMethod(ldb.logs,(void (*)(const void*))sdsfree);
|
||||
ldb.children = listCreate();
|
||||
ldb.src = NULL;
|
||||
ldb.lines = 0;
|
||||
|
@ -157,12 +157,12 @@ sds sdsnew(const char *init) {
|
||||
}
|
||||
|
||||
/* Duplicate an sds string. */
|
||||
sds sdsdup(const sds s) {
|
||||
sds sdsdup(const char *s) {
|
||||
return sdsnewlen(s, sdslen(s));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
s_free((char*)s-sdsHdrSize(s[-1]));
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ struct __attribute__ ((__packed__)) sdshdr64 {
|
||||
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
|
||||
#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];
|
||||
int type = flags & SDS_TYPE_MASK;
|
||||
|
||||
@ -126,7 +126,7 @@ static inline size_t sdslen(const sds s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t sdsavail(const sds s) {
|
||||
static inline size_t sdsavail(const char * s) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
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 sdsnew(const char *init);
|
||||
sds sdsempty(void);
|
||||
sds sdsdup(const sds s);
|
||||
void sdsfree(sds s);
|
||||
sds sdsdup(const char *s);
|
||||
void sdsfree(const char *s);
|
||||
sds sdsgrowzero(sds s, size_t len);
|
||||
sds sdscatlen(sds s, const void *t, size_t len);
|
||||
sds sdscat(sds s, const char *t);
|
||||
|
@ -3132,7 +3132,7 @@ void redisOpArrayFree(redisOpArray *oa) {
|
||||
|
||||
/* ====================== Commands lookup and execution ===================== */
|
||||
|
||||
extern "C" struct redisCommand *lookupCommand(sds name) {
|
||||
struct redisCommand *lookupCommand(sds 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
|
||||
* by the INFO command itself as we need to report the same information
|
||||
* on memory corruption problems. */
|
||||
extern "C" sds genRedisInfoString(const char *section) {
|
||||
sds genRedisInfoString(const char *section) {
|
||||
sds info = sdsempty();
|
||||
time_t uptime = server.unixtime-server.stat_starttime;
|
||||
int j;
|
||||
@ -4876,6 +4876,11 @@ int redisIsSupervised(int mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t getMvccTstamp()
|
||||
{
|
||||
return (server.mstime << 16);
|
||||
}
|
||||
|
||||
void *workerThreadMain(void *parg)
|
||||
{
|
||||
int iel = (int)((int64_t)parg);
|
||||
|
180
src/server.h
180
src/server.h
@ -84,9 +84,57 @@ typedef long long mstime_t; /* millisecond time type. */
|
||||
#include "endianconv.h"
|
||||
#include "crc64.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct redisObject;
|
||||
class robj_roptr
|
||||
{
|
||||
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 */
|
||||
#define C_OK 0
|
||||
@ -654,16 +702,28 @@ typedef struct RedisModuleDigest {
|
||||
#define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */
|
||||
|
||||
#define OBJ_SHARED_REFCOUNT INT_MAX
|
||||
#define OBJ_MVCC_INVALID (0xFFFFFFFFFFFFFFFFULL)
|
||||
typedef struct redisObject {
|
||||
unsigned type:4;
|
||||
unsigned encoding:4;
|
||||
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
|
||||
* LFU data (least significant 8 bits frequency
|
||||
* and most significant 16 bits access time). */
|
||||
int refcount;
|
||||
#ifdef ENABLE_MVCC
|
||||
uint64_t mvcc_tstamp;
|
||||
#endif
|
||||
mutable int refcount;
|
||||
void *m_ptr;
|
||||
} 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)
|
||||
{
|
||||
if (o->encoding == OBJ_ENCODING_EMBSTR)
|
||||
@ -671,6 +731,11 @@ __attribute__((always_inline)) inline void *ptrFromObj(const robj *o)
|
||||
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)
|
||||
{
|
||||
return (char*)ptrFromObj(o);
|
||||
@ -1511,7 +1576,7 @@ typedef struct _redisSortOperation {
|
||||
|
||||
/* Structure to hold list iteration abstraction. */
|
||||
typedef struct {
|
||||
robj *subject;
|
||||
robj_roptr subject;
|
||||
unsigned char encoding;
|
||||
unsigned char direction; /* Iteration direction */
|
||||
quicklistIter *iter;
|
||||
@ -1525,7 +1590,7 @@ typedef struct {
|
||||
|
||||
/* Structure to hold set iteration abstraction. */
|
||||
typedef struct {
|
||||
robj *subject;
|
||||
robj_roptr subject;
|
||||
int encoding;
|
||||
int ii; /* intset iterator */
|
||||
dictIterator *di;
|
||||
@ -1536,7 +1601,7 @@ typedef struct {
|
||||
* not both are required, store pointers in the iterator to avoid
|
||||
* unnecessary memory allocation for fields/values. */
|
||||
typedef struct {
|
||||
robj *subject;
|
||||
robj_roptr subject;
|
||||
int encoding;
|
||||
|
||||
unsigned char *fptr, *vptr;
|
||||
@ -1596,11 +1661,11 @@ void moduleCallCommandFilters(client *c);
|
||||
/* Utils */
|
||||
long long ustime(void);
|
||||
long long mstime(void);
|
||||
void getRandomHexChars(char *p, size_t len);
|
||||
void getRandomBytes(unsigned char *p, size_t len);
|
||||
extern "C" void getRandomHexChars(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);
|
||||
void exitFromChild(int retcode);
|
||||
size_t redisPopcount(void *s, long count);
|
||||
size_t redisPopcount(const void *s, long count);
|
||||
void redisSetProcTitle(const char *title);
|
||||
|
||||
/* networking.c -- Networking and Client related operations */
|
||||
@ -1627,11 +1692,11 @@ void addReplyNullArray(client *c);
|
||||
void addReplyBool(client *c, int b);
|
||||
void addReplyVerbatim(client *c, const char *s, size_t len, const char *ext);
|
||||
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 addReplyBulkCBuffer(client *c, const void *p, size_t len);
|
||||
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 addReplyBulkSds(client *c, sds s);
|
||||
void addReplyError(client *c, const char *err);
|
||||
@ -1653,7 +1718,7 @@ void addReplyLoadedModules(client *c);
|
||||
void copyClientOutputBuffer(client *dst, client *src);
|
||||
size_t sdsZmallocSize(sds s);
|
||||
size_t getStringObjectSdsUsedMemory(robj *o);
|
||||
void freeClientReplyValue(void *o);
|
||||
void freeClientReplyValue(const void *o);
|
||||
void *dupClientReplyValue(void *o);
|
||||
void getClientsMaxBuffers(unsigned long *longest_output_list,
|
||||
unsigned long *biggest_input_buffer);
|
||||
@ -1685,10 +1750,10 @@ void protectClient(client *c);
|
||||
void unprotectClient(client *c);
|
||||
|
||||
// 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 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 addReplyErrorAsync(client *c, const char *err);
|
||||
void addReplyMapLenAsync(client *c, long length);
|
||||
@ -1717,8 +1782,8 @@ void addReplyStatusFormat(client *c, const char *fmt, ...);
|
||||
void listTypeTryConversion(robj *subject, robj *value);
|
||||
void listTypePush(robj *subject, robj *value, int where);
|
||||
robj *listTypePop(robj *subject, int where);
|
||||
unsigned long listTypeLength(const robj *subject);
|
||||
listTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction);
|
||||
unsigned long listTypeLength(robj_roptr subject);
|
||||
listTypeIterator *listTypeInitIterator(robj_roptr subject, long index, unsigned char direction);
|
||||
void listTypeReleaseIterator(listTypeIterator *li);
|
||||
int listTypeNext(listTypeIterator *li, listTypeEntry *entry);
|
||||
robj *listTypeGet(listTypeEntry *entry);
|
||||
@ -1741,9 +1806,9 @@ void flagTransaction(client *c);
|
||||
void execCommandPropagateMulti(client *c);
|
||||
|
||||
/* Redis object implementation */
|
||||
void decrRefCount(robj *o);
|
||||
void decrRefCountVoid(void *o);
|
||||
void incrRefCount(robj *o);
|
||||
void decrRefCount(robj_roptr o);
|
||||
void decrRefCountVoid(const void *o);
|
||||
void incrRefCount(robj_roptr o);
|
||||
robj *makeObjectShared(robj *o);
|
||||
robj *resetRefCount(robj *obj);
|
||||
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 *createEmbeddedStringObject(const char *ptr, size_t len);
|
||||
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);
|
||||
robj *tryObjectEncoding(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 *createStringObjectFromLongLongForValue(long long value);
|
||||
robj *createStringObjectFromLongDouble(long double value, int humanfriendly);
|
||||
@ -1774,7 +1840,7 @@ robj *createZsetZiplistObject(void);
|
||||
robj *createStreamObject(void);
|
||||
robj *createModuleObject(moduleType *mt, void *value);
|
||||
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 getDoubleFromObjectOrReply(client *c, robj *o, double *target, const char *msg);
|
||||
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);
|
||||
unsigned char *zzlFirstInRange(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 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);
|
||||
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);
|
||||
void genericZpopCommand(client *c, robj **keyv, int keyc, int where, int emitkey, robj *countarg);
|
||||
sds ziplistGetObject(unsigned char *sptr);
|
||||
@ -1996,17 +2062,17 @@ void freeMemoryOverheadData(struct redisMemOverhead *mh);
|
||||
int restartServer(int flags, mstime_t delay);
|
||||
|
||||
/* Set data type */
|
||||
robj *setTypeCreate(sds value);
|
||||
int setTypeAdd(robj *subject, sds value);
|
||||
int setTypeRemove(robj *subject, sds value);
|
||||
int setTypeIsMember(robj *subject, sds value);
|
||||
setTypeIterator *setTypeInitIterator(robj *subject);
|
||||
robj *setTypeCreate(const char *value);
|
||||
int setTypeAdd(robj *subject, const char *value);
|
||||
int setTypeRemove(robj *subject, const char *value);
|
||||
int setTypeIsMember(robj_roptr subject, const char *value);
|
||||
setTypeIterator *setTypeInitIterator(robj_roptr subject);
|
||||
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);
|
||||
int setTypeRandomElement(robj *setobj, sds *sdsele, int64_t *llele);
|
||||
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);
|
||||
|
||||
/* Hash data type */
|
||||
@ -2016,10 +2082,10 @@ void setTypeConvert(robj *subject, int enc);
|
||||
|
||||
void hashTypeConvert(robj *o, int enc);
|
||||
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);
|
||||
unsigned long hashTypeLength(const robj *o);
|
||||
hashTypeIterator *hashTypeInitIterator(robj *subject);
|
||||
unsigned long hashTypeLength(robj_roptr o);
|
||||
hashTypeIterator *hashTypeInitIterator(robj_roptr subject);
|
||||
void hashTypeReleaseIterator(hashTypeIterator *hi);
|
||||
int hashTypeNext(hashTypeIterator *hi);
|
||||
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);
|
||||
sds hashTypeCurrentObjectNewSds(hashTypeIterator *hi, int what);
|
||||
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);
|
||||
|
||||
/* Pub / Sub */
|
||||
int pubsubUnsubscribeAllChannels(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 pubsubPublishMessage(robj *channel, robj *message);
|
||||
|
||||
@ -2057,14 +2123,13 @@ int rewriteConfig(char *path);
|
||||
int removeExpire(redisDb *db, robj *key);
|
||||
void propagateExpire(redisDb *db, robj *key, int lazy);
|
||||
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);
|
||||
robj *lookupKey(redisDb *db, robj *key, int flags);
|
||||
robj *lookupKeyRead(redisDb *db, robj *key);
|
||||
robj_roptr lookupKeyRead(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 *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags);
|
||||
robj_roptr lookupKeyReadWithFlags(redisDb *db, robj *key, int flags);
|
||||
robj *objectCommandLookup(client *c, robj *key);
|
||||
robj *objectCommandLookupOrReply(client *c, robj *key, robj *reply);
|
||||
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 delKeysInSlot(unsigned int hashslot);
|
||||
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);
|
||||
void slotToKeyAdd(robj *key);
|
||||
void slotToKeyDel(robj *key);
|
||||
@ -2115,7 +2180,7 @@ int *xreadGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys)
|
||||
|
||||
/* Cluster */
|
||||
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);
|
||||
void clusterCron(void);
|
||||
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);
|
||||
|
||||
/* Git SHA1 */
|
||||
char *redisGitSHA1(void);
|
||||
char *redisGitDirty(void);
|
||||
uint64_t redisBuildId(void);
|
||||
extern "C" char *redisGitSHA1(void);
|
||||
extern "C" char *redisGitDirty(void);
|
||||
extern "C" uint64_t redisBuildId(void);
|
||||
|
||||
/* Commands prototypes */
|
||||
void authCommand(client *c);
|
||||
@ -2380,6 +2445,9 @@ int FBrokenLinkToMaster();
|
||||
int FActiveMaster(client *c);
|
||||
struct redisMaster *MasterInfoFromClient(client *c);
|
||||
|
||||
/* MVCC */
|
||||
uint64_t getMvccTstamp();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#ifndef __cplusplus
|
||||
void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
|
||||
@ -2390,19 +2458,19 @@ void *realloc(void *ptr, size_t size) __attribute__ ((deprecated));
|
||||
#endif
|
||||
|
||||
/* Debugging stuff */
|
||||
void _serverAssertWithInfo(const client *c, const robj *o, const char *estr, const char *file, int line);
|
||||
void _serverAssert(const char *estr, const char *file, int line);
|
||||
void _serverPanic(const char *file, int line, const char *msg, ...);
|
||||
void _serverAssertWithInfo(const client *c, robj_roptr o, const char *estr, const char *file, int line);
|
||||
extern "C" void _serverAssert(const char *estr, const char *file, int line);
|
||||
extern "C" void _serverPanic(const char *file, int line, const char *msg, ...);
|
||||
void bugReportStart(void);
|
||||
void serverLogObjectDebugInfo(const robj *o);
|
||||
void serverLogObjectDebugInfo(robj_roptr o);
|
||||
void sigsegvHandler(int sig, siginfo_t *info, void *secret);
|
||||
sds genRedisInfoString(const char *section);
|
||||
void enableWatchdog(int period);
|
||||
void disableWatchdog(void);
|
||||
void watchdogScheduleSignal(int period);
|
||||
void serverLogHexDump(int level, const char *descr, void *value, size_t len);
|
||||
int memtest_preserving_test(unsigned long *m, size_t bytes, int passes);
|
||||
void mixDigest(unsigned char *digest, void *ptr, size_t len);
|
||||
extern "C" int memtest_preserving_test(unsigned long *m, size_t bytes, int passes);
|
||||
void mixDigest(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);
|
||||
|
||||
@ -2437,8 +2505,4 @@ inline int FCorrectThread(client *c)
|
||||
#define redisDebugMark() \
|
||||
printf("-- MARK %s:%d --\n", __FILE__, __LINE__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -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.
|
||||
*
|
||||
* This function will take care to release all the retained object. */
|
||||
void slowlogFreeEntry(void *septr) {
|
||||
void slowlogFreeEntry(const void *septr) {
|
||||
slowlogEntry *se = (slowlogEntry*)septr;
|
||||
int j;
|
||||
|
||||
|
@ -61,7 +61,8 @@ redisSortOperation *createSortOperation(int type, robj *pattern) {
|
||||
robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst, int writeflag) {
|
||||
char *p, *f, *k;
|
||||
sds spat, ssub;
|
||||
robj *keyobj, *fieldobj = NULL, *o;
|
||||
robj *keyobj, *fieldobj = NULL;
|
||||
robj_roptr o;
|
||||
int prefixlen, sublen, postfixlen, fieldlen;
|
||||
|
||||
/* 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);
|
||||
else
|
||||
o = lookupKeyWrite(db,keyobj);
|
||||
if (o == NULL) goto noobj;
|
||||
if (o == nullptr) goto noobj;
|
||||
|
||||
if (fieldobj) {
|
||||
if (o->type != OBJ_HASH) goto noobj;
|
||||
@ -127,7 +128,7 @@ robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst, int writeflag)
|
||||
}
|
||||
decrRefCount(keyobj);
|
||||
if (fieldobj) decrRefCount(fieldobj);
|
||||
return o;
|
||||
return o.unsafe_robjcast();
|
||||
|
||||
noobj:
|
||||
decrRefCount(keyobj);
|
||||
@ -271,7 +272,7 @@ void sortCommand(client *c) {
|
||||
|
||||
/* Lookup the key to sort. It must be of the right types */
|
||||
if (storekey)
|
||||
sortval = lookupKeyRead(c->db,c->argv[1]);
|
||||
sortval = lookupKeyRead(c->db,c->argv[1]).unsafe_robjcast();
|
||||
else
|
||||
sortval = lookupKeyWrite(c->db,c->argv[1]);
|
||||
if (sortval && sortval->type != OBJ_SET &&
|
||||
|
@ -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.
|
||||
* Returns -1 when the field cannot be found. */
|
||||
int hashTypeGetFromZiplist(robj *o, sds field,
|
||||
unsigned char **vstr,
|
||||
int hashTypeGetFromZiplist(robj_roptr o, const char *field,
|
||||
const unsigned char **vstr,
|
||||
unsigned int *vlen,
|
||||
long long *vll)
|
||||
{
|
||||
@ -64,7 +64,7 @@ int hashTypeGetFromZiplist(robj *o, sds field,
|
||||
|
||||
serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);
|
||||
|
||||
zl = (unsigned char*)ptrFromObj(o);
|
||||
zl = (unsigned char*)(ptrFromObj(o));
|
||||
fptr = ziplistIndex(zl, ZIPLIST_HEAD);
|
||||
if (fptr != NULL) {
|
||||
fptr = ziplistFind(fptr, (unsigned char*)field, sdslen(field), 1);
|
||||
@ -76,7 +76,7 @@ int hashTypeGetFromZiplist(robj *o, sds field,
|
||||
}
|
||||
|
||||
if (vptr != NULL) {
|
||||
ret = ziplistGet(vptr, vstr, vlen, vll);
|
||||
ret = ziplistGet(vptr, (unsigned char**)vstr, vlen, vll);
|
||||
serverAssert(ret);
|
||||
return 0;
|
||||
}
|
||||
@ -87,7 +87,7 @@ int hashTypeGetFromZiplist(robj *o, sds 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
|
||||
* is returned. */
|
||||
sds hashTypeGetFromHashTable(robj *o, sds field) {
|
||||
const char *hashTypeGetFromHashTable(robj_roptr o, const char *field) {
|
||||
dictEntry *de;
|
||||
|
||||
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
|
||||
* can always check the function return by checking the return value
|
||||
* 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) {
|
||||
*vstr = NULL;
|
||||
if (hashTypeGetFromZiplist(o, field, vstr, vlen, vll) == 0)
|
||||
return C_OK;
|
||||
} else if (o->encoding == OBJ_ENCODING_HT) {
|
||||
sds value;
|
||||
const char *value;
|
||||
if ((value = hashTypeGetFromHashTable(o, field)) != NULL) {
|
||||
*vstr = (unsigned char*) value;
|
||||
*vstr = (const unsigned char*) value;
|
||||
*vlen = sdslen(value);
|
||||
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.
|
||||
* The function returns NULL if the field is not found in the hash. Otherwise
|
||||
* a newly allocated string object with the value is returned. */
|
||||
robj *hashTypeGetValueObject(robj *o, sds field) {
|
||||
unsigned char *vstr;
|
||||
robj *hashTypeGetValueObject(robj_roptr o, sds field) {
|
||||
const unsigned char *vstr;
|
||||
unsigned int vlen;
|
||||
long long vll;
|
||||
|
||||
@ -141,17 +141,17 @@ robj *hashTypeGetValueObject(robj *o, sds field) {
|
||||
/* Higher level function using hashTypeGet*() to return the length of the
|
||||
* object associated with the requested field, or 0 if the field does not
|
||||
* exist. */
|
||||
size_t hashTypeGetValueLength(robj *o, sds field) {
|
||||
size_t hashTypeGetValueLength(robj_roptr o, const char *field) {
|
||||
size_t len = 0;
|
||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
unsigned char *vstr = NULL;
|
||||
const unsigned char *vstr = NULL;
|
||||
unsigned int vlen = UINT_MAX;
|
||||
long long vll = LLONG_MAX;
|
||||
|
||||
if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0)
|
||||
len = vstr ? vlen : sdigits10(vll);
|
||||
} else if (o->encoding == OBJ_ENCODING_HT) {
|
||||
sds aux;
|
||||
const char *aux;
|
||||
|
||||
if ((aux = hashTypeGetFromHashTable(o, field)) != NULL)
|
||||
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
|
||||
* 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) {
|
||||
unsigned char *vstr = NULL;
|
||||
const unsigned char *vstr = NULL;
|
||||
unsigned int vlen = UINT_MAX;
|
||||
long long vll = LLONG_MAX;
|
||||
|
||||
@ -308,7 +308,7 @@ int hashTypeDelete(robj *o, sds field) {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
@ -321,7 +321,7 @@ unsigned long hashTypeLength(const robj *o) {
|
||||
return length;
|
||||
}
|
||||
|
||||
hashTypeIterator *hashTypeInitIterator(robj *subject) {
|
||||
hashTypeIterator *hashTypeInitIterator(robj_roptr subject) {
|
||||
hashTypeIterator *hi = (hashTypeIterator*)zmalloc(sizeof(hashTypeIterator), MALLOC_LOCAL);
|
||||
hi->subject = subject;
|
||||
hi->encoding = subject->encoding;
|
||||
@ -560,7 +560,7 @@ void hincrbyCommand(client *c) {
|
||||
long long value, incr, oldvalue;
|
||||
robj *o;
|
||||
sds newstr;
|
||||
unsigned char *vstr;
|
||||
const unsigned char *vstr;
|
||||
unsigned int vlen;
|
||||
|
||||
if (getLongLongFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;
|
||||
@ -596,7 +596,7 @@ void hincrbyfloatCommand(client *c) {
|
||||
long long ll;
|
||||
robj *o;
|
||||
sds newstr;
|
||||
unsigned char *vstr;
|
||||
const unsigned char *vstr;
|
||||
unsigned int vlen;
|
||||
|
||||
if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;
|
||||
@ -641,16 +641,16 @@ void hincrbyfloatCommand(client *c) {
|
||||
decrRefCount(newobj);
|
||||
}
|
||||
|
||||
static void addHashFieldToReply(client *c, robj *o, sds field) {
|
||||
static void addHashFieldToReply(client *c, robj_roptr o, sds field) {
|
||||
int ret;
|
||||
|
||||
if (o == NULL) {
|
||||
if (o == nullptr) {
|
||||
addReplyNull(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
unsigned char *vstr = NULL;
|
||||
const unsigned char *vstr = NULL;
|
||||
unsigned int vlen = UINT_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) {
|
||||
sds value = hashTypeGetFromHashTable(o, field);
|
||||
const char* value = hashTypeGetFromHashTable(o, field);
|
||||
if (value == NULL)
|
||||
addReplyNull(c);
|
||||
else
|
||||
@ -677,22 +677,22 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
addHashFieldToReply(c, o, szFromObj(c->argv[2]));
|
||||
}
|
||||
|
||||
void hmgetCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
int i;
|
||||
|
||||
/* 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. */
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -732,18 +732,18 @@ void hdelCommand(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;
|
||||
|
||||
addReplyLongLong(c,hashTypeLength(o));
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
hashTypeIterator *hi;
|
||||
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;
|
||||
|
||||
/* 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) {
|
||||
robj *o;
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
|
||||
robj_roptr o;
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
|
||||
checkType(c,o,OBJ_HASH)) return;
|
||||
|
||||
addReply(c, hashTypeExists(o,szFromObj(c->argv[2])) ? shared.cone : shared.czero);
|
||||
}
|
||||
|
||||
void hscanCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
unsigned long cursor;
|
||||
|
||||
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;
|
||||
scanGenericCommand(c,o,cursor);
|
||||
}
|
||||
|
@ -71,16 +71,16 @@ robj *listTypePop(robj *subject, int where) {
|
||||
return value;
|
||||
}
|
||||
|
||||
unsigned long listTypeLength(const robj *subject) {
|
||||
unsigned long listTypeLength(robj_roptr subject) {
|
||||
if (subject->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||
return quicklistCount((quicklist*)ptrFromObj(subject));
|
||||
return quicklistCount((const quicklist*)ptrFromObj(subject));
|
||||
} else {
|
||||
serverPanic("Unknown list encoding");
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize an iterator at the specified index. */
|
||||
listTypeIterator *listTypeInitIterator(robj *subject, long index,
|
||||
listTypeIterator *listTypeInitIterator(robj_roptr subject, long index,
|
||||
unsigned char direction) {
|
||||
listTypeIterator *li = (listTypeIterator*)zmalloc(sizeof(listTypeIterator), MALLOC_LOCAL);
|
||||
li->subject = subject;
|
||||
@ -306,14 +306,14 @@ void linsertCommand(client *c) {
|
||||
}
|
||||
|
||||
void llenCommand(client *c) {
|
||||
robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.czero);
|
||||
if (o == NULL || checkType(c,o,OBJ_LIST)) return;
|
||||
robj_roptr o = lookupKeyReadOrReply(c,c->argv[1],shared.czero);
|
||||
if (o == nullptr || checkType(c,o,OBJ_LIST)) return;
|
||||
addReplyLongLong(c,listTypeLength(o));
|
||||
}
|
||||
|
||||
void lindexCommand(client *c) {
|
||||
robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]);
|
||||
if (o == NULL || checkType(c,o,OBJ_LIST)) return;
|
||||
robj_roptr o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]);
|
||||
if (o == nullptr || checkType(c,o,OBJ_LIST)) return;
|
||||
long index;
|
||||
robj *value = NULL;
|
||||
|
||||
@ -396,13 +396,13 @@ void rpopCommand(client *c) {
|
||||
}
|
||||
|
||||
void lrangeCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
long start, end, llen, rangelen;
|
||||
|
||||
if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||
|
||||
(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;
|
||||
llen = listTypeLength(o);
|
||||
|
||||
|
@ -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
|
||||
* an integer-encodable value, an intset will be returned. Otherwise a regular
|
||||
* hash table. */
|
||||
robj *setTypeCreate(sds value) {
|
||||
robj *setTypeCreate(const char *value) {
|
||||
if (isSdsRepresentableAsLongLong(value,NULL) == C_OK)
|
||||
return createIntsetObject();
|
||||
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
|
||||
* 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;
|
||||
if (subject->encoding == OBJ_ENCODING_HT) {
|
||||
dict *ht = (dict*)subject->m_ptr;
|
||||
dictEntry *de = dictAddRaw(ht,value,NULL);
|
||||
dictEntry *de = dictAddRaw(ht,(char*)value,NULL);
|
||||
if (de) {
|
||||
dictSetKey(ht,de,sdsdup(value));
|
||||
dictSetVal(ht,de,NULL);
|
||||
@ -85,7 +85,7 @@ int setTypeAdd(robj *subject, sds value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setTypeRemove(robj *setobj, sds value) {
|
||||
int setTypeRemove(robj *setobj, const char *value) {
|
||||
long long llval;
|
||||
if (setobj->encoding == OBJ_ENCODING_HT) {
|
||||
if (dictDelete((dict*)setobj->m_ptr,value) == DICT_OK) {
|
||||
@ -104,7 +104,7 @@ int setTypeRemove(robj *setobj, sds value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setTypeIsMember(robj *subject, sds value) {
|
||||
int setTypeIsMember(robj_roptr subject, const char *value) {
|
||||
long long llval;
|
||||
if (subject->encoding == OBJ_ENCODING_HT) {
|
||||
return dictFind((dict*)subject->m_ptr,value) != NULL;
|
||||
@ -118,7 +118,7 @@ int setTypeIsMember(robj *subject, sds value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
setTypeIterator *setTypeInitIterator(robj *subject) {
|
||||
setTypeIterator *setTypeInitIterator(robj_roptr subject) {
|
||||
setTypeIterator *si = (setTypeIterator*)zmalloc(sizeof(setTypeIterator), MALLOC_LOCAL);
|
||||
si->subject = subject;
|
||||
si->encoding = subject->encoding;
|
||||
@ -151,7 +151,7 @@ void setTypeReleaseIterator(setTypeIterator *si) {
|
||||
* used field with values which are easy to trap if misused.
|
||||
*
|
||||
* 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) {
|
||||
dictEntry *de = dictNext(si->di);
|
||||
if (de == NULL) return -1;
|
||||
@ -176,7 +176,7 @@ int setTypeNext(setTypeIterator *si, sds *sdsele, int64_t *llele) {
|
||||
* an issue. */
|
||||
sds setTypeNextObject(setTypeIterator *si) {
|
||||
int64_t intele;
|
||||
sds sdsele;
|
||||
const char *sdsele;
|
||||
int encoding;
|
||||
|
||||
encoding = setTypeNext(si,&sdsele,&intele);
|
||||
@ -219,7 +219,12 @@ int setTypeRandomElement(robj *setobj, sds *sdsele, int64_t *llele) {
|
||||
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) {
|
||||
return dictSize((const dict*)subject->m_ptr);
|
||||
} else if (subject->encoding == OBJ_ENCODING_INTSET) {
|
||||
@ -240,7 +245,7 @@ void setTypeConvert(robj *setobj, int enc) {
|
||||
if (enc == OBJ_ENCODING_HT) {
|
||||
int64_t intele;
|
||||
dict *d = dictCreate(&setDictType,NULL);
|
||||
sds element;
|
||||
const char *element;
|
||||
|
||||
/* Presize the dict to avoid rehashing */
|
||||
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 */
|
||||
si = setTypeInitIterator(setobj);
|
||||
while (setTypeNext(si,&element,&intele) != -1) {
|
||||
element = sdsfromlonglong(intele);
|
||||
serverAssert(dictAdd(d,element,NULL) == DICT_OK);
|
||||
sds elementNew = sdsfromlonglong(intele);
|
||||
serverAssert(dictAdd(d,elementNew,NULL) == DICT_OK);
|
||||
}
|
||||
setTypeReleaseIterator(si);
|
||||
|
||||
@ -371,9 +376,9 @@ void smoveCommand(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;
|
||||
|
||||
if (setTypeIsMember(set,szFromObj(c->argv[2])))
|
||||
@ -383,9 +388,9 @@ void sismemberCommand(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;
|
||||
|
||||
addReplyLongLong(c,setTypeSize(o));
|
||||
@ -458,7 +463,7 @@ void spopWithCountCommand(client *c) {
|
||||
addReplySetLen(c,count);
|
||||
|
||||
/* Common iteration vars. */
|
||||
sds sdsele;
|
||||
const char *sdsele;
|
||||
robj *objele;
|
||||
int encoding;
|
||||
int64_t llele;
|
||||
@ -615,8 +620,8 @@ void srandmemberWithCountCommand(client *c) {
|
||||
long l;
|
||||
unsigned long count, size;
|
||||
int uniq = 1;
|
||||
robj *set;
|
||||
sds ele;
|
||||
robj_roptr set;
|
||||
const char *ele;
|
||||
int64_t llele;
|
||||
int encoding;
|
||||
|
||||
@ -633,7 +638,7 @@ void srandmemberWithCountCommand(client *c) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* If count is zero, serve it ASAP to avoid special cases later. */
|
||||
@ -747,8 +752,8 @@ void srandmemberWithCountCommand(client *c) {
|
||||
}
|
||||
|
||||
void srandmemberCommand(client *c) {
|
||||
robj *set;
|
||||
sds ele;
|
||||
robj_roptr set;
|
||||
const char *ele;
|
||||
int64_t llele;
|
||||
int encoding;
|
||||
|
||||
@ -761,7 +766,7 @@ void srandmemberCommand(client *c) {
|
||||
}
|
||||
|
||||
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);
|
||||
if (encoding == OBJ_ENCODING_INTSET) {
|
||||
@ -794,7 +799,7 @@ void sinterGenericCommand(client *c, robj **setkeys,
|
||||
robj **sets = (robj**)zmalloc(sizeof(robj*)*setnum, MALLOC_SHARED);
|
||||
setTypeIterator *si;
|
||||
robj *dstset = NULL;
|
||||
sds elesds;
|
||||
const char *elesds;
|
||||
int64_t intobj;
|
||||
void *replylen = NULL;
|
||||
unsigned long j, cardinality = 0;
|
||||
@ -803,7 +808,7 @@ void sinterGenericCommand(client *c, robj **setkeys,
|
||||
for (j = 0; j < setnum; j++) {
|
||||
robj *setobj = dstkey ?
|
||||
lookupKeyWrite(c->db,setkeys[j]) :
|
||||
lookupKeyRead(c->db,setkeys[j]);
|
||||
lookupKeyRead(c->db,setkeys[j]).unsafe_robjcast();
|
||||
if (!setobj) {
|
||||
zfree(sets);
|
||||
if (dstkey) {
|
||||
@ -943,7 +948,7 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
|
||||
for (j = 0; j < setnum; j++) {
|
||||
robj *setobj = dstkey ?
|
||||
lookupKeyWrite(c->db,setkeys[j]) :
|
||||
lookupKeyRead(c->db,setkeys[j]);
|
||||
lookupKeyRead(c->db,setkeys[j]).unsafe_robjcast();
|
||||
if (!setobj) {
|
||||
sets[j] = NULL;
|
||||
continue;
|
||||
@ -1109,11 +1114,11 @@ void sdiffstoreCommand(client *c) {
|
||||
}
|
||||
|
||||
void sscanCommand(client *c) {
|
||||
robj *set;
|
||||
robj_roptr set;
|
||||
unsigned long cursor;
|
||||
|
||||
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;
|
||||
scanGenericCommand(c,set,cursor);
|
||||
}
|
||||
|
@ -1266,7 +1266,7 @@ void xaddCommand(client *c) {
|
||||
|
||||
/* XRANGE/XREVRANGE actual implementation. */
|
||||
void xrangeGenericCommand(client *c, int rev) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
stream *s;
|
||||
streamID startid, endid;
|
||||
long long count = -1;
|
||||
@ -1293,7 +1293,7 @@ void xrangeGenericCommand(client *c, int rev) {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
s = (stream*)ptrFromObj(o);
|
||||
@ -1318,8 +1318,8 @@ void xrevrangeCommand(client *c) {
|
||||
|
||||
/* XLEN */
|
||||
void xlenCommand(client *c) {
|
||||
robj *o;
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL
|
||||
robj_roptr o;
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr
|
||||
|| checkType(c,o,OBJ_STREAM)) return;
|
||||
stream *s = (stream*)ptrFromObj(o);
|
||||
addReplyLongLong(c,s->length);
|
||||
@ -1419,14 +1419,14 @@ void xreadCommand(client *c) {
|
||||
* starting from now. */
|
||||
int id_idx = i - streams_arg - 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;
|
||||
streamCG *group = NULL;
|
||||
|
||||
/* If a group was specified, than we need to be sure that the
|
||||
* key and group actually exist. */
|
||||
if (groupname) {
|
||||
if (o == NULL ||
|
||||
if (o == nullptr ||
|
||||
(group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(groupname))) == NULL)
|
||||
{
|
||||
addReplyErrorFormat(c, "-NOGROUP No such key '%s' or consumer "
|
||||
@ -1475,8 +1475,8 @@ void xreadCommand(client *c) {
|
||||
|
||||
/* Try to serve the client synchronously. */
|
||||
for (int i = 0; i < streams_count; i++) {
|
||||
robj *o = lookupKeyRead(c->db,c->argv[streams_arg+i]);
|
||||
if (o == NULL) continue;
|
||||
robj_roptr o = lookupKeyRead(c->db,c->argv[streams_arg+i]);
|
||||
if (o == nullptr) continue;
|
||||
stream *s = (stream*)ptrFromObj(o);
|
||||
streamID *gt = ids+i; /* ID must be greater than this. */
|
||||
int serve_synchronously = 0;
|
||||
@ -1887,14 +1887,14 @@ void xsetidCommand(client *c) {
|
||||
*/
|
||||
void xackCommand(client *c) {
|
||||
streamCG *group = NULL;
|
||||
robj *o = lookupKeyRead(c->db,c->argv[1]);
|
||||
robj_roptr o = lookupKeyRead(c->db,c->argv[1]);
|
||||
if (o) {
|
||||
if (checkType(c,o,OBJ_STREAM)) return; /* Type error. */
|
||||
group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(c->argv[2]));
|
||||
}
|
||||
|
||||
/* No key or group? Nothing to ack. */
|
||||
if (o == NULL || group == NULL) {
|
||||
if (o == nullptr || group == NULL) {
|
||||
addReply(c,shared.czero);
|
||||
return;
|
||||
}
|
||||
@ -1958,11 +1958,11 @@ void xpendingCommand(client *c) {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (o && checkType(c,o,OBJ_STREAM)) return;
|
||||
if (o == NULL ||
|
||||
if (o == nullptr ||
|
||||
(group = streamLookupCG((stream*)ptrFromObj(o),szFromObj(groupname))) == NULL)
|
||||
{
|
||||
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. */
|
||||
void xclaimCommand(client *c) {
|
||||
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 retrycount = -1; /* -1 means RETRYCOUNT option 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
|
||||
* is mandatory. */
|
||||
if (o == NULL || group == NULL) {
|
||||
if (o == nullptr || group == NULL) {
|
||||
addReplyErrorFormat(c,"-NOGROUP No such key '%s' or "
|
||||
"consumer group '%s'", (char*)ptrFromObj(c->argv[1]),
|
||||
(char*)ptrFromObj(c->argv[2]));
|
||||
|
@ -155,9 +155,9 @@ void psetexCommand(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;
|
||||
|
||||
if (o->type != OBJ_STRING) {
|
||||
@ -242,23 +242,24 @@ void setrangeCommand(client *c) {
|
||||
}
|
||||
|
||||
void getrangeCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
long long start, end;
|
||||
char *str, llbuf[32];
|
||||
const char *str;
|
||||
char llbuf[32];
|
||||
size_t strlen;
|
||||
|
||||
if (getLongLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK)
|
||||
return;
|
||||
if (getLongLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)
|
||||
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;
|
||||
|
||||
if (o->encoding == OBJ_ENCODING_INT) {
|
||||
str = llbuf;
|
||||
strlen = ll2string(llbuf,sizeof(llbuf),(long)ptrFromObj(o));
|
||||
} else {
|
||||
str = (char*)ptrFromObj(o);
|
||||
str = szFromObj(o);
|
||||
strlen = sdslen(str);
|
||||
}
|
||||
|
||||
@ -287,8 +288,8 @@ void mgetCommand(client *c) {
|
||||
|
||||
addReplyArrayLen(c,c->argc-1);
|
||||
for (j = 1; j < c->argc; j++) {
|
||||
robj *o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == NULL) {
|
||||
robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
|
||||
if (o == nullptr) {
|
||||
addReplyNull(c);
|
||||
} else {
|
||||
if (o->type != OBJ_STRING) {
|
||||
@ -464,8 +465,8 @@ void appendCommand(client *c) {
|
||||
}
|
||||
|
||||
void strlenCommand(client *c) {
|
||||
robj *o;
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
|
||||
robj_roptr o;
|
||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == nullptr ||
|
||||
checkType(c,o,OBJ_STRING)) return;
|
||||
addReplyLongLong(c,stringObjectLen(o));
|
||||
}
|
||||
|
@ -777,7 +777,7 @@ int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int cl
|
||||
return cmp;
|
||||
}
|
||||
|
||||
unsigned int zzlLength(unsigned char *zl) {
|
||||
unsigned int zzlLength(const unsigned char *zl) {
|
||||
return ziplistLen(zl)/2;
|
||||
}
|
||||
|
||||
@ -1153,10 +1153,10 @@ unsigned char *zzlDeleteRangeByRank(unsigned char *zl, unsigned int start, unsig
|
||||
* Common sorted set API
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
unsigned long zsetLength(const robj *zobj) {
|
||||
unsigned long zsetLength(robj_roptr zobj) {
|
||||
unsigned long length = 0;
|
||||
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) {
|
||||
length = ((const zset*)zobj->m_ptr)->zsl->length;
|
||||
} 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
|
||||
* otherwise C_OK is returned and *score is correctly populated.
|
||||
* 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->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 rank is computed considering as element with rank 0 the one with
|
||||
* 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 rank;
|
||||
|
||||
@ -2410,7 +2410,7 @@ void zinterstoreCommand(client *c) {
|
||||
|
||||
void zrangeGenericCommand(client *c, int reverse) {
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
int withscores = 0;
|
||||
long start;
|
||||
long end;
|
||||
@ -2427,7 +2427,7 @@ void zrangeGenericCommand(client *c, int reverse) {
|
||||
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;
|
||||
|
||||
/* Sanitize indexes. */
|
||||
@ -2527,7 +2527,7 @@ void zrevrangeCommand(client *c) {
|
||||
void genericZrangebyscoreCommand(client *c, int reverse) {
|
||||
zrangespec range;
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
long offset = 0, limit = -1;
|
||||
int withscores = 0;
|
||||
unsigned long rangelen = 0;
|
||||
@ -2575,7 +2575,7 @@ void genericZrangebyscoreCommand(client *c, int reverse) {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
@ -2719,7 +2719,7 @@ void zrevrangebyscoreCommand(client *c) {
|
||||
|
||||
void zcountCommand(client *c) {
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
zrangespec range;
|
||||
unsigned long count = 0;
|
||||
|
||||
@ -2730,7 +2730,7 @@ void zcountCommand(client *c) {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
@ -2796,7 +2796,7 @@ void zcountCommand(client *c) {
|
||||
|
||||
void zlexcountCommand(client *c) {
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
zlexrangespec range;
|
||||
unsigned long count = 0;
|
||||
|
||||
@ -2807,7 +2807,7 @@ void zlexcountCommand(client *c) {
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
zslFreeLexRange(&range);
|
||||
@ -2877,7 +2877,7 @@ void zlexcountCommand(client *c) {
|
||||
void genericZrangebylexCommand(client *c, int reverse) {
|
||||
zlexrangespec range;
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
long offset = 0, limit = -1;
|
||||
unsigned long rangelen = 0;
|
||||
void *replylen = NULL;
|
||||
@ -2920,7 +2920,7 @@ void genericZrangebylexCommand(client *c, int reverse) {
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
zslFreeLexRange(&range);
|
||||
@ -3063,9 +3063,9 @@ void zrevrangebylexCommand(client *c) {
|
||||
|
||||
void zcardCommand(client *c) {
|
||||
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;
|
||||
|
||||
addReplyLongLong(c,zsetLength(zobj));
|
||||
@ -3073,10 +3073,10 @@ void zcardCommand(client *c) {
|
||||
|
||||
void zscoreCommand(client *c) {
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
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;
|
||||
|
||||
if (zsetScore(zobj,szFromObj(c->argv[2]),&score) == C_ERR) {
|
||||
@ -3089,10 +3089,10 @@ void zscoreCommand(client *c) {
|
||||
void zrankGenericCommand(client *c, int reverse) {
|
||||
robj *key = c->argv[1];
|
||||
robj *ele = c->argv[2];
|
||||
robj *zobj;
|
||||
robj_roptr zobj;
|
||||
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;
|
||||
|
||||
serverAssertWithInfo(c,ele,sdsEncodedObject(ele));
|
||||
@ -3113,11 +3113,11 @@ void zrevrankCommand(client *c) {
|
||||
}
|
||||
|
||||
void zscanCommand(client *c) {
|
||||
robj *o;
|
||||
robj_roptr o;
|
||||
unsigned long cursor;
|
||||
|
||||
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;
|
||||
scanGenericCommand(c,o,cursor);
|
||||
}
|
||||
|
@ -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'. */
|
||||
unsigned int zipRawEntryLength(unsigned char *p) {
|
||||
unsigned int zipRawEntryLength(const unsigned char *p) {
|
||||
unsigned int prevlensize, encoding, lensize, len;
|
||||
ZIP_DECODE_PREVLENSIZE(p, prevlensize);
|
||||
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. */
|
||||
unsigned int ziplistLen(unsigned char *zl) {
|
||||
unsigned int ziplistLen(const unsigned char *zl) {
|
||||
unsigned int len = 0;
|
||||
if (intrev16ifbe(ZIPLIST_LENGTH(zl)) < UINT16_MAX) {
|
||||
len = intrev16ifbe(ZIPLIST_LENGTH(zl));
|
||||
} else {
|
||||
unsigned char *p = zl+ZIPLIST_HEADER_SIZE;
|
||||
const unsigned char *p = zl+ZIPLIST_HEADER_SIZE;
|
||||
while (*p != ZIP_END) {
|
||||
p += zipRawEntryLength(p);
|
||||
len++;
|
||||
|
@ -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 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 int ziplistLen(unsigned char *zl);
|
||||
unsigned int ziplistLen(const unsigned char *zl);
|
||||
size_t ziplistBlobLen(unsigned char *zl);
|
||||
void ziplistRepr(unsigned char *zl);
|
||||
|
||||
|
@ -205,7 +205,7 @@ size_t zmalloc_usable(void *ptr) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void zfree(void *ptr) {
|
||||
void zfree(const void *ptr) {
|
||||
#ifndef HAVE_MALLOC_SIZE
|
||||
void *realptr;
|
||||
size_t oldsize;
|
||||
@ -213,8 +213,8 @@ void zfree(void *ptr) {
|
||||
|
||||
if (ptr == NULL) return;
|
||||
#ifdef HAVE_MALLOC_SIZE
|
||||
update_zmalloc_stat_free(zmalloc_size(ptr));
|
||||
free(ptr);
|
||||
update_zmalloc_stat_free(zmalloc_size((void*)ptr));
|
||||
free((void*)ptr);
|
||||
#else
|
||||
realptr = (char*)ptr-PREFIX_SIZE;
|
||||
oldsize = *((size_t*)realptr);
|
||||
|
@ -89,7 +89,7 @@ extern "C" {
|
||||
void *zmalloc(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 zfree(void *ptr);
|
||||
void zfree(const void *ptr);
|
||||
char *zstrdup(const char *s);
|
||||
size_t zmalloc_used_memory(void);
|
||||
void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
|
||||
|
Loading…
x
Reference in New Issue
Block a user