Move remaning files dependent on server.h over to C++
Former-commit-id: 8c133b605c65212b023d35b3cb71e63b6a4c443a
This commit is contained in:
parent
e766f66b11
commit
7859e0562f
10
deps/hiredis/sds.h
vendored
10
deps/hiredis/sds.h
vendored
@ -45,31 +45,41 @@ typedef char *sds;
|
|||||||
* However is here to document the layout of type 5 SDS strings. */
|
* However is here to document the layout of type 5 SDS strings. */
|
||||||
struct __attribute__ ((__packed__)) sdshdr5 {
|
struct __attribute__ ((__packed__)) sdshdr5 {
|
||||||
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
|
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
|
||||||
|
#ifndef __cplusplus
|
||||||
char buf[];
|
char buf[];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
struct __attribute__ ((__packed__)) sdshdr8 {
|
struct __attribute__ ((__packed__)) sdshdr8 {
|
||||||
uint8_t len; /* used */
|
uint8_t len; /* used */
|
||||||
uint8_t alloc; /* excluding the header and null terminator */
|
uint8_t alloc; /* excluding the header and null terminator */
|
||||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||||
|
#ifndef __cplusplus
|
||||||
char buf[];
|
char buf[];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
struct __attribute__ ((__packed__)) sdshdr16 {
|
struct __attribute__ ((__packed__)) sdshdr16 {
|
||||||
uint16_t len; /* used */
|
uint16_t len; /* used */
|
||||||
uint16_t alloc; /* excluding the header and null terminator */
|
uint16_t alloc; /* excluding the header and null terminator */
|
||||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||||
|
#ifndef __cplusplus
|
||||||
char buf[];
|
char buf[];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
struct __attribute__ ((__packed__)) sdshdr32 {
|
struct __attribute__ ((__packed__)) sdshdr32 {
|
||||||
uint32_t len; /* used */
|
uint32_t len; /* used */
|
||||||
uint32_t alloc; /* excluding the header and null terminator */
|
uint32_t alloc; /* excluding the header and null terminator */
|
||||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||||
|
#ifndef __cplusplus
|
||||||
char buf[];
|
char buf[];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
struct __attribute__ ((__packed__)) sdshdr64 {
|
struct __attribute__ ((__packed__)) sdshdr64 {
|
||||||
uint64_t len; /* used */
|
uint64_t len; /* used */
|
||||||
uint64_t alloc; /* excluding the header and null terminator */
|
uint64_t alloc; /* excluding the header and null terminator */
|
||||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||||
|
#ifndef __cplusplus
|
||||||
char buf[];
|
char buf[];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SDS_TYPE_5 0
|
#define SDS_TYPE_5 0
|
||||||
|
@ -197,9 +197,9 @@ endif
|
|||||||
|
|
||||||
REDIS_SERVER_NAME=keydb-server
|
REDIS_SERVER_NAME=keydb-server
|
||||||
REDIS_SENTINEL_NAME=keydb-sentinel
|
REDIS_SENTINEL_NAME=keydb-sentinel
|
||||||
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o acl.o storage.o rdb-s3.o fastlock.o gopher.o $(ASM_OBJ)
|
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o acl.o storage.o rdb-s3.o fastlock.o $(ASM_OBJ)
|
||||||
REDIS_CLI_NAME=keydb-cli
|
REDIS_CLI_NAME=keydb-cli
|
||||||
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o $(ASM_OBJ)
|
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o $(ASM_OBJ)
|
||||||
REDIS_BENCHMARK_NAME=keydb-benchmark
|
REDIS_BENCHMARK_NAME=keydb-benchmark
|
||||||
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o redis-benchmark.o storage-lite.o fastlock.o $(ASM_OBJ)
|
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o redis-benchmark.o storage-lite.o fastlock.o $(ASM_OBJ)
|
||||||
REDIS_CHECK_RDB_NAME=keydb-check-rdb
|
REDIS_CHECK_RDB_NAME=keydb-check-rdb
|
||||||
|
@ -157,17 +157,17 @@ uint64_t ACLGetCommandCategoryFlagByName(const char *name) {
|
|||||||
/* Method for passwords/pattern comparison used for the user->passwords list
|
/* Method for passwords/pattern comparison used for the user->passwords list
|
||||||
* so that we can search for items with listSearchKey(). */
|
* so that we can search for items with listSearchKey(). */
|
||||||
int ACLListMatchSds(void *a, void *b) {
|
int ACLListMatchSds(void *a, void *b) {
|
||||||
return sdscmp(a,b) == 0;
|
return sdscmp((sds)a,(sds)b) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Method to free list elements from ACL users password/ptterns lists. */
|
/* Method to free list elements from ACL users password/ptterns lists. */
|
||||||
void ACLListFreeSds(void *item) {
|
void ACLListFreeSds(void *item) {
|
||||||
sdsfree(item);
|
sdsfree((sds)item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Method to duplicate list elements from ACL users password/ptterns lists. */
|
/* Method to duplicate list elements from ACL users password/ptterns lists. */
|
||||||
void *ACLListDupSds(void *item) {
|
void *ACLListDupSds(void *item) {
|
||||||
return sdsdup(item);
|
return sdsdup((sds)item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new user with the specified name, store it in the list
|
/* Create a new user with the specified name, store it in the list
|
||||||
@ -177,7 +177,7 @@ void *ACLListDupSds(void *item) {
|
|||||||
* If the user with such name already exists NULL is returned. */
|
* If the user with such name already exists NULL is returned. */
|
||||||
user *ACLCreateUser(const char *name, size_t namelen) {
|
user *ACLCreateUser(const char *name, size_t namelen) {
|
||||||
if (raxFind(Users,(unsigned char*)name,namelen) != raxNotFound) return NULL;
|
if (raxFind(Users,(unsigned char*)name,namelen) != raxNotFound) return NULL;
|
||||||
user *u = zmalloc(sizeof(*u), MALLOC_LOCAL);
|
user *u = (user*)zmalloc(sizeof(*u), MALLOC_LOCAL);
|
||||||
u->name = sdsnewlen(name,namelen);
|
u->name = sdsnewlen(name,namelen);
|
||||||
u->flags = USER_FLAG_DISABLED;
|
u->flags = USER_FLAG_DISABLED;
|
||||||
u->allowed_subcommands = NULL;
|
u->allowed_subcommands = NULL;
|
||||||
@ -229,7 +229,7 @@ void ACLFreeUserAndKillClients(user *u) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
listRewind(server.clients,&li);
|
listRewind(server.clients,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
client *c = listNodeValue(ln);
|
client *c = (client*)listNodeValue(ln);
|
||||||
if (c->puser == u) {
|
if (c->puser == u) {
|
||||||
/* We'll free the conenction asynchronously, so
|
/* We'll free the conenction asynchronously, so
|
||||||
* in theory to set a different user is not needed.
|
* in theory to set a different user is not needed.
|
||||||
@ -337,7 +337,7 @@ int ACLSetUserCommandBitsForCategory(user *u, const char *category, int value) {
|
|||||||
dictIterator *di = dictGetIterator(server.orig_commands);
|
dictIterator *di = dictGetIterator(server.orig_commands);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
while ((de = dictNext(di)) != NULL) {
|
while ((de = dictNext(di)) != NULL) {
|
||||||
struct redisCommand *cmd = dictGetVal(de);
|
struct redisCommand *cmd = (redisCommand*)dictGetVal(de);
|
||||||
if (cmd->flags & CMD_MODULE) continue; /* Ignore modules commands. */
|
if (cmd->flags & CMD_MODULE) continue; /* Ignore modules commands. */
|
||||||
if (cmd->flags & cflag) {
|
if (cmd->flags & cflag) {
|
||||||
ACLSetUserCommandBit(u,cmd->id,value);
|
ACLSetUserCommandBit(u,cmd->id,value);
|
||||||
@ -362,7 +362,7 @@ int ACLCountCategoryBitsForUser(user *u, unsigned long *on, unsigned long *off,
|
|||||||
dictIterator *di = dictGetIterator(server.orig_commands);
|
dictIterator *di = dictGetIterator(server.orig_commands);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
while ((de = dictNext(di)) != NULL) {
|
while ((de = dictNext(di)) != NULL) {
|
||||||
struct redisCommand *cmd = dictGetVal(de);
|
struct redisCommand *cmd = (redisCommand*)dictGetVal(de);
|
||||||
if (cmd->flags & cflag) {
|
if (cmd->flags & cflag) {
|
||||||
if (ACLGetUserCommandBit(u,cmd->id))
|
if (ACLGetUserCommandBit(u,cmd->id))
|
||||||
(*on)++;
|
(*on)++;
|
||||||
@ -431,7 +431,7 @@ sds ACLDescribeUserCommandRules(user *u) {
|
|||||||
dictIterator *di = dictGetIterator(server.orig_commands);
|
dictIterator *di = dictGetIterator(server.orig_commands);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
while ((de = dictNext(di)) != NULL) {
|
while ((de = dictNext(di)) != NULL) {
|
||||||
struct redisCommand *cmd = dictGetVal(de);
|
struct redisCommand *cmd = (redisCommand*)dictGetVal(de);
|
||||||
int userbit = ACLGetUserCommandBit(u,cmd->id);
|
int userbit = ACLGetUserCommandBit(u,cmd->id);
|
||||||
int fakebit = ACLGetUserCommandBit(fakeuser,cmd->id);
|
int fakebit = ACLGetUserCommandBit(fakeuser,cmd->id);
|
||||||
if (userbit != fakebit) {
|
if (userbit != fakebit) {
|
||||||
@ -501,7 +501,7 @@ sds ACLDescribeUser(user *u) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
listRewind(u->passwords,&li);
|
listRewind(u->passwords,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
sds thispass = listNodeValue(ln);
|
sds thispass = (sds)listNodeValue(ln);
|
||||||
res = sdscatlen(res,">",1);
|
res = sdscatlen(res,">",1);
|
||||||
res = sdscatsds(res,thispass);
|
res = sdscatsds(res,thispass);
|
||||||
res = sdscatlen(res," ",1);
|
res = sdscatlen(res," ",1);
|
||||||
@ -513,7 +513,7 @@ sds ACLDescribeUser(user *u) {
|
|||||||
} else {
|
} else {
|
||||||
listRewind(u->patterns,&li);
|
listRewind(u->patterns,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
sds thispat = listNodeValue(ln);
|
sds thispat = (sds)listNodeValue(ln);
|
||||||
res = sdscatlen(res,"~",1);
|
res = sdscatlen(res,"~",1);
|
||||||
res = sdscatsds(res,thispat);
|
res = sdscatsds(res,thispat);
|
||||||
res = sdscatlen(res," ",1);
|
res = sdscatlen(res," ",1);
|
||||||
@ -533,7 +533,7 @@ sds ACLDescribeUser(user *u) {
|
|||||||
struct redisCommand *ACLLookupCommand(const char *name) {
|
struct redisCommand *ACLLookupCommand(const char *name) {
|
||||||
struct redisCommand *cmd;
|
struct redisCommand *cmd;
|
||||||
sds sdsname = sdsnew(name);
|
sds sdsname = sdsnew(name);
|
||||||
cmd = dictFetchValue(server.orig_commands, sdsname);
|
cmd = (redisCommand*)dictFetchValue(server.orig_commands, sdsname);
|
||||||
sdsfree(sdsname);
|
sdsfree(sdsname);
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
@ -570,7 +570,7 @@ void ACLAddAllowedSubcommand(user *u, unsigned long id, const char *sub) {
|
|||||||
/* If this is the first subcommand to be configured for
|
/* If this is the first subcommand to be configured for
|
||||||
* this user, we have to allocate the subcommands array. */
|
* this user, we have to allocate the subcommands array. */
|
||||||
if (u->allowed_subcommands == NULL) {
|
if (u->allowed_subcommands == NULL) {
|
||||||
u->allowed_subcommands = zcalloc(USER_COMMAND_BITS_COUNT *
|
u->allowed_subcommands = (sds**)zcalloc(USER_COMMAND_BITS_COUNT *
|
||||||
sizeof(sds*), MALLOC_LOCAL);
|
sizeof(sds*), MALLOC_LOCAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +589,7 @@ void ACLAddAllowedSubcommand(user *u, unsigned long id, const char *sub) {
|
|||||||
|
|
||||||
/* Now we can make space for the new item (and the null term). */
|
/* Now we can make space for the new item (and the null term). */
|
||||||
items += 2;
|
items += 2;
|
||||||
u->allowed_subcommands[id] = zrealloc(u->allowed_subcommands[id],
|
u->allowed_subcommands[id] = (sds*)zrealloc(u->allowed_subcommands[id],
|
||||||
sizeof(sds)*items, MALLOC_LOCAL);
|
sizeof(sds)*items, MALLOC_LOCAL);
|
||||||
u->allowed_subcommands[id][items-2] = sdsnew(sub);
|
u->allowed_subcommands[id][items-2] = sdsnew(sub);
|
||||||
u->allowed_subcommands[id][items-1] = NULL;
|
u->allowed_subcommands[id][items-1] = NULL;
|
||||||
@ -802,8 +802,8 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) {
|
|||||||
|
|
||||||
/* Return a description of the error that occurred in ACLSetUser() according to
|
/* Return a description of the error that occurred in ACLSetUser() according to
|
||||||
* the errno value set by the function on error. */
|
* the errno value set by the function on error. */
|
||||||
char *ACLSetUserStringError(void) {
|
const char *ACLSetUserStringError(void) {
|
||||||
char *errmsg = "Wrong format";
|
const char *errmsg = "Wrong format";
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
errmsg = "Unknown command or category name in ACL";
|
errmsg = "Unknown command or category name in ACL";
|
||||||
else if (errno == EINVAL)
|
else if (errno == EINVAL)
|
||||||
@ -830,7 +830,7 @@ char *ACLSetUserStringError(void) {
|
|||||||
sds ACLDefaultUserFirstPassword(void) {
|
sds ACLDefaultUserFirstPassword(void) {
|
||||||
if (listLength(DefaultUser->passwords) == 0) return NULL;
|
if (listLength(DefaultUser->passwords) == 0) return NULL;
|
||||||
listNode *first = listFirst(DefaultUser->passwords);
|
listNode *first = listFirst(DefaultUser->passwords);
|
||||||
return listNodeValue(first);
|
return (sds)listNodeValue(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the default user, that will always exist for all the process
|
/* Initialize the default user, that will always exist for all the process
|
||||||
@ -857,7 +857,7 @@ void ACLInit(void) {
|
|||||||
* ENONENT: if the specified user does not exist at all.
|
* ENONENT: if the specified user does not exist at all.
|
||||||
*/
|
*/
|
||||||
int ACLCheckUserCredentials(robj *username, robj *password) {
|
int ACLCheckUserCredentials(robj *username, robj *password) {
|
||||||
user *u = ACLGetUserByName(ptrFromObj(username),sdslen(ptrFromObj(username)));
|
user *u = ACLGetUserByName(szFromObj(username),sdslen(szFromObj(username)));
|
||||||
if (u == NULL) {
|
if (u == NULL) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return C_ERR;
|
return C_ERR;
|
||||||
@ -878,8 +878,8 @@ int ACLCheckUserCredentials(robj *username, robj *password) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
listRewind(u->passwords,&li);
|
listRewind(u->passwords,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
sds thispass = listNodeValue(ln);
|
sds thispass = (sds)listNodeValue(ln);
|
||||||
if (!time_independent_strcmp(ptrFromObj(password), thispass))
|
if (!time_independent_strcmp(szFromObj(password), thispass))
|
||||||
return C_OK;
|
return C_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -944,7 +944,7 @@ unsigned long ACLGetCommandID(const char *cmdname) {
|
|||||||
user *ACLGetUserByName(const char *name, size_t namelen) {
|
user *ACLGetUserByName(const char *name, size_t namelen) {
|
||||||
void *myuser = raxFind(Users,(unsigned char*)name,namelen);
|
void *myuser = raxFind(Users,(unsigned char*)name,namelen);
|
||||||
if (myuser == raxNotFound) return NULL;
|
if (myuser == raxNotFound) return NULL;
|
||||||
return myuser;
|
return (user*)myuser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the command ready to be excuted in the client 'c', and already
|
/* Check if the command ready to be excuted in the client 'c', and already
|
||||||
@ -982,7 +982,7 @@ int ACLCheckCommandPerm(client *c) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
if (u->allowed_subcommands[id][subid] == NULL)
|
if (u->allowed_subcommands[id][subid] == NULL)
|
||||||
return ACL_DENIED_CMD;
|
return ACL_DENIED_CMD;
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[1]),
|
if (!strcasecmp(szFromObj(c->argv[1]),
|
||||||
u->allowed_subcommands[id][subid]))
|
u->allowed_subcommands[id][subid]))
|
||||||
break; /* Subcommand match found. Stop here. */
|
break; /* Subcommand match found. Stop here. */
|
||||||
subid++;
|
subid++;
|
||||||
@ -1005,11 +1005,11 @@ int ACLCheckCommandPerm(client *c) {
|
|||||||
/* Test this key against every pattern. */
|
/* Test this key against every pattern. */
|
||||||
int match = 0;
|
int match = 0;
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
sds pattern = listNodeValue(ln);
|
sds pattern = (sds)listNodeValue(ln);
|
||||||
size_t plen = sdslen(pattern);
|
size_t plen = sdslen(pattern);
|
||||||
int idx = keyidx[j];
|
int idx = keyidx[j];
|
||||||
if (stringmatchlen(pattern,plen,ptrFromObj(c->argv[idx]),
|
if (stringmatchlen(pattern,plen,szFromObj(c->argv[idx]),
|
||||||
sdslen(ptrFromObj(c->argv[idx])),0))
|
sdslen(szFromObj(c->argv[idx])),0))
|
||||||
{
|
{
|
||||||
match = 1;
|
match = 1;
|
||||||
break;
|
break;
|
||||||
@ -1071,7 +1071,7 @@ int ACLAppendUserForLoading(sds *argv, int argc, int *argc_err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rules look valid, let's append the user to the list. */
|
/* Rules look valid, let's append the user to the list. */
|
||||||
sds *copy = zmalloc(sizeof(sds)*argc, MALLOC_LOCAL);
|
sds *copy = (sds*)zmalloc(sizeof(sds)*argc, MALLOC_LOCAL);
|
||||||
for (int j = 1; j < argc; j++) copy[j-1] = sdsdup(argv[j]);
|
for (int j = 1; j < argc; j++) copy[j-1] = sdsdup(argv[j]);
|
||||||
copy[argc-1] = NULL;
|
copy[argc-1] = NULL;
|
||||||
listAddNodeTail(UsersToLoad,copy);
|
listAddNodeTail(UsersToLoad,copy);
|
||||||
@ -1087,7 +1087,7 @@ int ACLLoadConfiguredUsers(void) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
listRewind(UsersToLoad,&li);
|
listRewind(UsersToLoad,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
sds *aclrules = listNodeValue(ln);
|
sds *aclrules = (sds*)listNodeValue(ln);
|
||||||
sds username = aclrules[0];
|
sds username = aclrules[0];
|
||||||
user *u = ACLCreateUser(username,sdslen(username));
|
user *u = ACLCreateUser(username,sdslen(username));
|
||||||
if (!u) {
|
if (!u) {
|
||||||
@ -1099,7 +1099,7 @@ int ACLLoadConfiguredUsers(void) {
|
|||||||
/* Load every rule defined for this user. */
|
/* Load every rule defined for this user. */
|
||||||
for (int j = 1; aclrules[j]; j++) {
|
for (int j = 1; aclrules[j]; j++) {
|
||||||
if (ACLSetUser(u,aclrules[j],sdslen(aclrules[j])) != C_OK) {
|
if (ACLSetUser(u,aclrules[j],sdslen(aclrules[j])) != C_OK) {
|
||||||
char *errmsg = ACLSetUserStringError();
|
const char *errmsg = ACLSetUserStringError();
|
||||||
serverLog(LL_WARNING,"Error loading ACL rule '%s' for "
|
serverLog(LL_WARNING,"Error loading ACL rule '%s' for "
|
||||||
"the user named '%s': %s",
|
"the user named '%s': %s",
|
||||||
aclrules[j],aclrules[0],errmsg);
|
aclrules[j],aclrules[0],errmsg);
|
||||||
@ -1220,7 +1220,7 @@ sds ACLLoadFromFile(const char *filename) {
|
|||||||
int j;
|
int j;
|
||||||
for (j = 2; j < argc; j++) {
|
for (j = 2; j < argc; j++) {
|
||||||
if (ACLSetUser(fakeuser,argv[j],sdslen(argv[j])) != C_OK) {
|
if (ACLSetUser(fakeuser,argv[j],sdslen(argv[j])) != C_OK) {
|
||||||
char *errmsg = ACLSetUserStringError();
|
const char *errmsg = ACLSetUserStringError();
|
||||||
errors = sdscatprintf(errors,
|
errors = sdscatprintf(errors,
|
||||||
"%s:%d: %s. ",
|
"%s:%d: %s. ",
|
||||||
server.acl_filename, linenum, errmsg);
|
server.acl_filename, linenum, errmsg);
|
||||||
@ -1262,10 +1262,10 @@ sds ACLLoadFromFile(const char *filename) {
|
|||||||
/* The default user pointer is referenced in different places: instead
|
/* The default user pointer is referenced in different places: instead
|
||||||
* of replacing such occurrences it is much simpler to copy the new
|
* of replacing such occurrences it is much simpler to copy the new
|
||||||
* default user configuration in the old one. */
|
* default user configuration in the old one. */
|
||||||
user *new = ACLGetUserByName("default",7);
|
user *newuser = ACLGetUserByName("default",7);
|
||||||
serverAssert(new != NULL);
|
serverAssert(newuser != NULL);
|
||||||
ACLCopyUser(DefaultUser,new);
|
ACLCopyUser(DefaultUser,newuser);
|
||||||
ACLFreeUser(new);
|
ACLFreeUser(newuser);
|
||||||
raxInsert(Users,(unsigned char*)"default",7,DefaultUser,NULL);
|
raxInsert(Users,(unsigned char*)"default",7,DefaultUser,NULL);
|
||||||
raxRemove(old_users,(unsigned char*)"default",7,NULL);
|
raxRemove(old_users,(unsigned char*)"default",7,NULL);
|
||||||
ACLFreeUsersSet(old_users);
|
ACLFreeUsersSet(old_users);
|
||||||
@ -1294,7 +1294,7 @@ int ACLSaveToFile(const char *filename) {
|
|||||||
raxStart(&ri,Users);
|
raxStart(&ri,Users);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
user *u = ri.data;
|
user *u = (user*)ri.data;
|
||||||
/* Return information in the configuration file format. */
|
/* Return information in the configuration file format. */
|
||||||
sds user = sdsnew("user ");
|
sds user = sdsnew("user ");
|
||||||
user = sdscatsds(user,u->name);
|
user = sdscatsds(user,u->name);
|
||||||
@ -1393,9 +1393,9 @@ void ACLLoadUsersAtStartup(void) {
|
|||||||
* ACL WHOAMI
|
* ACL WHOAMI
|
||||||
*/
|
*/
|
||||||
void aclCommand(client *c) {
|
void aclCommand(client *c) {
|
||||||
char *sub = ptrFromObj(c->argv[1]);
|
char *sub = szFromObj(c->argv[1]);
|
||||||
if (!strcasecmp(sub,"setuser") && c->argc >= 3) {
|
if (!strcasecmp(sub,"setuser") && c->argc >= 3) {
|
||||||
sds username = ptrFromObj(c->argv[2]);
|
sds username = szFromObj(c->argv[2]);
|
||||||
/* Create a temporary user to validate and stage all changes against
|
/* Create a temporary user to validate and stage all changes against
|
||||||
* before applying to an existing user or creating a new user. If all
|
* before applying to an existing user or creating a new user. If all
|
||||||
* arguments are valid the user parameters will all be applied together.
|
* arguments are valid the user parameters will all be applied together.
|
||||||
@ -1405,8 +1405,8 @@ void aclCommand(client *c) {
|
|||||||
if (u) ACLCopyUser(tempu, u);
|
if (u) ACLCopyUser(tempu, u);
|
||||||
|
|
||||||
for (int j = 3; j < c->argc; j++) {
|
for (int j = 3; j < c->argc; j++) {
|
||||||
if (ACLSetUser(tempu,ptrFromObj(c->argv[j]),sdslen(ptrFromObj(c->argv[j]))) != C_OK) {
|
if (ACLSetUser(tempu,szFromObj(c->argv[j]),sdslen(szFromObj(c->argv[j]))) != C_OK) {
|
||||||
char *errmsg = ACLSetUserStringError();
|
const char *errmsg = ACLSetUserStringError();
|
||||||
addReplyErrorFormat(c,
|
addReplyErrorFormat(c,
|
||||||
"Error in ACL SETUSER modifier '%s': %s",
|
"Error in ACL SETUSER modifier '%s': %s",
|
||||||
(char*)ptrFromObj(c->argv[j]), errmsg);
|
(char*)ptrFromObj(c->argv[j]), errmsg);
|
||||||
@ -1425,7 +1425,7 @@ void aclCommand(client *c) {
|
|||||||
} else if (!strcasecmp(sub,"deluser") && c->argc >= 3) {
|
} else if (!strcasecmp(sub,"deluser") && c->argc >= 3) {
|
||||||
int deleted = 0;
|
int deleted = 0;
|
||||||
for (int j = 2; j < c->argc; j++) {
|
for (int j = 2; j < c->argc; j++) {
|
||||||
sds username = ptrFromObj(c->argv[j]);
|
sds username = szFromObj(c->argv[j]);
|
||||||
if (!strcmp(username,"default")) {
|
if (!strcmp(username,"default")) {
|
||||||
addReplyError(c,"The 'default' user cannot be removed");
|
addReplyError(c,"The 'default' user cannot be removed");
|
||||||
return;
|
return;
|
||||||
@ -1433,7 +1433,7 @@ void aclCommand(client *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 2; j < c->argc; j++) {
|
for (int j = 2; j < c->argc; j++) {
|
||||||
sds username = ptrFromObj(c->argv[j]);
|
sds username = szFromObj(c->argv[j]);
|
||||||
user *u;
|
user *u;
|
||||||
if (raxRemove(Users,(unsigned char*)username,
|
if (raxRemove(Users,(unsigned char*)username,
|
||||||
sdslen(username),
|
sdslen(username),
|
||||||
@ -1445,7 +1445,7 @@ void aclCommand(client *c) {
|
|||||||
}
|
}
|
||||||
addReplyLongLong(c,deleted);
|
addReplyLongLong(c,deleted);
|
||||||
} else if (!strcasecmp(sub,"getuser") && c->argc == 3) {
|
} else if (!strcasecmp(sub,"getuser") && c->argc == 3) {
|
||||||
user *u = ACLGetUserByName(ptrFromObj(c->argv[2]),sdslen(ptrFromObj(c->argv[2])));
|
user *u = ACLGetUserByName(szFromObj(c->argv[2]),sdslen(szFromObj(c->argv[2])));
|
||||||
if (u == NULL) {
|
if (u == NULL) {
|
||||||
addReplyNull(c);
|
addReplyNull(c);
|
||||||
return;
|
return;
|
||||||
@ -1472,7 +1472,7 @@ void aclCommand(client *c) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
listRewind(u->passwords,&li);
|
listRewind(u->passwords,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
sds thispass = listNodeValue(ln);
|
sds thispass = (sds)listNodeValue(ln);
|
||||||
addReplyBulkCBuffer(c,thispass,sdslen(thispass));
|
addReplyBulkCBuffer(c,thispass,sdslen(thispass));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1492,7 +1492,7 @@ void aclCommand(client *c) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
listRewind(u->patterns,&li);
|
listRewind(u->patterns,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
sds thispat = listNodeValue(ln);
|
sds thispat = (sds)listNodeValue(ln);
|
||||||
addReplyBulkCBuffer(c,thispat,sdslen(thispat));
|
addReplyBulkCBuffer(c,thispat,sdslen(thispat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1505,7 +1505,7 @@ void aclCommand(client *c) {
|
|||||||
raxStart(&ri,Users);
|
raxStart(&ri,Users);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
user *u = ri.data;
|
user *u = (user*)ri.data;
|
||||||
if (justnames) {
|
if (justnames) {
|
||||||
addReplyBulkCBuffer(c,u->name,sdslen(u->name));
|
addReplyBulkCBuffer(c,u->name,sdslen(u->name));
|
||||||
} else {
|
} else {
|
||||||
@ -1554,7 +1554,7 @@ void aclCommand(client *c) {
|
|||||||
addReplyBulkCString(c,ACLCommandCategories[j].name);
|
addReplyBulkCString(c,ACLCommandCategories[j].name);
|
||||||
setDeferredArrayLen(c,dl,j);
|
setDeferredArrayLen(c,dl,j);
|
||||||
} else if (!strcasecmp(sub,"cat") && c->argc == 3) {
|
} else if (!strcasecmp(sub,"cat") && c->argc == 3) {
|
||||||
uint64_t cflag = ACLGetCommandCategoryFlagByName(ptrFromObj(c->argv[2]));
|
uint64_t cflag = ACLGetCommandCategoryFlagByName(szFromObj(c->argv[2]));
|
||||||
if (cflag == 0) {
|
if (cflag == 0) {
|
||||||
addReplyErrorFormat(c, "Unknown category '%s'", (char*)ptrFromObj(c->argv[2]));
|
addReplyErrorFormat(c, "Unknown category '%s'", (char*)ptrFromObj(c->argv[2]));
|
||||||
return;
|
return;
|
||||||
@ -1564,7 +1564,7 @@ void aclCommand(client *c) {
|
|||||||
dictIterator *di = dictGetIterator(server.orig_commands);
|
dictIterator *di = dictGetIterator(server.orig_commands);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
while ((de = dictNext(di)) != NULL) {
|
while ((de = dictNext(di)) != NULL) {
|
||||||
struct redisCommand *cmd = dictGetVal(de);
|
struct redisCommand *cmd = (redisCommand*)dictGetVal(de);
|
||||||
if (cmd->flags & CMD_MODULE) continue;
|
if (cmd->flags & CMD_MODULE) continue;
|
||||||
if (cmd->flags & cflag) {
|
if (cmd->flags & cflag) {
|
||||||
addReplyBulkCString(c,cmd->name);
|
addReplyBulkCString(c,cmd->name);
|
@ -83,7 +83,7 @@ unsigned long aofRewriteBufferSize(void) {
|
|||||||
|
|
||||||
listRewind(server.aof_rewrite_buf_blocks,&li);
|
listRewind(server.aof_rewrite_buf_blocks,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
aofrwblock *block = listNodeValue(ln);
|
aofrwblock *block = (aofrwblock*)listNodeValue(ln);
|
||||||
size += block->used;
|
size += block->used;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
@ -105,7 +105,7 @@ void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {
|
|||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
ln = listFirst(server.aof_rewrite_buf_blocks);
|
ln = listFirst(server.aof_rewrite_buf_blocks);
|
||||||
block = ln ? ln->value : NULL;
|
block = (aofrwblock*)(ln ? ln->value : NULL);
|
||||||
if (server.aof_stop_sending_diff || !block) {
|
if (server.aof_stop_sending_diff || !block) {
|
||||||
aeDeleteFileEvent(el,server.aof_pipe_write_data_to_child,
|
aeDeleteFileEvent(el,server.aof_pipe_write_data_to_child,
|
||||||
AE_WRITABLE);
|
AE_WRITABLE);
|
||||||
@ -126,7 +126,7 @@ void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {
|
|||||||
/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */
|
/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */
|
||||||
void aofRewriteBufferAppend(unsigned char *s, unsigned long len) {
|
void aofRewriteBufferAppend(unsigned char *s, unsigned long len) {
|
||||||
listNode *ln = listLast(server.aof_rewrite_buf_blocks);
|
listNode *ln = listLast(server.aof_rewrite_buf_blocks);
|
||||||
aofrwblock *block = ln ? ln->value : NULL;
|
aofrwblock *block = (aofrwblock*)(ln ? ln->value : NULL);
|
||||||
|
|
||||||
while(len) {
|
while(len) {
|
||||||
/* If we already got at least an allocated block, try appending
|
/* If we already got at least an allocated block, try appending
|
||||||
@ -145,7 +145,7 @@ void aofRewriteBufferAppend(unsigned char *s, unsigned long len) {
|
|||||||
if (len) { /* First block to allocate, or need another block. */
|
if (len) { /* First block to allocate, or need another block. */
|
||||||
int numblocks;
|
int numblocks;
|
||||||
|
|
||||||
block = zmalloc(sizeof(*block), MALLOC_LOCAL);
|
block = (aofrwblock*)zmalloc(sizeof(*block), MALLOC_LOCAL);
|
||||||
block->free = AOF_RW_BUF_BLOCK_SIZE;
|
block->free = AOF_RW_BUF_BLOCK_SIZE;
|
||||||
block->used = 0;
|
block->used = 0;
|
||||||
listAddNodeTail(server.aof_rewrite_buf_blocks,block);
|
listAddNodeTail(server.aof_rewrite_buf_blocks,block);
|
||||||
@ -180,7 +180,7 @@ ssize_t aofRewriteBufferWrite(int fd) {
|
|||||||
|
|
||||||
listRewind(server.aof_rewrite_buf_blocks,&li);
|
listRewind(server.aof_rewrite_buf_blocks,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
aofrwblock *block = listNodeValue(ln);
|
aofrwblock *block = (aofrwblock*)listNodeValue(ln);
|
||||||
ssize_t nwritten;
|
ssize_t nwritten;
|
||||||
|
|
||||||
if (block->used) {
|
if (block->used) {
|
||||||
@ -508,11 +508,11 @@ sds catAppendOnlyGenericCommand(sds dst, int argc, robj **argv) {
|
|||||||
for (j = 0; j < argc; j++) {
|
for (j = 0; j < argc; j++) {
|
||||||
o = getDecodedObject(argv[j]);
|
o = getDecodedObject(argv[j]);
|
||||||
buf[0] = '$';
|
buf[0] = '$';
|
||||||
len = 1+ll2string(buf+1,sizeof(buf)-1,sdslen(ptrFromObj(o)));
|
len = 1+ll2string(buf+1,sizeof(buf)-1,sdslen(szFromObj(o)));
|
||||||
buf[len++] = '\r';
|
buf[len++] = '\r';
|
||||||
buf[len++] = '\n';
|
buf[len++] = '\n';
|
||||||
dst = sdscatlen(dst,buf,len);
|
dst = sdscatlen(dst,buf,len);
|
||||||
dst = sdscatlen(dst,ptrFromObj(o),sdslen(ptrFromObj(o)));
|
dst = sdscatlen(dst,ptrFromObj(o),sdslen(szFromObj(o)));
|
||||||
dst = sdscatlen(dst,"\r\n",2);
|
dst = sdscatlen(dst,"\r\n",2);
|
||||||
decrRefCount(o);
|
decrRefCount(o);
|
||||||
}
|
}
|
||||||
@ -532,7 +532,7 @@ sds catAppendOnlyExpireAtCommand(sds buf, struct redisCommand *cmd, robj *key, r
|
|||||||
|
|
||||||
/* Make sure we can use strtoll */
|
/* Make sure we can use strtoll */
|
||||||
seconds = getDecodedObject(seconds);
|
seconds = getDecodedObject(seconds);
|
||||||
when = strtoll(ptrFromObj(seconds),NULL,10);
|
when = strtoll(szFromObj(seconds),NULL,10);
|
||||||
/* Convert argument into milliseconds for EXPIRE, SETEX, EXPIREAT */
|
/* Convert argument into milliseconds for EXPIRE, SETEX, EXPIREAT */
|
||||||
if (cmd->proc == expireCommand || cmd->proc == setexCommand ||
|
if (cmd->proc == expireCommand || cmd->proc == setexCommand ||
|
||||||
cmd->proc == expireatCommand)
|
cmd->proc == expireatCommand)
|
||||||
@ -589,8 +589,8 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a
|
|||||||
/* Translate SET [EX seconds][PX milliseconds] to SET and PEXPIREAT */
|
/* Translate SET [EX seconds][PX milliseconds] to SET and PEXPIREAT */
|
||||||
buf = catAppendOnlyGenericCommand(buf,3,argv);
|
buf = catAppendOnlyGenericCommand(buf,3,argv);
|
||||||
for (i = 3; i < argc; i ++) {
|
for (i = 3; i < argc; i ++) {
|
||||||
if (!strcasecmp(ptrFromObj(argv[i]), "ex")) exarg = argv[i+1];
|
if (!strcasecmp(szFromObj(argv[i]), "ex")) exarg = argv[i+1];
|
||||||
if (!strcasecmp(ptrFromObj(argv[i]), "px")) pxarg = argv[i+1];
|
if (!strcasecmp(szFromObj(argv[i]), "px")) pxarg = argv[i+1];
|
||||||
}
|
}
|
||||||
serverAssert(!(exarg && pxarg));
|
serverAssert(!(exarg && pxarg));
|
||||||
if (exarg)
|
if (exarg)
|
||||||
@ -628,8 +628,8 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a
|
|||||||
|
|
||||||
/* In Redis commands are always executed in the context of a client, so in
|
/* In Redis commands are always executed in the context of a client, so in
|
||||||
* order to load the append only file we need to create a fake client. */
|
* order to load the append only file we need to create a fake client. */
|
||||||
struct client *createFakeClient(void) {
|
client *createFakeClient(void) {
|
||||||
struct client *c = zmalloc(sizeof(*c), MALLOC_LOCAL);
|
client *c = (client*)zmalloc(sizeof(*c), MALLOC_LOCAL);
|
||||||
|
|
||||||
selectDb(c,0);
|
selectDb(c,0);
|
||||||
c->fd = -1;
|
c->fd = -1;
|
||||||
@ -762,7 +762,7 @@ int loadAppendOnlyFile(char *filename) {
|
|||||||
argc = atoi(buf+1);
|
argc = atoi(buf+1);
|
||||||
if (argc < 1) goto fmterr;
|
if (argc < 1) goto fmterr;
|
||||||
|
|
||||||
argv = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL);
|
argv = (robj**)zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL);
|
||||||
fakeClient->argc = argc;
|
fakeClient->argc = argc;
|
||||||
fakeClient->argv = argv;
|
fakeClient->argv = argv;
|
||||||
|
|
||||||
@ -790,7 +790,7 @@ int loadAppendOnlyFile(char *filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Command lookup */
|
/* Command lookup */
|
||||||
cmd = lookupCommand(ptrFromObj(argv[0]));
|
cmd = lookupCommand(szFromObj(argv[0]));
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
serverLog(LL_WARNING,
|
serverLog(LL_WARNING,
|
||||||
"Unknown command '%s' reading the append only file",
|
"Unknown command '%s' reading the append only file",
|
||||||
@ -898,7 +898,7 @@ int rioWriteBulkObject(rio *r, robj *obj) {
|
|||||||
if (obj->encoding == OBJ_ENCODING_INT) {
|
if (obj->encoding == OBJ_ENCODING_INT) {
|
||||||
return rioWriteBulkLongLong(r,(long)obj->m_ptr);
|
return rioWriteBulkLongLong(r,(long)obj->m_ptr);
|
||||||
} else if (sdsEncodedObject(obj)) {
|
} else if (sdsEncodedObject(obj)) {
|
||||||
return rioWriteBulkString(r,ptrFromObj(obj),sdslen(ptrFromObj(obj)));
|
return rioWriteBulkString(r,szFromObj(obj),sdslen(szFromObj(obj)));
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown string encoding");
|
serverPanic("Unknown string encoding");
|
||||||
}
|
}
|
||||||
@ -910,7 +910,7 @@ int rewriteListObject(rio *r, robj *key, robj *o) {
|
|||||||
long long count = 0, items = listTypeLength(o);
|
long long count = 0, items = listTypeLength(o);
|
||||||
|
|
||||||
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||||
quicklist *list = ptrFromObj(o);
|
quicklist *list = (quicklist*)ptrFromObj(o);
|
||||||
quicklistIter *li = quicklistGetIterator(list, AL_START_HEAD);
|
quicklistIter *li = quicklistGetIterator(list, AL_START_HEAD);
|
||||||
quicklistEntry entry;
|
quicklistEntry entry;
|
||||||
|
|
||||||
@ -947,7 +947,7 @@ int rewriteSetObject(rio *r, robj *key, robj *o) {
|
|||||||
int ii = 0;
|
int ii = 0;
|
||||||
int64_t llval;
|
int64_t llval;
|
||||||
|
|
||||||
while(intsetGet(ptrFromObj(o),ii++,&llval)) {
|
while(intsetGet((intset*)ptrFromObj(o),ii++,&llval)) {
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?
|
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?
|
||||||
AOF_REWRITE_ITEMS_PER_CMD : items;
|
AOF_REWRITE_ITEMS_PER_CMD : items;
|
||||||
@ -961,11 +961,11 @@ int rewriteSetObject(rio *r, robj *key, robj *o) {
|
|||||||
items--;
|
items--;
|
||||||
}
|
}
|
||||||
} else if (o->encoding == OBJ_ENCODING_HT) {
|
} else if (o->encoding == OBJ_ENCODING_HT) {
|
||||||
dictIterator *di = dictGetIterator(ptrFromObj(o));
|
dictIterator *di = dictGetIterator((dict*)ptrFromObj(o));
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds ele = dictGetKey(de);
|
sds ele = (sds)dictGetKey(de);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?
|
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?
|
||||||
AOF_REWRITE_ITEMS_PER_CMD : items;
|
AOF_REWRITE_ITEMS_PER_CMD : items;
|
||||||
@ -991,7 +991,7 @@ int rewriteSortedSetObject(rio *r, robj *key, robj *o) {
|
|||||||
long long count = 0, items = zsetLength(o);
|
long long count = 0, items = zsetLength(o);
|
||||||
|
|
||||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
unsigned char *zl = ptrFromObj(o);
|
unsigned char *zl = (unsigned char*)ptrFromObj(o);
|
||||||
unsigned char *eptr, *sptr;
|
unsigned char *eptr, *sptr;
|
||||||
unsigned char *vstr;
|
unsigned char *vstr;
|
||||||
unsigned int vlen;
|
unsigned int vlen;
|
||||||
@ -1026,13 +1026,13 @@ int rewriteSortedSetObject(rio *r, robj *key, robj *o) {
|
|||||||
items--;
|
items--;
|
||||||
}
|
}
|
||||||
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||||
zset *zs = ptrFromObj(o);
|
zset *zs = (zset*)ptrFromObj(o);
|
||||||
dictIterator *di = dictGetIterator(zs->pdict);
|
dictIterator *di = dictGetIterator(zs->pdict);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds ele = dictGetKey(de);
|
sds ele = (sds)dictGetKey(de);
|
||||||
double *score = dictGetVal(de);
|
double *score = (double*)dictGetVal(de);
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?
|
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?
|
||||||
@ -1147,7 +1147,7 @@ int rioWriteStreamPendingEntry(rio *r, robj *key, const char *groupname, size_t
|
|||||||
/* Emit the commands needed to rebuild a stream object.
|
/* Emit the commands needed to rebuild a stream object.
|
||||||
* The function returns 0 on error, 1 on success. */
|
* The function returns 0 on error, 1 on success. */
|
||||||
int rewriteStreamObject(rio *r, robj *key, robj *o) {
|
int rewriteStreamObject(rio *r, robj *key, robj *o) {
|
||||||
stream *s = ptrFromObj(o);
|
stream *s = (stream*)ptrFromObj(o);
|
||||||
streamIterator si;
|
streamIterator si;
|
||||||
streamIteratorStart(&si,s,NULL,NULL,0);
|
streamIteratorStart(&si,s,NULL,NULL,0);
|
||||||
streamID id;
|
streamID id;
|
||||||
@ -1200,7 +1200,7 @@ int rewriteStreamObject(rio *r, robj *key, robj *o) {
|
|||||||
raxStart(&ri,s->cgroups);
|
raxStart(&ri,s->cgroups);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
streamCG *group = ri.data;
|
streamCG *group = (streamCG*)ri.data;
|
||||||
/* Emit the XGROUP CREATE in order to create the group. */
|
/* Emit the XGROUP CREATE in order to create the group. */
|
||||||
if (rioWriteBulkCount(r,'*',5) == 0) return 0;
|
if (rioWriteBulkCount(r,'*',5) == 0) return 0;
|
||||||
if (rioWriteBulkString(r,"XGROUP",6) == 0) return 0;
|
if (rioWriteBulkString(r,"XGROUP",6) == 0) return 0;
|
||||||
@ -1216,14 +1216,14 @@ int rewriteStreamObject(rio *r, robj *key, robj *o) {
|
|||||||
raxStart(&ri_cons,group->consumers);
|
raxStart(&ri_cons,group->consumers);
|
||||||
raxSeek(&ri_cons,"^",NULL,0);
|
raxSeek(&ri_cons,"^",NULL,0);
|
||||||
while(raxNext(&ri_cons)) {
|
while(raxNext(&ri_cons)) {
|
||||||
streamConsumer *consumer = ri_cons.data;
|
streamConsumer *consumer = (streamConsumer*)ri_cons.data;
|
||||||
/* For the current consumer, iterate all the PEL entries
|
/* For the current consumer, iterate all the PEL entries
|
||||||
* to emit the XCLAIM protocol. */
|
* to emit the XCLAIM protocol. */
|
||||||
raxIterator ri_pel;
|
raxIterator ri_pel;
|
||||||
raxStart(&ri_pel,consumer->pel);
|
raxStart(&ri_pel,consumer->pel);
|
||||||
raxSeek(&ri_pel,"^",NULL,0);
|
raxSeek(&ri_pel,"^",NULL,0);
|
||||||
while(raxNext(&ri_pel)) {
|
while(raxNext(&ri_pel)) {
|
||||||
streamNACK *nack = ri_pel.data;
|
streamNACK *nack = (streamNACK*)ri_pel.data;
|
||||||
if (rioWriteStreamPendingEntry(r,key,(char*)ri.key,
|
if (rioWriteStreamPendingEntry(r,key,(char*)ri.key,
|
||||||
ri.key_len,consumer,
|
ri.key_len,consumer,
|
||||||
ri_pel.key,nack) == 0)
|
ri_pel.key,nack) == 0)
|
||||||
@ -1247,7 +1247,7 @@ int rewriteStreamObject(rio *r, robj *key, robj *o) {
|
|||||||
* The function returns 0 on error, 1 on success. */
|
* The function returns 0 on error, 1 on success. */
|
||||||
int rewriteModuleObject(rio *r, robj *key, robj *o) {
|
int rewriteModuleObject(rio *r, robj *key, robj *o) {
|
||||||
RedisModuleIO io;
|
RedisModuleIO io;
|
||||||
moduleValue *mv = ptrFromObj(o);
|
moduleValue *mv = (moduleValue*)ptrFromObj(o);
|
||||||
moduleType *mt = mv->type;
|
moduleType *mt = mv->type;
|
||||||
moduleInitIOContext(io,mt,r,key);
|
moduleInitIOContext(io,mt,r,key);
|
||||||
mt->aof_rewrite(&io,key,mv->value);
|
mt->aof_rewrite(&io,key,mv->value);
|
||||||
@ -1296,8 +1296,8 @@ int rewriteAppendOnlyFileRio(rio *aof) {
|
|||||||
robj key, *o;
|
robj key, *o;
|
||||||
long long expiretime;
|
long long expiretime;
|
||||||
|
|
||||||
keystr = dictGetKey(de);
|
keystr = (sds)dictGetKey(de);
|
||||||
o = dictGetVal(de);
|
o = (robj*)dictGetVal(de);
|
||||||
initStaticStringObject(key,keystr);
|
initStaticStringObject(key,keystr);
|
||||||
|
|
||||||
expiretime = getExpire(db,&key);
|
expiretime = getExpire(db,&key);
|
||||||
@ -1360,6 +1360,8 @@ int rewriteAppendOnlyFile(char *filename) {
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
char tmpfile[256];
|
char tmpfile[256];
|
||||||
char byte;
|
char byte;
|
||||||
|
int nodata = 0;
|
||||||
|
mstime_t start = 0;
|
||||||
|
|
||||||
/* Note that we have to use a different temp name here compared to the
|
/* Note that we have to use a different temp name here compared to the
|
||||||
* one used by rewriteAppendOnlyFileBackground() function. */
|
* one used by rewriteAppendOnlyFileBackground() function. */
|
||||||
@ -1397,8 +1399,7 @@ int rewriteAppendOnlyFile(char *filename) {
|
|||||||
* some more data in a loop as soon as there is a good chance more data
|
* some more data in a loop as soon as there is a good chance more data
|
||||||
* will come. If it looks like we are wasting time, we abort (this
|
* will come. If it looks like we are wasting time, we abort (this
|
||||||
* happens after 20 ms without new data). */
|
* happens after 20 ms without new data). */
|
||||||
int nodata = 0;
|
start = mstime();
|
||||||
mstime_t start = mstime();
|
|
||||||
while(mstime()-start < 1000 && nodata < 20) {
|
while(mstime()-start < 1000 && nodata < 20) {
|
||||||
if (aeWait(server.aof_pipe_read_data_from_parent, AE_READABLE, 1) <= 0)
|
if (aeWait(server.aof_pipe_read_data_from_parent, AE_READABLE, 1) <= 0)
|
||||||
{
|
{
|
@ -129,7 +129,7 @@ void bioInit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
|
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
|
||||||
struct bio_job *job = zmalloc(sizeof(*job), MALLOC_LOCAL);
|
struct bio_job *job = (bio_job*)zmalloc(sizeof(*job), MALLOC_LOCAL);
|
||||||
|
|
||||||
job->time = time(NULL);
|
job->time = time(NULL);
|
||||||
job->arg1 = arg1;
|
job->arg1 = arg1;
|
||||||
@ -178,7 +178,7 @@ void *bioProcessBackgroundJobs(void *arg) {
|
|||||||
}
|
}
|
||||||
/* Pop the job from the queue. */
|
/* Pop the job from the queue. */
|
||||||
ln = listFirst(bio_jobs[type]);
|
ln = listFirst(bio_jobs[type]);
|
||||||
job = ln->value;
|
job = (bio_job*)ln->value;
|
||||||
/* It is now possible to unlock the background system as we know have
|
/* It is now possible to unlock the background system as we know have
|
||||||
* a stand alone job structure to process.*/
|
* a stand alone job structure to process.*/
|
||||||
pthread_mutex_unlock(&bio_mutex[type]);
|
pthread_mutex_unlock(&bio_mutex[type]);
|
||||||
@ -194,11 +194,11 @@ void *bioProcessBackgroundJobs(void *arg) {
|
|||||||
* arg2 & arg3 -> free two dictionaries (a Redis DB).
|
* arg2 & arg3 -> free two dictionaries (a Redis DB).
|
||||||
* only arg3 -> free the skiplist. */
|
* only arg3 -> free the skiplist. */
|
||||||
if (job->arg1)
|
if (job->arg1)
|
||||||
lazyfreeFreeObjectFromBioThread(job->arg1);
|
lazyfreeFreeObjectFromBioThread((robj*)job->arg1);
|
||||||
else if (job->arg2 && job->arg3)
|
else if (job->arg2 && job->arg3)
|
||||||
lazyfreeFreeDatabaseFromBioThread(job->arg2,job->arg3);
|
lazyfreeFreeDatabaseFromBioThread((dict*)job->arg2,(dict*)job->arg3);
|
||||||
else if (job->arg3)
|
else if (job->arg3)
|
||||||
lazyfreeFreeSlotsMapFromBioThread(job->arg3);
|
lazyfreeFreeSlotsMapFromBioThread((rax*)job->arg3);
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Wrong job type in bioProcessBackgroundJobs().");
|
serverPanic("Wrong job type in bioProcessBackgroundJobs().");
|
||||||
}
|
}
|
@ -39,7 +39,7 @@
|
|||||||
* work with a input string length up to 512 MB. */
|
* work with a input string length up to 512 MB. */
|
||||||
size_t redisPopcount(void *s, long count) {
|
size_t redisPopcount(void *s, long count) {
|
||||||
size_t bits = 0;
|
size_t bits = 0;
|
||||||
unsigned char *p = s;
|
unsigned char *p = (unsigned char*)s;
|
||||||
uint32_t *p4;
|
uint32_t *p4;
|
||||||
static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
|
static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
|
||||||
|
|
||||||
@ -410,8 +410,8 @@ void printBits(unsigned char *p, unsigned long count) {
|
|||||||
* is multiplied by 'bits'. This is useful for the BITFIELD command. */
|
* is multiplied by 'bits'. This is useful for the BITFIELD command. */
|
||||||
int getBitOffsetFromArgument(client *c, robj *o, size_t *offset, int hash, int bits) {
|
int getBitOffsetFromArgument(client *c, robj *o, size_t *offset, int hash, int bits) {
|
||||||
long long loffset;
|
long long loffset;
|
||||||
char *err = "bit offset is not an integer or out of range";
|
const char *err = "bit offset is not an integer or out of range";
|
||||||
char *p = ptrFromObj(o);
|
char *p = szFromObj(o);
|
||||||
size_t plen = sdslen(p);
|
size_t plen = sdslen(p);
|
||||||
int usehash = 0;
|
int usehash = 0;
|
||||||
|
|
||||||
@ -445,8 +445,8 @@ int getBitOffsetFromArgument(client *c, robj *o, size_t *offset, int hash, int b
|
|||||||
*
|
*
|
||||||
* On error C_ERR is returned and an error is sent to the client. */
|
* On error C_ERR is returned and an error is sent to the client. */
|
||||||
int getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) {
|
int getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) {
|
||||||
char *p = ptrFromObj(o);
|
char *p = szFromObj(o);
|
||||||
char *err = "Invalid bitfield type. Use something like i16 u8. Note that u64 is not supported but i64 is.";
|
const char *err = "Invalid bitfield type. Use something like i16 u8. Note that u64 is not supported but i64 is.";
|
||||||
long long llbits;
|
long long llbits;
|
||||||
|
|
||||||
if (p[0] == 'i') {
|
if (p[0] == 'i') {
|
||||||
@ -485,7 +485,7 @@ robj *lookupStringForBitCommand(client *c, size_t maxbit) {
|
|||||||
} else {
|
} else {
|
||||||
if (checkType(c,o,OBJ_STRING)) return NULL;
|
if (checkType(c,o,OBJ_STRING)) return NULL;
|
||||||
o = dbUnshareStringValue(c->db,c->argv[1],o);
|
o = dbUnshareStringValue(c->db,c->argv[1],o);
|
||||||
o->m_ptr = sdsgrowzero(ptrFromObj(o),byte+1);
|
o->m_ptr = sdsgrowzero(szFromObj(o),byte+1);
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -514,7 +514,7 @@ unsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) {
|
|||||||
if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)ptrFromObj(o));
|
if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)ptrFromObj(o));
|
||||||
} else if (o) {
|
} else if (o) {
|
||||||
p = (unsigned char*) ptrFromObj(o);
|
p = (unsigned char*) ptrFromObj(o);
|
||||||
if (len) *len = sdslen(ptrFromObj(o));
|
if (len) *len = sdslen(szFromObj(o));
|
||||||
} else {
|
} else {
|
||||||
if (len) *len = 0;
|
if (len) *len = 0;
|
||||||
}
|
}
|
||||||
@ -524,7 +524,7 @@ unsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) {
|
|||||||
/* SETBIT key offset bitvalue */
|
/* SETBIT key offset bitvalue */
|
||||||
void setbitCommand(client *c) {
|
void setbitCommand(client *c) {
|
||||||
robj *o;
|
robj *o;
|
||||||
char *err = "bit is not an integer or out of range";
|
const char *err = "bit is not an integer or out of range";
|
||||||
size_t bitoffset;
|
size_t bitoffset;
|
||||||
ssize_t byte, bit;
|
ssize_t byte, bit;
|
||||||
int byteval, bitval;
|
int byteval, bitval;
|
||||||
@ -577,7 +577,7 @@ void getbitCommand(client *c) {
|
|||||||
byte = bitoffset >> 3;
|
byte = bitoffset >> 3;
|
||||||
bit = 7 - (bitoffset & 0x7);
|
bit = 7 - (bitoffset & 0x7);
|
||||||
if (sdsEncodedObject(o)) {
|
if (sdsEncodedObject(o)) {
|
||||||
if (byte < sdslen(ptrFromObj(o)))
|
if (byte < sdslen(szFromObj(o)))
|
||||||
bitval = ((uint8_t*)ptrFromObj(o))[byte] & (1 << bit);
|
bitval = ((uint8_t*)ptrFromObj(o))[byte] & (1 << bit);
|
||||||
} else {
|
} else {
|
||||||
if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)ptrFromObj(o)))
|
if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)ptrFromObj(o)))
|
||||||
@ -589,7 +589,7 @@ void getbitCommand(client *c) {
|
|||||||
|
|
||||||
/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */
|
/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */
|
||||||
void bitopCommand(client *c) {
|
void bitopCommand(client *c) {
|
||||||
char *opname = ptrFromObj(c->argv[1]);
|
char *opname = szFromObj(c->argv[1]);
|
||||||
robj *o, *targetkey = c->argv[2];
|
robj *o, *targetkey = c->argv[2];
|
||||||
unsigned long op, j, numkeys;
|
unsigned long op, j, numkeys;
|
||||||
robj **objects; /* Array of source objects. */
|
robj **objects; /* Array of source objects. */
|
||||||
@ -621,9 +621,9 @@ void bitopCommand(client *c) {
|
|||||||
|
|
||||||
/* Lookup keys, and store pointers to the string objects into an array. */
|
/* Lookup keys, and store pointers to the string objects into an array. */
|
||||||
numkeys = c->argc - 3;
|
numkeys = c->argc - 3;
|
||||||
src = zmalloc(sizeof(unsigned char*) * numkeys, MALLOC_LOCAL);
|
src = (unsigned char**)zmalloc(sizeof(unsigned char*) * numkeys, MALLOC_LOCAL);
|
||||||
len = zmalloc(sizeof(long) * numkeys, MALLOC_LOCAL);
|
len = (unsigned long*)zmalloc(sizeof(long) * numkeys, MALLOC_LOCAL);
|
||||||
objects = zmalloc(sizeof(robj*) * numkeys, MALLOC_LOCAL);
|
objects = (robj**)zmalloc(sizeof(robj*) * numkeys, MALLOC_LOCAL);
|
||||||
for (j = 0; j < numkeys; j++) {
|
for (j = 0; j < numkeys; j++) {
|
||||||
o = lookupKeyRead(c->db,c->argv[j+3]);
|
o = lookupKeyRead(c->db,c->argv[j+3]);
|
||||||
/* Handle non-existing keys as empty strings. */
|
/* Handle non-existing keys as empty strings. */
|
||||||
@ -647,8 +647,8 @@ void bitopCommand(client *c) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
objects[j] = getDecodedObject(o);
|
objects[j] = getDecodedObject(o);
|
||||||
src[j] = ptrFromObj(objects[j]);
|
src[j] = (unsigned char*)ptrFromObj(objects[j]);
|
||||||
len[j] = sdslen(ptrFromObj(objects[j]));
|
len[j] = sdslen(szFromObj(objects[j]));
|
||||||
if (len[j] > maxlen) maxlen = len[j];
|
if (len[j] > maxlen) maxlen = len[j];
|
||||||
if (j == 0 || len[j] < minlen) minlen = len[j];
|
if (j == 0 || len[j] < minlen) minlen = len[j];
|
||||||
}
|
}
|
||||||
@ -922,7 +922,7 @@ void bitfieldCommand(client *c) {
|
|||||||
|
|
||||||
for (j = 2; j < c->argc; j++) {
|
for (j = 2; j < c->argc; j++) {
|
||||||
int remargs = c->argc-j-1; /* Remaining args other than current. */
|
int remargs = c->argc-j-1; /* Remaining args other than current. */
|
||||||
char *subcmd = ptrFromObj(c->argv[j]); /* Current command name. */
|
char *subcmd = szFromObj(c->argv[j]); /* Current command name. */
|
||||||
int opcode; /* Current operation code. */
|
int opcode; /* Current operation code. */
|
||||||
long long i64 = 0; /* Signed SET value. */
|
long long i64 = 0; /* Signed SET value. */
|
||||||
int sign = 0; /* Signed or unsigned type? */
|
int sign = 0; /* Signed or unsigned type? */
|
||||||
@ -935,7 +935,7 @@ void bitfieldCommand(client *c) {
|
|||||||
else if (!strcasecmp(subcmd,"incrby") && remargs >= 3)
|
else if (!strcasecmp(subcmd,"incrby") && remargs >= 3)
|
||||||
opcode = BITFIELDOP_INCRBY;
|
opcode = BITFIELDOP_INCRBY;
|
||||||
else if (!strcasecmp(subcmd,"overflow") && remargs >= 1) {
|
else if (!strcasecmp(subcmd,"overflow") && remargs >= 1) {
|
||||||
char *owtypename = ptrFromObj(c->argv[j+1]);
|
char *owtypename = szFromObj(c->argv[j+1]);
|
||||||
j++;
|
j++;
|
||||||
if (!strcasecmp(owtypename,"wrap"))
|
if (!strcasecmp(owtypename,"wrap"))
|
||||||
owtype = BFOVERFLOW_WRAP;
|
owtype = BFOVERFLOW_WRAP;
|
||||||
@ -978,7 +978,7 @@ void bitfieldCommand(client *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Populate the array of operations we'll process. */
|
/* Populate the array of operations we'll process. */
|
||||||
ops = zrealloc(ops,sizeof(*ops)*(numops+1), MALLOC_SHARED);
|
ops = (bitfieldOp*)zrealloc(ops,sizeof(*ops)*(numops+1), MALLOC_SHARED);
|
||||||
ops[numops].offset = bitoffset;
|
ops[numops].offset = bitoffset;
|
||||||
ops[numops].i64 = i64;
|
ops[numops].i64 = i64;
|
||||||
ops[numops].opcode = opcode;
|
ops[numops].opcode = opcode;
|
||||||
@ -1023,7 +1023,7 @@ void bitfieldCommand(client *c) {
|
|||||||
int64_t oldval, newval, wrapped, retval;
|
int64_t oldval, newval, wrapped, retval;
|
||||||
int overflow;
|
int overflow;
|
||||||
|
|
||||||
oldval = getSignedBitfield(ptrFromObj(o),thisop->offset,
|
oldval = getSignedBitfield((unsigned char*)ptrFromObj(o),thisop->offset,
|
||||||
thisop->bits);
|
thisop->bits);
|
||||||
|
|
||||||
if (thisop->opcode == BITFIELDOP_INCRBY) {
|
if (thisop->opcode == BITFIELDOP_INCRBY) {
|
||||||
@ -1044,7 +1044,7 @@ void bitfieldCommand(client *c) {
|
|||||||
* NULL to signal the condition. */
|
* NULL to signal the condition. */
|
||||||
if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {
|
if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {
|
||||||
addReplyLongLong(c,retval);
|
addReplyLongLong(c,retval);
|
||||||
setSignedBitfield(ptrFromObj(o),thisop->offset,
|
setSignedBitfield((unsigned char*)ptrFromObj(o),thisop->offset,
|
||||||
thisop->bits,newval);
|
thisop->bits,newval);
|
||||||
} else {
|
} else {
|
||||||
addReplyNull(c);
|
addReplyNull(c);
|
||||||
@ -1053,7 +1053,7 @@ void bitfieldCommand(client *c) {
|
|||||||
uint64_t oldval, newval, wrapped, retval;
|
uint64_t oldval, newval, wrapped, retval;
|
||||||
int overflow;
|
int overflow;
|
||||||
|
|
||||||
oldval = getUnsignedBitfield(ptrFromObj(o),thisop->offset,
|
oldval = getUnsignedBitfield((unsigned char*)ptrFromObj(o),thisop->offset,
|
||||||
thisop->bits);
|
thisop->bits);
|
||||||
|
|
||||||
if (thisop->opcode == BITFIELDOP_INCRBY) {
|
if (thisop->opcode == BITFIELDOP_INCRBY) {
|
||||||
@ -1073,7 +1073,7 @@ void bitfieldCommand(client *c) {
|
|||||||
* NULL to signal the condition. */
|
* NULL to signal the condition. */
|
||||||
if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {
|
if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {
|
||||||
addReplyLongLong(c,retval);
|
addReplyLongLong(c,retval);
|
||||||
setUnsignedBitfield(ptrFromObj(o),thisop->offset,
|
setUnsignedBitfield((unsigned char*)ptrFromObj(o),thisop->offset,
|
||||||
thisop->bits,newval);
|
thisop->bits,newval);
|
||||||
} else {
|
} else {
|
||||||
addReplyNull(c);
|
addReplyNull(c);
|
@ -82,7 +82,7 @@ struct redisMaster *getFirstMaster()
|
|||||||
serverAssert(listLength(server.masters) <= 1);
|
serverAssert(listLength(server.masters) <= 1);
|
||||||
if (!listLength(server.masters))
|
if (!listLength(server.masters))
|
||||||
return NULL;
|
return NULL;
|
||||||
return listFirst(server.masters)->value;
|
return (redisMaster*)listFirst(server.masters)->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
@ -127,7 +127,7 @@ int clusterLoadConfig(char *filename) {
|
|||||||
*
|
*
|
||||||
* To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */
|
* To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */
|
||||||
maxline = 1024+CLUSTER_SLOTS*128;
|
maxline = 1024+CLUSTER_SLOTS*128;
|
||||||
line = zmalloc(maxline, MALLOC_LOCAL);
|
line = (char*)zmalloc(maxline, MALLOC_LOCAL);
|
||||||
while(fgets(line,maxline,fp) != NULL) {
|
while(fgets(line,maxline,fp) != NULL) {
|
||||||
int argc;
|
int argc;
|
||||||
sds *argv;
|
sds *argv;
|
||||||
@ -442,7 +442,7 @@ void clusterInit(void) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
server.cluster = zmalloc(sizeof(clusterState), MALLOC_LOCAL);
|
server.cluster = (clusterState*)zmalloc(sizeof(clusterState), MALLOC_LOCAL);
|
||||||
server.cluster->myself = NULL;
|
server.cluster->myself = NULL;
|
||||||
server.cluster->currentEpoch = 0;
|
server.cluster->currentEpoch = 0;
|
||||||
server.cluster->state = CLUSTER_FAIL;
|
server.cluster->state = CLUSTER_FAIL;
|
||||||
@ -552,7 +552,7 @@ void clusterReset(int hard) {
|
|||||||
if (listLength(server.masters) > 0)
|
if (listLength(server.masters) > 0)
|
||||||
{
|
{
|
||||||
serverAssert(listLength(server.masters) == 1);
|
serverAssert(listLength(server.masters) == 1);
|
||||||
replicationUnsetMaster(listFirst(server.masters)->value);
|
replicationUnsetMaster((redisMaster*)listFirst(server.masters)->value);
|
||||||
}
|
}
|
||||||
emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
||||||
}
|
}
|
||||||
@ -567,7 +567,7 @@ void clusterReset(int hard) {
|
|||||||
/* Forget all the nodes, but myself. */
|
/* Forget all the nodes, but myself. */
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (node == myself) continue;
|
if (node == myself) continue;
|
||||||
clusterDelNode(node);
|
clusterDelNode(node);
|
||||||
@ -604,7 +604,7 @@ void clusterReset(int hard) {
|
|||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
clusterLink *createClusterLink(clusterNode *node) {
|
clusterLink *createClusterLink(clusterNode *node) {
|
||||||
clusterLink *link = zmalloc(sizeof(*link), MALLOC_LOCAL);
|
clusterLink *link = (clusterLink*)zmalloc(sizeof(*link), MALLOC_LOCAL);
|
||||||
link->ctime = mstime();
|
link->ctime = mstime();
|
||||||
link->sndbuf = sdsempty();
|
link->sndbuf = sdsempty();
|
||||||
link->rcvbuf = sdsempty();
|
link->rcvbuf = sdsempty();
|
||||||
@ -709,7 +709,7 @@ unsigned int keyHashSlot(char *key, int keylen) {
|
|||||||
* The node is created and returned to the user, but it is not automatically
|
* The node is created and returned to the user, but it is not automatically
|
||||||
* added to the nodes hash table. */
|
* added to the nodes hash table. */
|
||||||
clusterNode *createClusterNode(char *nodename, int flags) {
|
clusterNode *createClusterNode(char *nodename, int flags) {
|
||||||
clusterNode *node = zmalloc(sizeof(*node), MALLOC_LOCAL);
|
clusterNode *node = (clusterNode*)zmalloc(sizeof(*node), MALLOC_LOCAL);
|
||||||
|
|
||||||
if (nodename)
|
if (nodename)
|
||||||
memcpy(node->name, nodename, CLUSTER_NAMELEN);
|
memcpy(node->name, nodename, CLUSTER_NAMELEN);
|
||||||
@ -758,7 +758,7 @@ int clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) {
|
|||||||
* the timestamp. */
|
* the timestamp. */
|
||||||
listRewind(l,&li);
|
listRewind(l,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
fr = ln->value;
|
fr = (clusterNodeFailReport*)ln->value;
|
||||||
if (fr->node == sender) {
|
if (fr->node == sender) {
|
||||||
fr->time = mstime();
|
fr->time = mstime();
|
||||||
return 0;
|
return 0;
|
||||||
@ -766,7 +766,7 @@ int clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise create a new report. */
|
/* Otherwise create a new report. */
|
||||||
fr = zmalloc(sizeof(*fr), MALLOC_LOCAL);
|
fr = (clusterNodeFailReport*)zmalloc(sizeof(*fr), MALLOC_LOCAL);
|
||||||
fr->node = sender;
|
fr->node = sender;
|
||||||
fr->time = mstime();
|
fr->time = mstime();
|
||||||
listAddNodeTail(l,fr);
|
listAddNodeTail(l,fr);
|
||||||
@ -789,7 +789,7 @@ void clusterNodeCleanupFailureReports(clusterNode *node) {
|
|||||||
|
|
||||||
listRewind(l,&li);
|
listRewind(l,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
fr = ln->value;
|
fr = (clusterNodeFailReport*)ln->value;
|
||||||
if (now - fr->time > maxtime) listDelNode(l,ln);
|
if (now - fr->time > maxtime) listDelNode(l,ln);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -814,7 +814,7 @@ int clusterNodeDelFailureReport(clusterNode *node, clusterNode *sender) {
|
|||||||
/* Search for a failure report from this sender. */
|
/* Search for a failure report from this sender. */
|
||||||
listRewind(l,&li);
|
listRewind(l,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
fr = ln->value;
|
fr = (clusterNodeFailReport*)ln->value;
|
||||||
if (fr->node == sender) break;
|
if (fr->node == sender) break;
|
||||||
}
|
}
|
||||||
if (!ln) return 0; /* No failure report from this sender. */
|
if (!ln) return 0; /* No failure report from this sender. */
|
||||||
@ -858,7 +858,7 @@ int clusterNodeAddSlave(clusterNode *master, clusterNode *slave) {
|
|||||||
/* If it's already a slave, don't add it again. */
|
/* If it's already a slave, don't add it again. */
|
||||||
for (j = 0; j < master->numslaves; j++)
|
for (j = 0; j < master->numslaves; j++)
|
||||||
if (master->slaves[j] == slave) return C_ERR;
|
if (master->slaves[j] == slave) return C_ERR;
|
||||||
master->slaves = zrealloc(master->slaves,
|
master->slaves = (clusterNode**)zrealloc(master->slaves,
|
||||||
sizeof(clusterNode*)*(master->numslaves+1), MALLOC_LOCAL);
|
sizeof(clusterNode*)*(master->numslaves+1), MALLOC_LOCAL);
|
||||||
master->slaves[master->numslaves] = slave;
|
master->slaves[master->numslaves] = slave;
|
||||||
master->numslaves++;
|
master->numslaves++;
|
||||||
@ -937,7 +937,7 @@ void clusterDelNode(clusterNode *delnode) {
|
|||||||
/* 2) Remove failure reports. */
|
/* 2) Remove failure reports. */
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (node == delnode) continue;
|
if (node == delnode) continue;
|
||||||
clusterNodeDelFailureReport(node,delnode);
|
clusterNodeDelFailureReport(node,delnode);
|
||||||
@ -956,7 +956,7 @@ clusterNode *clusterLookupNode(const char *name) {
|
|||||||
de = dictFind(server.cluster->nodes,s);
|
de = dictFind(server.cluster->nodes,s);
|
||||||
sdsfree(s);
|
sdsfree(s);
|
||||||
if (de == NULL) return NULL;
|
if (de == NULL) return NULL;
|
||||||
return dictGetVal(de);
|
return (clusterNode*)dictGetVal(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is only used after the handshake. When we connect a given IP/PORT
|
/* This is only used after the handshake. When we connect a given IP/PORT
|
||||||
@ -989,7 +989,7 @@ uint64_t clusterGetMaxEpoch(void) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
if (node->configEpoch > max) max = node->configEpoch;
|
if (node->configEpoch > max) max = node->configEpoch;
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
@ -1277,7 +1277,7 @@ int clusterHandshakeInProgress(char *ip, int port, int cport) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (!nodeInHandshake(node)) continue;
|
if (!nodeInHandshake(node)) continue;
|
||||||
if (!strcasecmp(node->ip,ip) &&
|
if (!strcasecmp(node->ip,ip) &&
|
||||||
@ -2253,12 +2253,12 @@ void clusterBroadcastMessage(void *buf, size_t len) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (!node->link) continue;
|
if (!node->link) continue;
|
||||||
if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))
|
if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))
|
||||||
continue;
|
continue;
|
||||||
clusterSendMessage(node->link,buf,len);
|
clusterSendMessage(node->link,(unsigned char*)buf,len);
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
}
|
}
|
||||||
@ -2422,7 +2422,7 @@ void clusterSendPing(clusterLink *link, int type) {
|
|||||||
/* Note: clusterBuildMessageHdr() expects the buffer to be always at least
|
/* Note: clusterBuildMessageHdr() expects the buffer to be always at least
|
||||||
* sizeof(clusterMsg) or more. */
|
* sizeof(clusterMsg) or more. */
|
||||||
if (totlen < (int)sizeof(clusterMsg)) totlen = sizeof(clusterMsg);
|
if (totlen < (int)sizeof(clusterMsg)) totlen = sizeof(clusterMsg);
|
||||||
buf = zcalloc(totlen, MALLOC_LOCAL);
|
buf = (unsigned char*)zcalloc(totlen, MALLOC_LOCAL);
|
||||||
hdr = (clusterMsg*) buf;
|
hdr = (clusterMsg*) buf;
|
||||||
|
|
||||||
/* Populate the header. */
|
/* Populate the header. */
|
||||||
@ -2434,32 +2434,32 @@ void clusterSendPing(clusterLink *link, int type) {
|
|||||||
int maxiterations = wanted*3;
|
int maxiterations = wanted*3;
|
||||||
while(freshnodes > 0 && gossipcount < wanted && maxiterations--) {
|
while(freshnodes > 0 && gossipcount < wanted && maxiterations--) {
|
||||||
dictEntry *de = dictGetRandomKey(server.cluster->nodes);
|
dictEntry *de = dictGetRandomKey(server.cluster->nodes);
|
||||||
clusterNode *this = dictGetVal(de);
|
clusterNode *thisNode = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
/* Don't include this node: the whole packet header is about us
|
/* Don't include this node: the whole packet header is about us
|
||||||
* already, so we just gossip about other nodes. */
|
* already, so we just gossip about other nodes. */
|
||||||
if (this == myself) continue;
|
if (thisNode == myself) continue;
|
||||||
|
|
||||||
/* PFAIL nodes will be added later. */
|
/* PFAIL nodes will be added later. */
|
||||||
if (this->flags & CLUSTER_NODE_PFAIL) continue;
|
if (thisNode->flags & CLUSTER_NODE_PFAIL) continue;
|
||||||
|
|
||||||
/* In the gossip section don't include:
|
/* In the gossip section don't include:
|
||||||
* 1) Nodes in HANDSHAKE state.
|
* 1) Nodes in HANDSHAKE state.
|
||||||
* 3) Nodes with the NOADDR flag set.
|
* 3) Nodes with the NOADDR flag set.
|
||||||
* 4) Disconnected nodes if they don't have configured slots.
|
* 4) Disconnected nodes if they don't have configured slots.
|
||||||
*/
|
*/
|
||||||
if (this->flags & (CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_NOADDR) ||
|
if (thisNode->flags & (CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_NOADDR) ||
|
||||||
(this->link == NULL && this->numslots == 0))
|
(thisNode->link == NULL && thisNode->numslots == 0))
|
||||||
{
|
{
|
||||||
freshnodes--; /* Tecnically not correct, but saves CPU. */
|
freshnodes--; /* Tecnically not correct, but saves CPU. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not add a node we already have. */
|
/* Do not add a node we already have. */
|
||||||
if (clusterNodeIsInGossipSection(hdr,gossipcount,this)) continue;
|
if (clusterNodeIsInGossipSection(hdr,gossipcount,thisNode)) continue;
|
||||||
|
|
||||||
/* Add it */
|
/* Add it */
|
||||||
clusterSetGossipEntry(hdr,gossipcount,this);
|
clusterSetGossipEntry(hdr,gossipcount,thisNode);
|
||||||
freshnodes--;
|
freshnodes--;
|
||||||
gossipcount++;
|
gossipcount++;
|
||||||
}
|
}
|
||||||
@ -2471,7 +2471,7 @@ void clusterSendPing(clusterLink *link, int type) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL && pfail_wanted > 0) {
|
while((de = dictNext(di)) != NULL && pfail_wanted > 0) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
if (node->flags & CLUSTER_NODE_HANDSHAKE) continue;
|
if (node->flags & CLUSTER_NODE_HANDSHAKE) continue;
|
||||||
if (node->flags & CLUSTER_NODE_NOADDR) continue;
|
if (node->flags & CLUSTER_NODE_NOADDR) continue;
|
||||||
if (!(node->flags & CLUSTER_NODE_PFAIL)) continue;
|
if (!(node->flags & CLUSTER_NODE_PFAIL)) continue;
|
||||||
@ -2518,7 +2518,7 @@ void clusterBroadcastPong(int target) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (!node->link) continue;
|
if (!node->link) continue;
|
||||||
if (node == myself || nodeInHandshake(node)) continue;
|
if (node == myself || nodeInHandshake(node)) continue;
|
||||||
@ -2544,8 +2544,8 @@ void clusterSendPublish(clusterLink *link, robj *channel, robj *message) {
|
|||||||
|
|
||||||
channel = getDecodedObject(channel);
|
channel = getDecodedObject(channel);
|
||||||
message = getDecodedObject(message);
|
message = getDecodedObject(message);
|
||||||
channel_len = sdslen(ptrFromObj(channel));
|
channel_len = sdslen(szFromObj(channel));
|
||||||
message_len = sdslen(ptrFromObj(message));
|
message_len = sdslen(szFromObj(message));
|
||||||
|
|
||||||
clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_PUBLISH);
|
clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_PUBLISH);
|
||||||
totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
|
totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
|
||||||
@ -2559,13 +2559,13 @@ void clusterSendPublish(clusterLink *link, robj *channel, robj *message) {
|
|||||||
if (totlen < sizeof(buf)) {
|
if (totlen < sizeof(buf)) {
|
||||||
payload = buf;
|
payload = buf;
|
||||||
} else {
|
} else {
|
||||||
payload = zmalloc(totlen, MALLOC_LOCAL);
|
payload = (unsigned char*)zmalloc(totlen, MALLOC_LOCAL);
|
||||||
memcpy(payload,hdr,sizeof(*hdr));
|
memcpy(payload,hdr,sizeof(*hdr));
|
||||||
hdr = (clusterMsg*) payload;
|
hdr = (clusterMsg*) payload;
|
||||||
}
|
}
|
||||||
memcpy(hdr->data.publish.msg.bulk_data,ptrFromObj(channel),sdslen(ptrFromObj(channel)));
|
memcpy(hdr->data.publish.msg.bulk_data,ptrFromObj(channel),sdslen(szFromObj(channel)));
|
||||||
memcpy(hdr->data.publish.msg.bulk_data+sdslen(ptrFromObj(channel)),
|
memcpy(hdr->data.publish.msg.bulk_data+sdslen(szFromObj(channel)),
|
||||||
ptrFromObj(message),sdslen(ptrFromObj(message)));
|
ptrFromObj(message),sdslen(szFromObj(message)));
|
||||||
|
|
||||||
if (link)
|
if (link)
|
||||||
clusterSendMessage(link,payload,totlen);
|
clusterSendMessage(link,payload,totlen);
|
||||||
@ -2628,7 +2628,7 @@ void clusterSendModule(clusterLink *link, uint64_t module_id, uint8_t type,
|
|||||||
if (totlen < sizeof(buf)) {
|
if (totlen < sizeof(buf)) {
|
||||||
heapbuf = buf;
|
heapbuf = buf;
|
||||||
} else {
|
} else {
|
||||||
heapbuf = zmalloc(totlen, MALLOC_LOCAL);
|
heapbuf = (unsigned char*)zmalloc(totlen, MALLOC_LOCAL);
|
||||||
memcpy(heapbuf,hdr,sizeof(*hdr));
|
memcpy(heapbuf,hdr,sizeof(*hdr));
|
||||||
hdr = (clusterMsg*) heapbuf;
|
hdr = (clusterMsg*) heapbuf;
|
||||||
}
|
}
|
||||||
@ -2879,7 +2879,7 @@ int clusterGetSlaveRank(void) {
|
|||||||
*
|
*
|
||||||
* The function is guaranteed to be called only if 'myself' is a slave. */
|
* The function is guaranteed to be called only if 'myself' is a slave. */
|
||||||
void clusterLogCantFailover(int reason) {
|
void clusterLogCantFailover(int reason) {
|
||||||
char *msg;
|
const char *msg;
|
||||||
static time_t lastlog_time = 0;
|
static time_t lastlog_time = 0;
|
||||||
mstime_t nolog_fail_time = server.cluster_node_timeout + 5000;
|
mstime_t nolog_fail_time = server.cluster_node_timeout + 5000;
|
||||||
|
|
||||||
@ -3192,7 +3192,7 @@ void clusterHandleSlaveMigration(int max_slaves) {
|
|||||||
candidate = myself;
|
candidate = myself;
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
int okslaves = 0, is_orphaned = 1;
|
int okslaves = 0, is_orphaned = 1;
|
||||||
|
|
||||||
/* We want to migrate only if this master is working, orphaned, and
|
/* We want to migrate only if this master is working, orphaned, and
|
||||||
@ -3386,7 +3386,7 @@ void clusterCron(void) {
|
|||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
server.cluster->stats_pfail_nodes = 0;
|
server.cluster->stats_pfail_nodes = 0;
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
/* Not interested in reconnecting the link with myself or nodes
|
/* Not interested in reconnecting the link with myself or nodes
|
||||||
* for which we have no address. */
|
* for which we have no address. */
|
||||||
@ -3463,15 +3463,15 @@ void clusterCron(void) {
|
|||||||
* pong_received time. */
|
* pong_received time. */
|
||||||
for (j = 0; j < 5; j++) {
|
for (j = 0; j < 5; j++) {
|
||||||
de = dictGetRandomKey(server.cluster->nodes);
|
de = dictGetRandomKey(server.cluster->nodes);
|
||||||
clusterNode *this = dictGetVal(de);
|
clusterNode *thisNode = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
/* Don't ping nodes disconnected or with a ping currently active. */
|
/* Don't ping nodes disconnected or with a ping currently active. */
|
||||||
if (this->link == NULL || this->ping_sent != 0) continue;
|
if (thisNode->link == NULL || thisNode->ping_sent != 0) continue;
|
||||||
if (this->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))
|
if (thisNode->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))
|
||||||
continue;
|
continue;
|
||||||
if (min_pong_node == NULL || min_pong > this->pong_received) {
|
if (min_pong_node == NULL || min_pong > thisNode->pong_received) {
|
||||||
min_pong_node = this;
|
min_pong_node = thisNode;
|
||||||
min_pong = this->pong_received;
|
min_pong = thisNode->pong_received;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (min_pong_node) {
|
if (min_pong_node) {
|
||||||
@ -3491,7 +3491,7 @@ void clusterCron(void) {
|
|||||||
this_slaves = 0;
|
this_slaves = 0;
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
now = mstime(); /* Use an updated time at every iteration. */
|
now = mstime(); /* Use an updated time at every iteration. */
|
||||||
mstime_t delay;
|
mstime_t delay;
|
||||||
|
|
||||||
@ -3672,7 +3672,7 @@ int clusterMastersHaveSlaves(void) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
int slaves = 0;
|
int slaves = 0;
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (nodeIsSlave(node)) continue;
|
if (nodeIsSlave(node)) continue;
|
||||||
slaves += node->numslaves;
|
slaves += node->numslaves;
|
||||||
@ -3824,7 +3824,7 @@ void clusterUpdateState(void) {
|
|||||||
server.cluster->size = 0;
|
server.cluster->size = 0;
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (nodeIsMaster(node) && node->numslots) {
|
if (nodeIsMaster(node) && node->numslots) {
|
||||||
server.cluster->size++;
|
server.cluster->size++;
|
||||||
@ -3974,7 +3974,7 @@ void clusterSetMaster(clusterNode *n) {
|
|||||||
|
|
||||||
struct redisNodeFlags {
|
struct redisNodeFlags {
|
||||||
uint16_t flag;
|
uint16_t flag;
|
||||||
char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct redisNodeFlags redisNodeFlagsTable[] = {
|
static struct redisNodeFlags redisNodeFlagsTable[] = {
|
||||||
@ -4091,7 +4091,7 @@ sds clusterGenNodesDescription(int filter) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.cluster->nodes);
|
di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
|
|
||||||
if (node->flags & filter) continue;
|
if (node->flags & filter) continue;
|
||||||
ni = clusterGenNodeDescription(node);
|
ni = clusterGenNodeDescription(node);
|
||||||
@ -4153,7 +4153,7 @@ void clusterReplyMultiBulkSlots(client *c) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
dictIterator *di = dictGetSafeIterator(server.cluster->nodes);
|
dictIterator *di = dictGetSafeIterator(server.cluster->nodes);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
clusterNode *node = dictGetVal(de);
|
clusterNode *node = (clusterNode*)dictGetVal(de);
|
||||||
int j = 0, start = -1;
|
int j = 0, start = -1;
|
||||||
|
|
||||||
/* Skip slaves (that are iterated when producing the output of their
|
/* Skip slaves (that are iterated when producing the output of their
|
||||||
@ -4215,7 +4215,7 @@ void clusterCommand(client *c) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"help")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"ADDSLOTS <slot> [slot ...] -- Assign slots to current node.",
|
"ADDSLOTS <slot> [slot ...] -- Assign slots to current node.",
|
||||||
"BUMPEPOCH -- Advance the cluster config epoch.",
|
"BUMPEPOCH -- Advance the cluster config epoch.",
|
||||||
@ -4242,7 +4242,7 @@ void clusterCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"meet") && (c->argc == 4 || c->argc == 5)) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"meet") && (c->argc == 4 || c->argc == 5)) {
|
||||||
/* CLUSTER MEET <ip> <port> [cport] */
|
/* CLUSTER MEET <ip> <port> [cport] */
|
||||||
long long port, cport;
|
long long port, cport;
|
||||||
|
|
||||||
@ -4262,7 +4262,7 @@ NULL
|
|||||||
cport = port + CLUSTER_PORT_INCR;
|
cport = port + CLUSTER_PORT_INCR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clusterStartHandshake(ptrFromObj(c->argv[2]),port,cport) == 0 &&
|
if (clusterStartHandshake(szFromObj(c->argv[2]),port,cport) == 0 &&
|
||||||
errno == EINVAL)
|
errno == EINVAL)
|
||||||
{
|
{
|
||||||
addReplyErrorFormat(c,"Invalid node address specified: %s:%s",
|
addReplyErrorFormat(c,"Invalid node address specified: %s:%s",
|
||||||
@ -4270,7 +4270,7 @@ NULL
|
|||||||
} else {
|
} else {
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"nodes") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"nodes") && c->argc == 2) {
|
||||||
/* CLUSTER NODES */
|
/* CLUSTER NODES */
|
||||||
robj *o;
|
robj *o;
|
||||||
sds ci = clusterGenNodesDescription(0);
|
sds ci = clusterGenNodesDescription(0);
|
||||||
@ -4278,13 +4278,13 @@ NULL
|
|||||||
o = createObject(OBJ_STRING,ci);
|
o = createObject(OBJ_STRING,ci);
|
||||||
addReplyBulk(c,o);
|
addReplyBulk(c,o);
|
||||||
decrRefCount(o);
|
decrRefCount(o);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"myid") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"myid") && c->argc == 2) {
|
||||||
/* CLUSTER MYID */
|
/* CLUSTER MYID */
|
||||||
addReplyBulkCBuffer(c,myself->name, CLUSTER_NAMELEN);
|
addReplyBulkCBuffer(c,myself->name, CLUSTER_NAMELEN);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"slots") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"slots") && c->argc == 2) {
|
||||||
/* CLUSTER SLOTS */
|
/* CLUSTER SLOTS */
|
||||||
clusterReplyMultiBulkSlots(c);
|
clusterReplyMultiBulkSlots(c);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"flushslots") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"flushslots") && c->argc == 2) {
|
||||||
/* CLUSTER FLUSHSLOTS */
|
/* CLUSTER FLUSHSLOTS */
|
||||||
if (dictSize(server.db[0].pdict) != 0) {
|
if (dictSize(server.db[0].pdict) != 0) {
|
||||||
addReplyError(c,"DB must be empty to perform CLUSTER FLUSHSLOTS.");
|
addReplyError(c,"DB must be empty to perform CLUSTER FLUSHSLOTS.");
|
||||||
@ -4293,14 +4293,14 @@ NULL
|
|||||||
clusterDelNodeSlots(myself);
|
clusterDelNodeSlots(myself);
|
||||||
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
|
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if ((!strcasecmp(ptrFromObj(c->argv[1]),"addslots") ||
|
} else if ((!strcasecmp(szFromObj(c->argv[1]),"addslots") ||
|
||||||
!strcasecmp(ptrFromObj(c->argv[1]),"delslots")) && c->argc >= 3)
|
!strcasecmp(szFromObj(c->argv[1]),"delslots")) && c->argc >= 3)
|
||||||
{
|
{
|
||||||
/* CLUSTER ADDSLOTS <slot> [slot] ... */
|
/* CLUSTER ADDSLOTS <slot> [slot] ... */
|
||||||
/* CLUSTER DELSLOTS <slot> [slot] ... */
|
/* CLUSTER DELSLOTS <slot> [slot] ... */
|
||||||
int j, slot;
|
int j, slot;
|
||||||
unsigned char *slots = zmalloc(CLUSTER_SLOTS, MALLOC_LOCAL);
|
unsigned char *slots = (unsigned char*)zmalloc(CLUSTER_SLOTS, MALLOC_LOCAL);
|
||||||
int del = !strcasecmp(ptrFromObj(c->argv[1]),"delslots");
|
int del = !strcasecmp(szFromObj(c->argv[1]),"delslots");
|
||||||
|
|
||||||
memset(slots,0,CLUSTER_SLOTS);
|
memset(slots,0,CLUSTER_SLOTS);
|
||||||
/* Check that all the arguments are parseable and that all the
|
/* Check that all the arguments are parseable and that all the
|
||||||
@ -4343,7 +4343,7 @@ NULL
|
|||||||
zfree(slots);
|
zfree(slots);
|
||||||
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
|
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"setslot") && c->argc >= 4) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"setslot") && c->argc >= 4) {
|
||||||
/* SETSLOT 10 MIGRATING <node ID> */
|
/* SETSLOT 10 MIGRATING <node ID> */
|
||||||
/* SETSLOT 10 IMPORTING <node ID> */
|
/* SETSLOT 10 IMPORTING <node ID> */
|
||||||
/* SETSLOT 10 STABLE */
|
/* SETSLOT 10 STABLE */
|
||||||
@ -4358,36 +4358,36 @@ NULL
|
|||||||
|
|
||||||
if ((slot = getSlotOrReply(c,c->argv[2])) == -1) return;
|
if ((slot = getSlotOrReply(c,c->argv[2])) == -1) return;
|
||||||
|
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[3]),"migrating") && c->argc == 5) {
|
if (!strcasecmp(szFromObj(c->argv[3]),"migrating") && c->argc == 5) {
|
||||||
if (server.cluster->slots[slot] != myself) {
|
if (server.cluster->slots[slot] != myself) {
|
||||||
addReplyErrorFormat(c,"I'm not the owner of hash slot %u",slot);
|
addReplyErrorFormat(c,"I'm not the owner of hash slot %u",slot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((n = clusterLookupNode(ptrFromObj(c->argv[4]))) == NULL) {
|
if ((n = clusterLookupNode(szFromObj(c->argv[4]))) == NULL) {
|
||||||
addReplyErrorFormat(c,"I don't know about node %s",
|
addReplyErrorFormat(c,"I don't know about node %s",
|
||||||
(char*)ptrFromObj(c->argv[4]));
|
(char*)ptrFromObj(c->argv[4]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
server.cluster->migrating_slots_to[slot] = n;
|
server.cluster->migrating_slots_to[slot] = n;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[3]),"importing") && c->argc == 5) {
|
} else if (!strcasecmp(szFromObj(c->argv[3]),"importing") && c->argc == 5) {
|
||||||
if (server.cluster->slots[slot] == myself) {
|
if (server.cluster->slots[slot] == myself) {
|
||||||
addReplyErrorFormat(c,
|
addReplyErrorFormat(c,
|
||||||
"I'm already the owner of hash slot %u",slot);
|
"I'm already the owner of hash slot %u",slot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((n = clusterLookupNode(ptrFromObj(c->argv[4]))) == NULL) {
|
if ((n = clusterLookupNode(szFromObj(c->argv[4]))) == NULL) {
|
||||||
addReplyErrorFormat(c,"I don't know about node %s",
|
addReplyErrorFormat(c,"I don't know about node %s",
|
||||||
(char*)ptrFromObj(c->argv[4]));
|
(char*)ptrFromObj(c->argv[4]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
server.cluster->importing_slots_from[slot] = n;
|
server.cluster->importing_slots_from[slot] = n;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[3]),"stable") && c->argc == 4) {
|
} else if (!strcasecmp(szFromObj(c->argv[3]),"stable") && c->argc == 4) {
|
||||||
/* CLUSTER SETSLOT <SLOT> STABLE */
|
/* CLUSTER SETSLOT <SLOT> STABLE */
|
||||||
server.cluster->importing_slots_from[slot] = NULL;
|
server.cluster->importing_slots_from[slot] = NULL;
|
||||||
server.cluster->migrating_slots_to[slot] = NULL;
|
server.cluster->migrating_slots_to[slot] = NULL;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[3]),"node") && c->argc == 5) {
|
} else if (!strcasecmp(szFromObj(c->argv[3]),"node") && c->argc == 5) {
|
||||||
/* CLUSTER SETSLOT <SLOT> NODE <NODE ID> */
|
/* CLUSTER SETSLOT <SLOT> NODE <NODE ID> */
|
||||||
clusterNode *n = clusterLookupNode(ptrFromObj(c->argv[4]));
|
clusterNode *n = clusterLookupNode(szFromObj(c->argv[4]));
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
addReplyErrorFormat(c,"Unknown node %s",
|
addReplyErrorFormat(c,"Unknown node %s",
|
||||||
@ -4440,16 +4440,16 @@ NULL
|
|||||||
}
|
}
|
||||||
clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|CLUSTER_TODO_UPDATE_STATE);
|
clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|CLUSTER_TODO_UPDATE_STATE);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"bumpepoch") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"bumpepoch") && c->argc == 2) {
|
||||||
/* CLUSTER BUMPEPOCH */
|
/* CLUSTER BUMPEPOCH */
|
||||||
int retval = clusterBumpConfigEpochWithoutConsensus();
|
int retval = clusterBumpConfigEpochWithoutConsensus();
|
||||||
sds reply = sdscatprintf(sdsempty(),"+%s %llu\r\n",
|
sds reply = sdscatprintf(sdsempty(),"+%s %llu\r\n",
|
||||||
(retval == C_OK) ? "BUMPED" : "STILL",
|
(retval == C_OK) ? "BUMPED" : "STILL",
|
||||||
(unsigned long long) myself->configEpoch);
|
(unsigned long long) myself->configEpoch);
|
||||||
addReplySds(c,reply);
|
addReplySds(c,reply);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"info") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"info") && c->argc == 2) {
|
||||||
/* CLUSTER INFO */
|
/* CLUSTER INFO */
|
||||||
char *statestr[] = {"ok","fail","needhelp"};
|
const char *statestr[] = {"ok","fail","needhelp"};
|
||||||
int slots_assigned = 0, slots_ok = 0, slots_pfail = 0, slots_fail = 0;
|
int slots_assigned = 0, slots_ok = 0, slots_pfail = 0, slots_fail = 0;
|
||||||
uint64_t myepoch;
|
uint64_t myepoch;
|
||||||
int j;
|
int j;
|
||||||
@ -4523,7 +4523,7 @@ NULL
|
|||||||
(unsigned long)sdslen(info)));
|
(unsigned long)sdslen(info)));
|
||||||
addReplySds(c,info);
|
addReplySds(c,info);
|
||||||
addReply(c,shared.crlf);
|
addReply(c,shared.crlf);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"saveconfig") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"saveconfig") && c->argc == 2) {
|
||||||
int retval = clusterSaveConfig(1);
|
int retval = clusterSaveConfig(1);
|
||||||
|
|
||||||
if (retval == 0)
|
if (retval == 0)
|
||||||
@ -4531,12 +4531,12 @@ NULL
|
|||||||
else
|
else
|
||||||
addReplyErrorFormat(c,"error saving the cluster node config: %s",
|
addReplyErrorFormat(c,"error saving the cluster node config: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"keyslot") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"keyslot") && c->argc == 3) {
|
||||||
/* CLUSTER KEYSLOT <key> */
|
/* CLUSTER KEYSLOT <key> */
|
||||||
sds key = ptrFromObj(c->argv[2]);
|
sds key = szFromObj(c->argv[2]);
|
||||||
|
|
||||||
addReplyLongLong(c,keyHashSlot(key,sdslen(key)));
|
addReplyLongLong(c,keyHashSlot(key,sdslen(key)));
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"countkeysinslot") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"countkeysinslot") && c->argc == 3) {
|
||||||
/* CLUSTER COUNTKEYSINSLOT <slot> */
|
/* CLUSTER COUNTKEYSINSLOT <slot> */
|
||||||
long long slot;
|
long long slot;
|
||||||
|
|
||||||
@ -4547,7 +4547,7 @@ NULL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addReplyLongLong(c,countKeysInSlot(slot));
|
addReplyLongLong(c,countKeysInSlot(slot));
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"getkeysinslot") && c->argc == 4) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"getkeysinslot") && c->argc == 4) {
|
||||||
/* CLUSTER GETKEYSINSLOT <slot> <count> */
|
/* CLUSTER GETKEYSINSLOT <slot> <count> */
|
||||||
long long maxkeys, slot;
|
long long maxkeys, slot;
|
||||||
unsigned int numkeys, j;
|
unsigned int numkeys, j;
|
||||||
@ -4568,7 +4568,7 @@ NULL
|
|||||||
unsigned int keys_in_slot = countKeysInSlot(slot);
|
unsigned int keys_in_slot = countKeysInSlot(slot);
|
||||||
if (maxkeys > keys_in_slot) maxkeys = keys_in_slot;
|
if (maxkeys > keys_in_slot) maxkeys = keys_in_slot;
|
||||||
|
|
||||||
keys = zmalloc(sizeof(robj*)*maxkeys, MALLOC_LOCAL);
|
keys = (robj**)zmalloc(sizeof(robj*)*maxkeys, MALLOC_LOCAL);
|
||||||
numkeys = getKeysInSlot(slot, keys, maxkeys);
|
numkeys = getKeysInSlot(slot, keys, maxkeys);
|
||||||
addReplyArrayLen(c,numkeys);
|
addReplyArrayLen(c,numkeys);
|
||||||
for (j = 0; j < numkeys; j++) {
|
for (j = 0; j < numkeys; j++) {
|
||||||
@ -4576,9 +4576,9 @@ NULL
|
|||||||
decrRefCount(keys[j]);
|
decrRefCount(keys[j]);
|
||||||
}
|
}
|
||||||
zfree(keys);
|
zfree(keys);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"forget") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"forget") && c->argc == 3) {
|
||||||
/* CLUSTER FORGET <NODE ID> */
|
/* CLUSTER FORGET <NODE ID> */
|
||||||
clusterNode *n = clusterLookupNode(ptrFromObj(c->argv[2]));
|
clusterNode *n = clusterLookupNode(szFromObj(c->argv[2]));
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
addReplyErrorFormat(c,"Unknown node %s", (char*)ptrFromObj(c->argv[2]));
|
addReplyErrorFormat(c,"Unknown node %s", (char*)ptrFromObj(c->argv[2]));
|
||||||
@ -4595,9 +4595,9 @@ NULL
|
|||||||
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|
|
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|
|
||||||
CLUSTER_TODO_SAVE_CONFIG);
|
CLUSTER_TODO_SAVE_CONFIG);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"replicate") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"replicate") && c->argc == 3) {
|
||||||
/* CLUSTER REPLICATE <NODE ID> */
|
/* CLUSTER REPLICATE <NODE ID> */
|
||||||
clusterNode *n = clusterLookupNode(ptrFromObj(c->argv[2]));
|
clusterNode *n = clusterLookupNode(szFromObj(c->argv[2]));
|
||||||
|
|
||||||
/* Lookup the specified node in our table. */
|
/* Lookup the specified node in our table. */
|
||||||
if (!n) {
|
if (!n) {
|
||||||
@ -4632,10 +4632,10 @@ NULL
|
|||||||
clusterSetMaster(n);
|
clusterSetMaster(n);
|
||||||
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
|
clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if ((!strcasecmp(ptrFromObj(c->argv[1]),"slaves") ||
|
} else if ((!strcasecmp(szFromObj(c->argv[1]),"slaves") ||
|
||||||
!strcasecmp(ptrFromObj(c->argv[1]),"replicas")) && c->argc == 3) {
|
!strcasecmp(szFromObj(c->argv[1]),"replicas")) && c->argc == 3) {
|
||||||
/* CLUSTER SLAVES <NODE ID> */
|
/* CLUSTER SLAVES <NODE ID> */
|
||||||
clusterNode *n = clusterLookupNode(ptrFromObj(c->argv[2]));
|
clusterNode *n = clusterLookupNode(szFromObj(c->argv[2]));
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
/* Lookup the specified node in our table. */
|
/* Lookup the specified node in our table. */
|
||||||
@ -4655,11 +4655,11 @@ NULL
|
|||||||
addReplyBulkCString(c,ni);
|
addReplyBulkCString(c,ni);
|
||||||
sdsfree(ni);
|
sdsfree(ni);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"count-failure-reports") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"count-failure-reports") &&
|
||||||
c->argc == 3)
|
c->argc == 3)
|
||||||
{
|
{
|
||||||
/* CLUSTER COUNT-FAILURE-REPORTS <NODE ID> */
|
/* CLUSTER COUNT-FAILURE-REPORTS <NODE ID> */
|
||||||
clusterNode *n = clusterLookupNode(ptrFromObj(c->argv[2]));
|
clusterNode *n = clusterLookupNode(szFromObj(c->argv[2]));
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
addReplyErrorFormat(c,"Unknown node %s", (char*)ptrFromObj(c->argv[2]));
|
addReplyErrorFormat(c,"Unknown node %s", (char*)ptrFromObj(c->argv[2]));
|
||||||
@ -4667,16 +4667,16 @@ NULL
|
|||||||
} else {
|
} else {
|
||||||
addReplyLongLong(c,clusterNodeFailureReportsCount(n));
|
addReplyLongLong(c,clusterNodeFailureReportsCount(n));
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"failover") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"failover") &&
|
||||||
(c->argc == 2 || c->argc == 3))
|
(c->argc == 2 || c->argc == 3))
|
||||||
{
|
{
|
||||||
/* CLUSTER FAILOVER [FORCE|TAKEOVER] */
|
/* CLUSTER FAILOVER [FORCE|TAKEOVER] */
|
||||||
int force = 0, takeover = 0;
|
int force = 0, takeover = 0;
|
||||||
|
|
||||||
if (c->argc == 3) {
|
if (c->argc == 3) {
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[2]),"force")) {
|
if (!strcasecmp(szFromObj(c->argv[2]),"force")) {
|
||||||
force = 1;
|
force = 1;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),"takeover")) {
|
} else if (!strcasecmp(szFromObj(c->argv[2]),"takeover")) {
|
||||||
takeover = 1;
|
takeover = 1;
|
||||||
force = 1; /* Takeover also implies force. */
|
force = 1; /* Takeover also implies force. */
|
||||||
} else {
|
} else {
|
||||||
@ -4722,7 +4722,7 @@ NULL
|
|||||||
clusterSendMFStart(myself->slaveof);
|
clusterSendMFStart(myself->slaveof);
|
||||||
}
|
}
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"set-config-epoch") && c->argc == 3)
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"set-config-epoch") && c->argc == 3)
|
||||||
{
|
{
|
||||||
/* CLUSTER SET-CONFIG-EPOCH <epoch>
|
/* CLUSTER SET-CONFIG-EPOCH <epoch>
|
||||||
*
|
*
|
||||||
@ -4758,7 +4758,7 @@ NULL
|
|||||||
CLUSTER_TODO_SAVE_CONFIG);
|
CLUSTER_TODO_SAVE_CONFIG);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"reset") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"reset") &&
|
||||||
(c->argc == 2 || c->argc == 3))
|
(c->argc == 2 || c->argc == 3))
|
||||||
{
|
{
|
||||||
/* CLUSTER RESET [SOFT|HARD] */
|
/* CLUSTER RESET [SOFT|HARD] */
|
||||||
@ -4766,9 +4766,9 @@ NULL
|
|||||||
|
|
||||||
/* Parse soft/hard argument. Default is soft. */
|
/* Parse soft/hard argument. Default is soft. */
|
||||||
if (c->argc == 3) {
|
if (c->argc == 3) {
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[2]),"hard")) {
|
if (!strcasecmp(szFromObj(c->argv[2]),"hard")) {
|
||||||
hard = 1;
|
hard = 1;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),"soft")) {
|
} else if (!strcasecmp(szFromObj(c->argv[2]),"soft")) {
|
||||||
hard = 0;
|
hard = 0;
|
||||||
} else {
|
} else {
|
||||||
addReply(c,shared.syntaxerr);
|
addReply(c,shared.syntaxerr);
|
||||||
@ -4882,11 +4882,11 @@ void restoreCommand(client *c) {
|
|||||||
/* Parse additional options */
|
/* Parse additional options */
|
||||||
for (j = 4; j < c->argc; j++) {
|
for (j = 4; j < c->argc; j++) {
|
||||||
int additional = c->argc-j-1;
|
int additional = c->argc-j-1;
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[j]),"replace")) {
|
if (!strcasecmp(szFromObj(c->argv[j]),"replace")) {
|
||||||
replace = 1;
|
replace = 1;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"absttl")) {
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"absttl")) {
|
||||||
absttl = 1;
|
absttl = 1;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"idletime") && additional >= 1 &&
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"idletime") && additional >= 1 &&
|
||||||
lfu_freq == -1)
|
lfu_freq == -1)
|
||||||
{
|
{
|
||||||
if (getLongLongFromObjectOrReply(c,c->argv[j+1],&lru_idle,NULL)
|
if (getLongLongFromObjectOrReply(c,c->argv[j+1],&lru_idle,NULL)
|
||||||
@ -4897,7 +4897,7 @@ void restoreCommand(client *c) {
|
|||||||
}
|
}
|
||||||
lru_clock = LRU_CLOCK();
|
lru_clock = LRU_CLOCK();
|
||||||
j++; /* Consume additional arg. */
|
j++; /* Consume additional arg. */
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"freq") && additional >= 1 &&
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"freq") && additional >= 1 &&
|
||||||
lru_idle == -1)
|
lru_idle == -1)
|
||||||
{
|
{
|
||||||
if (getLongLongFromObjectOrReply(c,c->argv[j+1],&lfu_freq,NULL)
|
if (getLongLongFromObjectOrReply(c,c->argv[j+1],&lfu_freq,NULL)
|
||||||
@ -4928,13 +4928,13 @@ void restoreCommand(client *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Verify RDB version and data checksum. */
|
/* Verify RDB version and data checksum. */
|
||||||
if (verifyDumpPayload(ptrFromObj(c->argv[3]),sdslen(ptrFromObj(c->argv[3]))) == C_ERR)
|
if (verifyDumpPayload((unsigned char*)ptrFromObj(c->argv[3]),sdslen(szFromObj(c->argv[3]))) == C_ERR)
|
||||||
{
|
{
|
||||||
addReplyError(c,"DUMP payload version or checksum are wrong");
|
addReplyError(c,"DUMP payload version or checksum are wrong");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rioInitWithBuffer(&payload,ptrFromObj(c->argv[3]));
|
rioInitWithBuffer(&payload,szFromObj(c->argv[3]));
|
||||||
if (((type = rdbLoadObjectType(&payload)) == -1) ||
|
if (((type = rdbLoadObjectType(&payload)) == -1) ||
|
||||||
((obj = rdbLoadObject(type,&payload,c->argv[1])) == NULL))
|
((obj = rdbLoadObject(type,&payload,c->argv[1])) == NULL))
|
||||||
{
|
{
|
||||||
@ -4989,10 +4989,10 @@ migrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long ti
|
|||||||
migrateCachedSocket *cs;
|
migrateCachedSocket *cs;
|
||||||
|
|
||||||
/* Check if we have an already cached socket for this ip:port pair. */
|
/* Check if we have an already cached socket for this ip:port pair. */
|
||||||
name = sdscatlen(name,ptrFromObj(host),sdslen(ptrFromObj(host)));
|
name = sdscatlen(name,ptrFromObj(host),sdslen(szFromObj(host)));
|
||||||
name = sdscatlen(name,":",1);
|
name = sdscatlen(name,":",1);
|
||||||
name = sdscatlen(name,ptrFromObj(port),sdslen(ptrFromObj(port)));
|
name = sdscatlen(name,ptrFromObj(port),sdslen(szFromObj(port)));
|
||||||
cs = dictFetchValue(server.migrate_cached_sockets,name);
|
cs = (migrateCachedSocket*)dictFetchValue(server.migrate_cached_sockets,name);
|
||||||
if (cs) {
|
if (cs) {
|
||||||
sdsfree(name);
|
sdsfree(name);
|
||||||
cs->last_use_time = server.unixtime;
|
cs->last_use_time = server.unixtime;
|
||||||
@ -5003,15 +5003,15 @@ migrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long ti
|
|||||||
if (dictSize(server.migrate_cached_sockets) == MIGRATE_SOCKET_CACHE_ITEMS) {
|
if (dictSize(server.migrate_cached_sockets) == MIGRATE_SOCKET_CACHE_ITEMS) {
|
||||||
/* Too many items, drop one at random. */
|
/* Too many items, drop one at random. */
|
||||||
dictEntry *de = dictGetRandomKey(server.migrate_cached_sockets);
|
dictEntry *de = dictGetRandomKey(server.migrate_cached_sockets);
|
||||||
cs = dictGetVal(de);
|
cs = (migrateCachedSocket*)dictGetVal(de);
|
||||||
close(cs->fd);
|
close(cs->fd);
|
||||||
zfree(cs);
|
zfree(cs);
|
||||||
dictDelete(server.migrate_cached_sockets,dictGetKey(de));
|
dictDelete(server.migrate_cached_sockets,dictGetKey(de));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the socket */
|
/* Create the socket */
|
||||||
fd = anetTcpNonBlockConnect(server.neterr,ptrFromObj(c->argv[1]),
|
fd = anetTcpNonBlockConnect(server.neterr,szFromObj(c->argv[1]),
|
||||||
atoi(ptrFromObj(c->argv[2])));
|
atoi(szFromObj(c->argv[2])));
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
sdsfree(name);
|
sdsfree(name);
|
||||||
addReplyErrorFormat(c,"Can't connect to target node: %s",
|
addReplyErrorFormat(c,"Can't connect to target node: %s",
|
||||||
@ -5030,7 +5030,7 @@ migrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long ti
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add to the cache and return it to the caller. */
|
/* Add to the cache and return it to the caller. */
|
||||||
cs = zmalloc(sizeof(*cs), MALLOC_LOCAL);
|
cs = (migrateCachedSocket*)zmalloc(sizeof(*cs), MALLOC_LOCAL);
|
||||||
cs->fd = fd;
|
cs->fd = fd;
|
||||||
cs->last_dbid = -1;
|
cs->last_dbid = -1;
|
||||||
cs->last_use_time = server.unixtime;
|
cs->last_use_time = server.unixtime;
|
||||||
@ -5043,10 +5043,10 @@ void migrateCloseSocket(robj *host, robj *port) {
|
|||||||
sds name = sdsempty();
|
sds name = sdsempty();
|
||||||
migrateCachedSocket *cs;
|
migrateCachedSocket *cs;
|
||||||
|
|
||||||
name = sdscatlen(name,ptrFromObj(host),sdslen(ptrFromObj(host)));
|
name = sdscatlen(name,ptrFromObj(host),sdslen(szFromObj(host)));
|
||||||
name = sdscatlen(name,":",1);
|
name = sdscatlen(name,":",1);
|
||||||
name = sdscatlen(name,ptrFromObj(port),sdslen(ptrFromObj(port)));
|
name = sdscatlen(name,ptrFromObj(port),sdslen(szFromObj(port)));
|
||||||
cs = dictFetchValue(server.migrate_cached_sockets,name);
|
cs = (migrateCachedSocket*)dictFetchValue(server.migrate_cached_sockets,name);
|
||||||
if (!cs) {
|
if (!cs) {
|
||||||
sdsfree(name);
|
sdsfree(name);
|
||||||
return;
|
return;
|
||||||
@ -5063,7 +5063,7 @@ void migrateCloseTimedoutSockets(void) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
migrateCachedSocket *cs = dictGetVal(de);
|
migrateCachedSocket *cs = (migrateCachedSocket*)dictGetVal(de);
|
||||||
|
|
||||||
if ((server.unixtime - cs->last_use_time) > MIGRATE_SOCKET_CACHE_TTL) {
|
if ((server.unixtime - cs->last_use_time) > MIGRATE_SOCKET_CACHE_TTL) {
|
||||||
close(cs->fd);
|
close(cs->fd);
|
||||||
@ -5101,19 +5101,19 @@ void migrateCommand(client *c) {
|
|||||||
/* Parse additional options */
|
/* Parse additional options */
|
||||||
for (j = 6; j < c->argc; j++) {
|
for (j = 6; j < c->argc; j++) {
|
||||||
int moreargs = j < c->argc-1;
|
int moreargs = j < c->argc-1;
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[j]),"copy")) {
|
if (!strcasecmp(szFromObj(c->argv[j]),"copy")) {
|
||||||
copy = 1;
|
copy = 1;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"replace")) {
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"replace")) {
|
||||||
replace = 1;
|
replace = 1;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"auth")) {
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"auth")) {
|
||||||
if (!moreargs) {
|
if (!moreargs) {
|
||||||
addReply(c,shared.syntaxerr);
|
addReply(c,shared.syntaxerr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
password = ptrFromObj(c->argv[j]);
|
password = szFromObj(c->argv[j]);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"keys")) {
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"keys")) {
|
||||||
if (sdslen(ptrFromObj(c->argv[3])) != 0) {
|
if (sdslen(szFromObj(c->argv[3])) != 0) {
|
||||||
addReplyError(c,
|
addReplyError(c,
|
||||||
"When using MIGRATE KEYS option, the key argument"
|
"When using MIGRATE KEYS option, the key argument"
|
||||||
" must be set to the empty string");
|
" must be set to the empty string");
|
||||||
@ -5141,8 +5141,8 @@ void migrateCommand(client *c) {
|
|||||||
* the caller there was nothing to migrate. We don't return an error in
|
* the caller there was nothing to migrate. We don't return an error in
|
||||||
* this case, since often this is due to a normal condition like the key
|
* this case, since often this is due to a normal condition like the key
|
||||||
* expiring in the meantime. */
|
* expiring in the meantime. */
|
||||||
ov = zrealloc(ov,sizeof(robj*)*num_keys, MALLOC_LOCAL);
|
ov = (robj**)zrealloc(ov,sizeof(robj*)*num_keys, MALLOC_LOCAL);
|
||||||
kv = zrealloc(kv,sizeof(robj*)*num_keys, MALLOC_LOCAL);
|
kv = (robj**)zrealloc(kv,sizeof(robj*)*num_keys, MALLOC_LOCAL);
|
||||||
int oi = 0;
|
int oi = 0;
|
||||||
|
|
||||||
for (j = 0; j < num_keys; j++) {
|
for (j = 0; j < num_keys; j++) {
|
||||||
@ -5218,8 +5218,8 @@ try_again:
|
|||||||
else
|
else
|
||||||
serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"RESTORE",7));
|
serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"RESTORE",7));
|
||||||
serverAssertWithInfo(c,NULL,sdsEncodedObject(kv[j]));
|
serverAssertWithInfo(c,NULL,sdsEncodedObject(kv[j]));
|
||||||
serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,ptrFromObj(kv[j]),
|
serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,szFromObj(kv[j]),
|
||||||
sdslen(ptrFromObj(kv[j]))));
|
sdslen(szFromObj(kv[j]))));
|
||||||
serverAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));
|
serverAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));
|
||||||
|
|
||||||
/* Emit the payload argument, that is the serialized object using
|
/* Emit the payload argument, that is the serialized object using
|
||||||
@ -5239,6 +5239,13 @@ try_again:
|
|||||||
/* Fix the actual number of keys we are migrating. */
|
/* Fix the actual number of keys we are migrating. */
|
||||||
num_keys = non_expired;
|
num_keys = non_expired;
|
||||||
|
|
||||||
|
char buf0[1024]; /* Auth reply. */
|
||||||
|
char buf1[1024]; /* Select reply. */
|
||||||
|
char buf2[1024]; /* Restore reply. */
|
||||||
|
int error_from_target = 0;
|
||||||
|
int socket_error = 0;
|
||||||
|
int del_idx = 1; /* Index of the key argument for the replicated DEL op. */
|
||||||
|
|
||||||
/* Transfer the query to the other node in 64K chunks. */
|
/* Transfer the query to the other node in 64K chunks. */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
{
|
{
|
||||||
@ -5257,9 +5264,6 @@ try_again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf0[1024]; /* Auth reply. */
|
|
||||||
char buf1[1024]; /* Select reply. */
|
|
||||||
char buf2[1024]; /* Restore reply. */
|
|
||||||
|
|
||||||
/* Read the AUTH reply if needed. */
|
/* Read the AUTH reply if needed. */
|
||||||
if (password && syncReadLine(cs->fd, buf0, sizeof(buf0), timeout) <= 0)
|
if (password && syncReadLine(cs->fd, buf0, sizeof(buf0), timeout) <= 0)
|
||||||
@ -5269,17 +5273,13 @@ try_again:
|
|||||||
if (select && syncReadLine(cs->fd, buf1, sizeof(buf1), timeout) <= 0)
|
if (select && syncReadLine(cs->fd, buf1, sizeof(buf1), timeout) <= 0)
|
||||||
goto socket_err;
|
goto socket_err;
|
||||||
|
|
||||||
/* Read the RESTORE replies. */
|
|
||||||
int error_from_target = 0;
|
|
||||||
int socket_error = 0;
|
|
||||||
int del_idx = 1; /* Index of the key argument for the replicated DEL op. */
|
|
||||||
|
|
||||||
/* Allocate the new argument vector that will replace the current command,
|
/* Allocate the new argument vector that will replace the current command,
|
||||||
* to propagate the MIGRATE as a DEL command (if no COPY option was given).
|
* to propagate the MIGRATE as a DEL command (if no COPY option was given).
|
||||||
* We allocate num_keys+1 because the additional argument is for "DEL"
|
* We allocate num_keys+1 because the additional argument is for "DEL"
|
||||||
* command name itself. */
|
* command name itself. */
|
||||||
if (!copy) newargv = zmalloc(sizeof(robj*)*(num_keys+1), MALLOC_LOCAL);
|
if (!copy) newargv = (robj**)zmalloc(sizeof(robj*)*(num_keys+1), MALLOC_LOCAL);
|
||||||
|
|
||||||
|
/* Read the RESTORE replies. */
|
||||||
for (j = 0; j < num_keys; j++) {
|
for (j = 0; j < num_keys; j++) {
|
||||||
if (syncReadLine(cs->fd, buf2, sizeof(buf2), timeout) <= 0) {
|
if (syncReadLine(cs->fd, buf2, sizeof(buf2), timeout) <= 0) {
|
||||||
socket_error = 1;
|
socket_error = 1;
|
||||||
@ -5531,7 +5531,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
|||||||
for (j = 0; j < numkeys; j++) {
|
for (j = 0; j < numkeys; j++) {
|
||||||
robj *thiskey = margv[keyindex[j]];
|
robj *thiskey = margv[keyindex[j]];
|
||||||
int thisslot = keyHashSlot((char*)ptrFromObj(thiskey),
|
int thisslot = keyHashSlot((char*)ptrFromObj(thiskey),
|
||||||
sdslen(ptrFromObj(thiskey)));
|
sdslen(szFromObj(thiskey)));
|
||||||
|
|
||||||
if (firstkey == NULL) {
|
if (firstkey == NULL) {
|
||||||
/* This is the first key we see. Check what is the slot
|
/* This is the first key we see. Check what is the slot
|
||||||
@ -5711,8 +5711,8 @@ int clusterRedirectBlockedClientIfNeeded(client *c) {
|
|||||||
/* All keys must belong to the same slot, so check first key only. */
|
/* All keys must belong to the same slot, so check first key only. */
|
||||||
di = dictGetIterator(c->bpop.keys);
|
di = dictGetIterator(c->bpop.keys);
|
||||||
if ((de = dictNext(di)) != NULL) {
|
if ((de = dictNext(di)) != NULL) {
|
||||||
robj *key = dictGetKey(de);
|
robj *key = (robj*)dictGetKey(de);
|
||||||
int slot = keyHashSlot((char*)ptrFromObj(key), sdslen(ptrFromObj(key)));
|
int slot = keyHashSlot((char*)ptrFromObj(key), sdslen(szFromObj(key)));
|
||||||
clusterNode *node = server.cluster->slots[slot];
|
clusterNode *node = server.cluster->slots[slot];
|
||||||
|
|
||||||
/* We send an error and unblock the client if:
|
/* We send an error and unblock the client if:
|
@ -143,7 +143,7 @@ int yesnotoi(char *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void appendServerSaveParams(time_t seconds, int changes) {
|
void appendServerSaveParams(time_t seconds, int changes) {
|
||||||
server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1), MALLOC_LOCAL);
|
server.saveparams = (saveparam*)zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1), MALLOC_LOCAL);
|
||||||
server.saveparams[server.saveparamslen].seconds = seconds;
|
server.saveparams[server.saveparamslen].seconds = seconds;
|
||||||
server.saveparams[server.saveparamslen].changes = changes;
|
server.saveparams[server.saveparamslen].changes = changes;
|
||||||
server.saveparamslen++;
|
server.saveparamslen++;
|
||||||
@ -159,8 +159,8 @@ void queueLoadModule(sds path, sds *argv, int argc) {
|
|||||||
int i;
|
int i;
|
||||||
struct moduleLoadQueueEntry *loadmod;
|
struct moduleLoadQueueEntry *loadmod;
|
||||||
|
|
||||||
loadmod = zmalloc(sizeof(struct moduleLoadQueueEntry), MALLOC_LOCAL);
|
loadmod = (moduleLoadQueueEntry*)zmalloc(sizeof(struct moduleLoadQueueEntry), MALLOC_LOCAL);
|
||||||
loadmod->argv = zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL);
|
loadmod->argv = (robj**)zmalloc(sizeof(robj*)*argc, MALLOC_LOCAL);
|
||||||
loadmod->path = sdsnew(path);
|
loadmod->path = sdsnew(path);
|
||||||
loadmod->argc = argc;
|
loadmod->argc = argc;
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
@ -170,7 +170,7 @@ void queueLoadModule(sds path, sds *argv, int argc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadServerConfigFromString(char *config) {
|
void loadServerConfigFromString(char *config) {
|
||||||
char *err = NULL;
|
const char *err = NULL;
|
||||||
int linenum = 0, totlines, i;
|
int linenum = 0, totlines, i;
|
||||||
int slaveof_linenum = 0;
|
int slaveof_linenum = 0;
|
||||||
sds *lines;
|
sds *lines;
|
||||||
@ -216,10 +216,6 @@ void loadServerConfigFromString(char *config) {
|
|||||||
if ((server.protected_mode = yesnotoi(argv[1])) == -1) {
|
if ((server.protected_mode = yesnotoi(argv[1])) == -1) {
|
||||||
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(argv[0],"gopher-enabled") && argc == 2) {
|
|
||||||
if ((server.gopher_enabled = yesnotoi(argv[1])) == -1) {
|
|
||||||
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
|
||||||
}
|
|
||||||
} else if (!strcasecmp(argv[0],"port") && argc == 2) {
|
} else if (!strcasecmp(argv[0],"port") && argc == 2) {
|
||||||
server.port = atoi(argv[1]);
|
server.port = atoi(argv[1]);
|
||||||
if (server.port < 0 || server.port > 65535) {
|
if (server.port < 0 || server.port > 65535) {
|
||||||
@ -729,11 +725,11 @@ void loadServerConfigFromString(char *config) {
|
|||||||
} else if (!strcasecmp(argv[0],"client-output-buffer-limit") &&
|
} else if (!strcasecmp(argv[0],"client-output-buffer-limit") &&
|
||||||
argc == 5)
|
argc == 5)
|
||||||
{
|
{
|
||||||
int class = getClientTypeByName(argv[1]);
|
int type = getClientTypeByName(argv[1]);
|
||||||
unsigned long long hard, soft;
|
unsigned long long hard, soft;
|
||||||
int soft_seconds;
|
int soft_seconds;
|
||||||
|
|
||||||
if (class == -1 || class == CLIENT_TYPE_MASTER) {
|
if (type == -1 || type == CLIENT_TYPE_MASTER) {
|
||||||
err = "Unrecognized client limit class: the user specified "
|
err = "Unrecognized client limit class: the user specified "
|
||||||
"an invalid one, or 'master' which has no buffer limits.";
|
"an invalid one, or 'master' which has no buffer limits.";
|
||||||
goto loaderr;
|
goto loaderr;
|
||||||
@ -745,9 +741,9 @@ void loadServerConfigFromString(char *config) {
|
|||||||
err = "Negative number of seconds in soft limit is invalid";
|
err = "Negative number of seconds in soft limit is invalid";
|
||||||
goto loaderr;
|
goto loaderr;
|
||||||
}
|
}
|
||||||
server.client_obuf_limits[class].hard_limit_bytes = hard;
|
server.client_obuf_limits[type].hard_limit_bytes = hard;
|
||||||
server.client_obuf_limits[class].soft_limit_bytes = soft;
|
server.client_obuf_limits[type].soft_limit_bytes = soft;
|
||||||
server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;
|
server.client_obuf_limits[type].soft_limit_seconds = soft_seconds;
|
||||||
} else if (!strcasecmp(argv[0],"stop-writes-on-bgsave-error") &&
|
} else if (!strcasecmp(argv[0],"stop-writes-on-bgsave-error") &&
|
||||||
argc == 2) {
|
argc == 2) {
|
||||||
if ((server.stop_writes_on_bgsave_err = yesnotoi(argv[1])) == -1) {
|
if ((server.stop_writes_on_bgsave_err = yesnotoi(argv[1])) == -1) {
|
||||||
@ -806,7 +802,7 @@ void loadServerConfigFromString(char *config) {
|
|||||||
int argc_err;
|
int argc_err;
|
||||||
if (ACLAppendUserForLoading(argv,argc,&argc_err) == C_ERR) {
|
if (ACLAppendUserForLoading(argv,argc,&argc_err) == C_ERR) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *errmsg = ACLSetUserStringError();
|
const char *errmsg = ACLSetUserStringError();
|
||||||
snprintf(buf,sizeof(buf),"Error in user declaration '%s': %s",
|
snprintf(buf,sizeof(buf),"Error in user declaration '%s': %s",
|
||||||
argv[argc_err],errmsg);
|
argv[argc_err],errmsg);
|
||||||
err = buf;
|
err = buf;
|
||||||
@ -928,36 +924,36 @@ void loadServerConfig(char *filename, char *options) {
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define config_set_bool_field(_name,_var) \
|
#define config_set_bool_field(_name,_var) \
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),_name)) { \
|
} else if (!strcasecmp(szFromObj(c->argv[2]),_name)) { \
|
||||||
int yn = yesnotoi(ptrFromObj(o)); \
|
int yn = yesnotoi(szFromObj(o)); \
|
||||||
if (yn == -1) goto badfmt; \
|
if (yn == -1) goto badfmt; \
|
||||||
_var = yn;
|
_var = yn;
|
||||||
|
|
||||||
#define config_set_numerical_field(_name,_var,min,max) \
|
#define config_set_numerical_field(_name,_var,min,max) \
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),_name)) { \
|
} else if (!strcasecmp(szFromObj(c->argv[2]),_name)) { \
|
||||||
if (getLongLongFromObject(o,&ll) == C_ERR) goto badfmt; \
|
if (getLongLongFromObject(o,&ll) == C_ERR) goto badfmt; \
|
||||||
if (min != LLONG_MIN && ll < min) goto badfmt; \
|
if (min != LLONG_MIN && ll < min) goto badfmt; \
|
||||||
if (max != LLONG_MAX && ll > max) goto badfmt; \
|
if (max != LLONG_MAX && ll > max) goto badfmt; \
|
||||||
_var = ll;
|
_var = ll;
|
||||||
|
|
||||||
#define config_set_memory_field(_name,_var) \
|
#define config_set_memory_field(_name,_var) \
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),_name)) { \
|
} else if (!strcasecmp(szFromObj(c->argv[2]),_name)) { \
|
||||||
ll = memtoll(ptrFromObj(o),&err); \
|
ll = memtoll(szFromObj(o),&err); \
|
||||||
if (err || ll < 0) goto badfmt; \
|
if (err || ll < 0) goto badfmt; \
|
||||||
_var = ll;
|
_var = ll;
|
||||||
|
|
||||||
#define config_set_enum_field(_name,_var,_enumvar) \
|
#define config_set_enum_field(_name,_var,_enumvar) \
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),_name)) { \
|
} else if (!strcasecmp(szFromObj(c->argv[2]),_name)) { \
|
||||||
int enumval = configEnumGetValue(_enumvar,ptrFromObj(o)); \
|
int enumval = configEnumGetValue(_enumvar,szFromObj(o)); \
|
||||||
if (enumval == INT_MIN) goto badfmt; \
|
if (enumval == INT_MIN) goto badfmt; \
|
||||||
_var = enumval;
|
_var = enumval;
|
||||||
|
|
||||||
#define config_set_special_field(_name) \
|
#define config_set_special_field(_name) \
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),_name)) {
|
} else if (!strcasecmp(szFromObj(c->argv[2]),_name)) {
|
||||||
|
|
||||||
#define config_set_special_field_with_alias(_name1,_name2) \
|
#define config_set_special_field_with_alias(_name1,_name2) \
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[2]),_name1) || \
|
} else if (!strcasecmp(szFromObj(c->argv[2]),_name1) || \
|
||||||
!strcasecmp(ptrFromObj(c->argv[2]),_name2)) {
|
!strcasecmp(szFromObj(c->argv[2]),_name2)) {
|
||||||
|
|
||||||
#define config_set_else } else
|
#define config_set_else } else
|
||||||
|
|
||||||
@ -973,14 +969,14 @@ void configSetCommand(client *c) {
|
|||||||
|
|
||||||
/* Special fields that can't be handled with general macros. */
|
/* Special fields that can't be handled with general macros. */
|
||||||
config_set_special_field("dbfilename") {
|
config_set_special_field("dbfilename") {
|
||||||
if (!pathIsBaseName(ptrFromObj(o))) {
|
if (!pathIsBaseName(szFromObj(o))) {
|
||||||
addReplyError(c, "dbfilename can't be a path, just a filename");
|
addReplyError(c, "dbfilename can't be a path, just a filename");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zfree(server.rdb_filename);
|
zfree(server.rdb_filename);
|
||||||
server.rdb_filename = zstrdup(ptrFromObj(o));
|
server.rdb_filename = zstrdup(szFromObj(o));
|
||||||
} config_set_special_field("requirepass") {
|
} config_set_special_field("requirepass") {
|
||||||
if (sdslen(ptrFromObj(o)) > CONFIG_AUTHPASS_MAX_LEN) goto badfmt;
|
if (sdslen(szFromObj(o)) > CONFIG_AUTHPASS_MAX_LEN) goto badfmt;
|
||||||
/* The old "requirepass" directive just translates to setting
|
/* The old "requirepass" directive just translates to setting
|
||||||
* a password to the default user. */
|
* a password to the default user. */
|
||||||
ACLSetUser(DefaultUser,"resetpass",-1);
|
ACLSetUser(DefaultUser,"resetpass",-1);
|
||||||
@ -989,13 +985,13 @@ void configSetCommand(client *c) {
|
|||||||
sdsfree(aclop);
|
sdsfree(aclop);
|
||||||
} config_set_special_field("masteruser") {
|
} config_set_special_field("masteruser") {
|
||||||
zfree(server.default_masteruser);
|
zfree(server.default_masteruser);
|
||||||
server.default_masteruser = ((char*)ptrFromObj(o))[0] ? zstrdup(ptrFromObj(o)) : NULL;
|
server.default_masteruser = ((char*)ptrFromObj(o))[0] ? zstrdup(szFromObj(o)) : NULL;
|
||||||
} config_set_special_field("masterauth") {
|
} config_set_special_field("masterauth") {
|
||||||
zfree(server.default_masterauth);
|
zfree(server.default_masterauth);
|
||||||
server.default_masterauth = ((char*)ptrFromObj(o))[0] ? zstrdup(ptrFromObj(o)) : NULL;
|
server.default_masterauth = ((char*)ptrFromObj(o))[0] ? zstrdup(szFromObj(o)) : NULL;
|
||||||
} config_set_special_field("cluster-announce-ip") {
|
} config_set_special_field("cluster-announce-ip") {
|
||||||
zfree(server.cluster_announce_ip);
|
zfree(server.cluster_announce_ip);
|
||||||
server.cluster_announce_ip = ((char*)ptrFromObj(o))[0] ? zstrdup(ptrFromObj(o)) : NULL;
|
server.cluster_announce_ip = ((char*)ptrFromObj(o))[0] ? zstrdup(szFromObj(o)) : NULL;
|
||||||
} config_set_special_field("maxclients") {
|
} config_set_special_field("maxclients") {
|
||||||
int orig_value = server.maxclients;
|
int orig_value = server.maxclients;
|
||||||
|
|
||||||
@ -1027,7 +1023,7 @@ void configSetCommand(client *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} config_set_special_field("appendonly") {
|
} config_set_special_field("appendonly") {
|
||||||
int enable = yesnotoi(ptrFromObj(o));
|
int enable = yesnotoi(szFromObj(o));
|
||||||
|
|
||||||
if (enable == -1) goto badfmt;
|
if (enable == -1) goto badfmt;
|
||||||
if (enable == 0 && server.aof_state != AOF_OFF) {
|
if (enable == 0 && server.aof_state != AOF_OFF) {
|
||||||
@ -1041,7 +1037,7 @@ void configSetCommand(client *c) {
|
|||||||
}
|
}
|
||||||
} config_set_special_field("save") {
|
} config_set_special_field("save") {
|
||||||
int vlen, j;
|
int vlen, j;
|
||||||
sds *v = sdssplitlen(ptrFromObj(o),sdslen(ptrFromObj(o))," ",1,&vlen);
|
sds *v = sdssplitlen(szFromObj(o),sdslen(szFromObj(o))," ",1,&vlen);
|
||||||
|
|
||||||
/* Perform sanity check before setting the new config:
|
/* Perform sanity check before setting the new config:
|
||||||
* - Even number of args
|
* - Even number of args
|
||||||
@ -1080,7 +1076,7 @@ void configSetCommand(client *c) {
|
|||||||
}
|
}
|
||||||
} config_set_special_field("client-output-buffer-limit") {
|
} config_set_special_field("client-output-buffer-limit") {
|
||||||
int vlen, j;
|
int vlen, j;
|
||||||
sds *v = sdssplitlen(ptrFromObj(o),sdslen(ptrFromObj(o))," ",1,&vlen);
|
sds *v = sdssplitlen(szFromObj(o),sdslen(szFromObj(o))," ",1,&vlen);
|
||||||
|
|
||||||
/* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */
|
/* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */
|
||||||
if (vlen % 4) {
|
if (vlen % 4) {
|
||||||
@ -1095,8 +1091,8 @@ void configSetCommand(client *c) {
|
|||||||
long val;
|
long val;
|
||||||
|
|
||||||
if ((j % 4) == 0) {
|
if ((j % 4) == 0) {
|
||||||
int class = getClientTypeByName(v[j]);
|
int type = getClientTypeByName(v[j]);
|
||||||
if (class == -1 || class == CLIENT_TYPE_MASTER) {
|
if (type == -1 || type == CLIENT_TYPE_MASTER) {
|
||||||
sdsfreesplitres(v,vlen);
|
sdsfreesplitres(v,vlen);
|
||||||
goto badfmt;
|
goto badfmt;
|
||||||
}
|
}
|
||||||
@ -1110,22 +1106,21 @@ void configSetCommand(client *c) {
|
|||||||
}
|
}
|
||||||
/* Finally set the new config */
|
/* Finally set the new config */
|
||||||
for (j = 0; j < vlen; j += 4) {
|
for (j = 0; j < vlen; j += 4) {
|
||||||
int class;
|
|
||||||
unsigned long long hard, soft;
|
unsigned long long hard, soft;
|
||||||
int soft_seconds;
|
int soft_seconds;
|
||||||
|
|
||||||
class = getClientTypeByName(v[j]);
|
int type = getClientTypeByName(v[j]);
|
||||||
hard = memtoll(v[j+1],NULL);
|
hard = memtoll(v[j+1],NULL);
|
||||||
soft = memtoll(v[j+2],NULL);
|
soft = memtoll(v[j+2],NULL);
|
||||||
soft_seconds = strtoll(v[j+3],NULL,10);
|
soft_seconds = strtoll(v[j+3],NULL,10);
|
||||||
|
|
||||||
server.client_obuf_limits[class].hard_limit_bytes = hard;
|
server.client_obuf_limits[type].hard_limit_bytes = hard;
|
||||||
server.client_obuf_limits[class].soft_limit_bytes = soft;
|
server.client_obuf_limits[type].soft_limit_bytes = soft;
|
||||||
server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;
|
server.client_obuf_limits[type].soft_limit_seconds = soft_seconds;
|
||||||
}
|
}
|
||||||
sdsfreesplitres(v,vlen);
|
sdsfreesplitres(v,vlen);
|
||||||
} config_set_special_field("notify-keyspace-events") {
|
} config_set_special_field("notify-keyspace-events") {
|
||||||
int flags = keyspaceEventsStringToFlags(ptrFromObj(o));
|
int flags = keyspaceEventsStringToFlags(szFromObj(o));
|
||||||
|
|
||||||
if (flags == -1) goto badfmt;
|
if (flags == -1) goto badfmt;
|
||||||
server.notify_keyspace_events = flags;
|
server.notify_keyspace_events = flags;
|
||||||
@ -1133,7 +1128,7 @@ void configSetCommand(client *c) {
|
|||||||
"replica-announce-ip")
|
"replica-announce-ip")
|
||||||
{
|
{
|
||||||
zfree(server.slave_announce_ip);
|
zfree(server.slave_announce_ip);
|
||||||
server.slave_announce_ip = ((char*)ptrFromObj(o))[0] ? zstrdup(ptrFromObj(o)) : NULL;
|
server.slave_announce_ip = ((char*)ptrFromObj(o))[0] ? zstrdup(szFromObj(o)) : NULL;
|
||||||
|
|
||||||
/* Boolean fields.
|
/* Boolean fields.
|
||||||
* config_set_bool_field(name,var). */
|
* config_set_bool_field(name,var). */
|
||||||
@ -1186,8 +1181,6 @@ void configSetCommand(client *c) {
|
|||||||
#endif
|
#endif
|
||||||
} config_set_bool_field(
|
} config_set_bool_field(
|
||||||
"protected-mode",server.protected_mode) {
|
"protected-mode",server.protected_mode) {
|
||||||
} config_set_bool_field(
|
|
||||||
"gopher-enabled",server.gopher_enabled) {
|
|
||||||
} config_set_bool_field(
|
} config_set_bool_field(
|
||||||
"stop-writes-on-bgsave-error",server.stop_writes_on_bgsave_err) {
|
"stop-writes-on-bgsave-error",server.stop_writes_on_bgsave_err) {
|
||||||
} config_set_bool_field(
|
} config_set_bool_field(
|
||||||
@ -1402,7 +1395,7 @@ badfmt: /* Bad format errors */
|
|||||||
void configGetCommand(client *c) {
|
void configGetCommand(client *c) {
|
||||||
robj *o = c->argv[2];
|
robj *o = c->argv[2];
|
||||||
void *replylen = addReplyDeferredLen(c);
|
void *replylen = addReplyDeferredLen(c);
|
||||||
char *pattern = ptrFromObj(o);
|
char *pattern = szFromObj(o);
|
||||||
char buf[128];
|
char buf[128];
|
||||||
int matches = 0;
|
int matches = 0;
|
||||||
serverAssertWithInfo(c,o,sdsEncodedObject(o));
|
serverAssertWithInfo(c,o,sdsEncodedObject(o));
|
||||||
@ -1521,7 +1514,6 @@ void configGetCommand(client *c) {
|
|||||||
config_get_bool_field("activerehashing", server.activerehashing);
|
config_get_bool_field("activerehashing", server.activerehashing);
|
||||||
config_get_bool_field("activedefrag", server.active_defrag_enabled);
|
config_get_bool_field("activedefrag", server.active_defrag_enabled);
|
||||||
config_get_bool_field("protected-mode", server.protected_mode);
|
config_get_bool_field("protected-mode", server.protected_mode);
|
||||||
config_get_bool_field("gopher-enabled", server.gopher_enabled);
|
|
||||||
config_get_bool_field("repl-disable-tcp-nodelay",
|
config_get_bool_field("repl-disable-tcp-nodelay",
|
||||||
server.repl_disable_tcp_nodelay);
|
server.repl_disable_tcp_nodelay);
|
||||||
config_get_bool_field("repl-diskless-sync",
|
config_get_bool_field("repl-diskless-sync",
|
||||||
@ -1620,7 +1612,7 @@ void configGetCommand(client *c) {
|
|||||||
if (stringmatch(pattern,"slaveof",1) ||
|
if (stringmatch(pattern,"slaveof",1) ||
|
||||||
stringmatch(pattern,"replicaof",1))
|
stringmatch(pattern,"replicaof",1))
|
||||||
{
|
{
|
||||||
char *optname = stringmatch(pattern,"slaveof",1) ?
|
const char *optname = stringmatch(pattern,"slaveof",1) ?
|
||||||
"slaveof" : "replicaof";
|
"slaveof" : "replicaof";
|
||||||
char buf[256];
|
char buf[256];
|
||||||
addReplyBulkCString(c,optname);
|
addReplyBulkCString(c,optname);
|
||||||
@ -1722,13 +1714,13 @@ struct rewriteConfigState {
|
|||||||
|
|
||||||
/* Append the new line to the current configuration state. */
|
/* Append the new line to the current configuration state. */
|
||||||
void rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) {
|
void rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) {
|
||||||
state->lines = zrealloc(state->lines, sizeof(char*) * (state->numlines+1), MALLOC_LOCAL);
|
state->lines = (sds*)zrealloc(state->lines, sizeof(char*) * (state->numlines+1), MALLOC_LOCAL);
|
||||||
state->lines[state->numlines++] = line;
|
state->lines[state->numlines++] = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Populate the option -> list of line numbers map. */
|
/* Populate the option -> list of line numbers map. */
|
||||||
void rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) {
|
void rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) {
|
||||||
list *l = dictFetchValue(state->option_to_line,option);
|
list *l = (list*)dictFetchValue(state->option_to_line,option);
|
||||||
|
|
||||||
if (l == NULL) {
|
if (l == NULL) {
|
||||||
l = listCreate();
|
l = listCreate();
|
||||||
@ -1754,7 +1746,7 @@ void rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char *
|
|||||||
* If the old file does not exist at all, an empty state is returned. */
|
* If the old file does not exist at all, an empty state is returned. */
|
||||||
struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
|
struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
|
||||||
FILE *fp = fopen(path,"r");
|
FILE *fp = fopen(path,"r");
|
||||||
struct rewriteConfigState *state = zmalloc(sizeof(*state), MALLOC_LOCAL);
|
struct rewriteConfigState *state = (rewriteConfigState*)zmalloc(sizeof(*state), MALLOC_LOCAL);
|
||||||
char buf[CONFIG_MAX_LINE+1];
|
char buf[CONFIG_MAX_LINE+1];
|
||||||
int linenum = -1;
|
int linenum = -1;
|
||||||
|
|
||||||
@ -1839,7 +1831,7 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
|
|||||||
* in any way. */
|
* in any way. */
|
||||||
void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {
|
void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {
|
||||||
sds o = sdsnew(option);
|
sds o = sdsnew(option);
|
||||||
list *l = dictFetchValue(state->option_to_line,o);
|
list *l = (list*)dictFetchValue(state->option_to_line,o);
|
||||||
|
|
||||||
rewriteConfigMarkAsProcessed(state,option);
|
rewriteConfigMarkAsProcessed(state,option);
|
||||||
|
|
||||||
@ -1891,7 +1883,7 @@ int rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite a simple "option-name <bytes>" configuration option. */
|
/* Rewrite a simple "option-name <bytes>" configuration option. */
|
||||||
void rewriteConfigBytesOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {
|
void rewriteConfigBytesOption(struct rewriteConfigState *state, const char *option, long long value, long long defvalue) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
int force = value != defvalue;
|
int force = value != defvalue;
|
||||||
sds line;
|
sds line;
|
||||||
@ -1902,7 +1894,7 @@ void rewriteConfigBytesOption(struct rewriteConfigState *state, char *option, lo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite a yes/no option. */
|
/* Rewrite a yes/no option. */
|
||||||
void rewriteConfigYesNoOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {
|
void rewriteConfigYesNoOption(struct rewriteConfigState *state, const char *option, int value, int defvalue) {
|
||||||
int force = value != defvalue;
|
int force = value != defvalue;
|
||||||
sds line = sdscatprintf(sdsempty(),"%s %s",option,
|
sds line = sdscatprintf(sdsempty(),"%s %s",option,
|
||||||
value ? "yes" : "no");
|
value ? "yes" : "no");
|
||||||
@ -1911,7 +1903,7 @@ void rewriteConfigYesNoOption(struct rewriteConfigState *state, char *option, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite a string option. */
|
/* Rewrite a string option. */
|
||||||
void rewriteConfigStringOption(struct rewriteConfigState *state, char *option, char *value, char *defvalue) {
|
void rewriteConfigStringOption(struct rewriteConfigState *state, const char *option, const char *value, const char *defvalue) {
|
||||||
int force = 1;
|
int force = 1;
|
||||||
sds line;
|
sds line;
|
||||||
|
|
||||||
@ -1933,7 +1925,7 @@ void rewriteConfigStringOption(struct rewriteConfigState *state, char *option, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite a numerical (long long range) option. */
|
/* Rewrite a numerical (long long range) option. */
|
||||||
void rewriteConfigNumericalOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {
|
void rewriteConfigNumericalOption(struct rewriteConfigState *state, const char *option, long long value, long long defvalue) {
|
||||||
int force = value != defvalue;
|
int force = value != defvalue;
|
||||||
sds line = sdscatprintf(sdsempty(),"%s %lld",option,value);
|
sds line = sdscatprintf(sdsempty(),"%s %lld",option,value);
|
||||||
|
|
||||||
@ -1941,7 +1933,7 @@ void rewriteConfigNumericalOption(struct rewriteConfigState *state, char *option
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite a octal option. */
|
/* Rewrite a octal option. */
|
||||||
void rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {
|
void rewriteConfigOctalOption(struct rewriteConfigState *state, const char *option, int value, int defvalue) {
|
||||||
int force = value != defvalue;
|
int force = value != defvalue;
|
||||||
sds line = sdscatprintf(sdsempty(),"%s %o",option,value);
|
sds line = sdscatprintf(sdsempty(),"%s %o",option,value);
|
||||||
|
|
||||||
@ -1951,7 +1943,7 @@ void rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, in
|
|||||||
/* Rewrite an enumeration option. It takes as usually state and option name,
|
/* Rewrite an enumeration option. It takes as usually state and option name,
|
||||||
* and in addition the enumeration array and the default value for the
|
* and in addition the enumeration array and the default value for the
|
||||||
* option. */
|
* option. */
|
||||||
void rewriteConfigEnumOption(struct rewriteConfigState *state, char *option, int value, configEnum *ce, int defval) {
|
void rewriteConfigEnumOption(struct rewriteConfigState *state, const char *option, int value, configEnum *ce, int defval) {
|
||||||
sds line;
|
sds line;
|
||||||
const char *name = configEnumGetNameOrUnknown(ce,value);
|
const char *name = configEnumGetNameOrUnknown(ce,value);
|
||||||
int force = value != defval;
|
int force = value != defval;
|
||||||
@ -2006,7 +1998,7 @@ void rewriteConfigUserOption(struct rewriteConfigState *state) {
|
|||||||
raxStart(&ri,Users);
|
raxStart(&ri,Users);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
user *u = ri.data;
|
user *u = (user*)ri.data;
|
||||||
sds line = sdsnew("user ");
|
sds line = sdsnew("user ");
|
||||||
line = sdscatsds(line,u->name);
|
line = sdscatsds(line,u->name);
|
||||||
line = sdscatlen(line," ",1);
|
line = sdscatlen(line," ",1);
|
||||||
@ -2033,7 +2025,7 @@ void rewriteConfigDirOption(struct rewriteConfigState *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite the slaveof option. */
|
/* Rewrite the slaveof option. */
|
||||||
void rewriteConfigSlaveofOption(struct rewriteConfigState *state, char *option) {
|
void rewriteConfigSlaveofOption(struct rewriteConfigState *state, const char *option) {
|
||||||
/* If this is a master, we want all the slaveof config options
|
/* If this is a master, we want all the slaveof config options
|
||||||
* in the file to be removed. Note that if this is a cluster instance
|
* in the file to be removed. Note that if this is a cluster instance
|
||||||
* we don't want a slaveof directive inside redis.conf. */
|
* we don't want a slaveof directive inside redis.conf. */
|
||||||
@ -2059,7 +2051,7 @@ void rewriteConfigSlaveofOption(struct rewriteConfigState *state, char *option)
|
|||||||
/* Rewrite the notify-keyspace-events option. */
|
/* Rewrite the notify-keyspace-events option. */
|
||||||
void rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {
|
void rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {
|
||||||
int force = server.notify_keyspace_events != 0;
|
int force = server.notify_keyspace_events != 0;
|
||||||
char *option = "notify-keyspace-events";
|
const char *option = "notify-keyspace-events";
|
||||||
sds line, flags;
|
sds line, flags;
|
||||||
|
|
||||||
flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);
|
flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);
|
||||||
@ -2073,7 +2065,7 @@ void rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {
|
|||||||
/* Rewrite the client-output-buffer-limit option. */
|
/* Rewrite the client-output-buffer-limit option. */
|
||||||
void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) {
|
void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) {
|
||||||
int j;
|
int j;
|
||||||
char *option = "client-output-buffer-limit";
|
const char *option = "client-output-buffer-limit";
|
||||||
|
|
||||||
for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++) {
|
for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++) {
|
||||||
int force = (server.client_obuf_limits[j].hard_limit_bytes !=
|
int force = (server.client_obuf_limits[j].hard_limit_bytes !=
|
||||||
@ -2090,10 +2082,10 @@ void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state
|
|||||||
rewriteConfigFormatMemory(soft,sizeof(soft),
|
rewriteConfigFormatMemory(soft,sizeof(soft),
|
||||||
server.client_obuf_limits[j].soft_limit_bytes);
|
server.client_obuf_limits[j].soft_limit_bytes);
|
||||||
|
|
||||||
const char *typename = getClientTypeName(j);
|
const char *tname = getClientTypeName(j);
|
||||||
if (!strcmp(typename,"slave")) typename = "replica";
|
if (!strcmp(tname,"slave")) tname = "replica";
|
||||||
line = sdscatprintf(sdsempty(),"%s %s %s %s %ld",
|
line = sdscatprintf(sdsempty(),"%s %s %s %s %ld",
|
||||||
option, typename, hard, soft,
|
option, tname, hard, soft,
|
||||||
(long) server.client_obuf_limits[j].soft_limit_seconds);
|
(long) server.client_obuf_limits[j].soft_limit_seconds);
|
||||||
rewriteConfigRewriteLine(state,option,line,force);
|
rewriteConfigRewriteLine(state,option,line,force);
|
||||||
}
|
}
|
||||||
@ -2103,7 +2095,7 @@ void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state
|
|||||||
void rewriteConfigBindOption(struct rewriteConfigState *state) {
|
void rewriteConfigBindOption(struct rewriteConfigState *state) {
|
||||||
int force = 1;
|
int force = 1;
|
||||||
sds line, addresses;
|
sds line, addresses;
|
||||||
char *option = "bind";
|
const char *option = "bind";
|
||||||
|
|
||||||
/* Nothing to rewrite if we don't have bind addresses. */
|
/* Nothing to rewrite if we don't have bind addresses. */
|
||||||
if (server.bindaddr_count == 0) {
|
if (server.bindaddr_count == 0) {
|
||||||
@ -2122,7 +2114,7 @@ void rewriteConfigBindOption(struct rewriteConfigState *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite the requirepass option. */
|
/* Rewrite the requirepass option. */
|
||||||
void rewriteConfigRequirepassOption(struct rewriteConfigState *state, char *option) {
|
void rewriteConfigRequirepassOption(struct rewriteConfigState *state, const char *option) {
|
||||||
int force = 1;
|
int force = 1;
|
||||||
sds line;
|
sds line;
|
||||||
sds password = ACLDefaultUserFirstPassword();
|
sds password = ACLDefaultUserFirstPassword();
|
||||||
@ -2182,8 +2174,8 @@ void rewriteConfigRemoveOrphaned(struct rewriteConfigState *state) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
list *l = dictGetVal(de);
|
list *l = (list*)dictGetVal(de);
|
||||||
sds option = dictGetKey(de);
|
sds option = (sds)dictGetKey(de);
|
||||||
|
|
||||||
/* Don't blank lines about options the rewrite process
|
/* Don't blank lines about options the rewrite process
|
||||||
* don't understand. */
|
* don't understand. */
|
||||||
@ -2370,7 +2362,6 @@ int rewriteConfig(char *path) {
|
|||||||
rewriteConfigYesNoOption(state,"activerehashing",server.activerehashing,CONFIG_DEFAULT_ACTIVE_REHASHING);
|
rewriteConfigYesNoOption(state,"activerehashing",server.activerehashing,CONFIG_DEFAULT_ACTIVE_REHASHING);
|
||||||
rewriteConfigYesNoOption(state,"activedefrag",server.active_defrag_enabled,CONFIG_DEFAULT_ACTIVE_DEFRAG);
|
rewriteConfigYesNoOption(state,"activedefrag",server.active_defrag_enabled,CONFIG_DEFAULT_ACTIVE_DEFRAG);
|
||||||
rewriteConfigYesNoOption(state,"protected-mode",server.protected_mode,CONFIG_DEFAULT_PROTECTED_MODE);
|
rewriteConfigYesNoOption(state,"protected-mode",server.protected_mode,CONFIG_DEFAULT_PROTECTED_MODE);
|
||||||
rewriteConfigYesNoOption(state,"gopher-enabled",server.gopher_enabled,CONFIG_DEFAULT_GOPHER_ENABLED);
|
|
||||||
rewriteConfigClientoutputbufferlimitOption(state);
|
rewriteConfigClientoutputbufferlimitOption(state);
|
||||||
rewriteConfigNumericalOption(state,"hz",server.config_hz,CONFIG_DEFAULT_HZ);
|
rewriteConfigNumericalOption(state,"hz",server.config_hz,CONFIG_DEFAULT_HZ);
|
||||||
rewriteConfigYesNoOption(state,"aof-rewrite-incremental-fsync",server.aof_rewrite_incremental_fsync,CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC);
|
rewriteConfigYesNoOption(state,"aof-rewrite-incremental-fsync",server.aof_rewrite_incremental_fsync,CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC);
|
||||||
@ -2410,12 +2401,12 @@ int rewriteConfig(char *path) {
|
|||||||
|
|
||||||
void configCommand(client *c) {
|
void configCommand(client *c) {
|
||||||
/* Only allow CONFIG GET while loading. */
|
/* Only allow CONFIG GET while loading. */
|
||||||
if (server.loading && strcasecmp(ptrFromObj(c->argv[1]),"get")) {
|
if (server.loading && strcasecmp(szFromObj(c->argv[1]),"get")) {
|
||||||
addReplyError(c,"Only CONFIG GET is allowed during loading");
|
addReplyError(c,"Only CONFIG GET is allowed during loading");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"help")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"GET <pattern> -- Return parameters matching the glob-like <pattern> and their values.",
|
"GET <pattern> -- Return parameters matching the glob-like <pattern> and their values.",
|
||||||
"SET <parameter> <value> -- Set parameter to value.",
|
"SET <parameter> <value> -- Set parameter to value.",
|
||||||
@ -2424,15 +2415,15 @@ void configCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"set") && c->argc == 4) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"set") && c->argc == 4) {
|
||||||
configSetCommand(c);
|
configSetCommand(c);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"get") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"get") && c->argc == 3) {
|
||||||
configGetCommand(c);
|
configGetCommand(c);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"resetstat") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"resetstat") && c->argc == 2) {
|
||||||
resetServerStats();
|
resetServerStats();
|
||||||
resetCommandTableStats();
|
resetCommandTableStats();
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"rewrite") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"rewrite") && c->argc == 2) {
|
||||||
if (server.configfile == NULL) {
|
if (server.configfile == NULL) {
|
||||||
addReplyError(c,"The server is running without a config file");
|
addReplyError(c,"The server is running without a config file");
|
||||||
return;
|
return;
|
@ -1,5 +1,3 @@
|
|||||||
#include "server.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2010 Georges Menie (www.menie.org)
|
* Copyright 2001-2010 Georges Menie (www.menie.org)
|
||||||
* Copyright 2010-2012 Salvatore Sanfilippo (adapted to Redis coding style)
|
* Copyright 2010-2012 Salvatore Sanfilippo (adapted to Redis coding style)
|
||||||
@ -29,6 +27,8 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
/* CRC16 implementation according to CCITT standards.
|
/* CRC16 implementation according to CCITT standards.
|
||||||
*
|
*
|
||||||
* Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the
|
* Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the
|
||||||
|
@ -61,9 +61,10 @@ typedef ucontext_t sigcontext_t;
|
|||||||
* "add" digests relative to unordered elements.
|
* "add" digests relative to unordered elements.
|
||||||
*
|
*
|
||||||
* So digest(a,b,c,d) will be the same of digest(b,a,c,d) */
|
* So digest(a,b,c,d) will be the same of digest(b,a,c,d) */
|
||||||
void xorDigest(unsigned char *digest, void *ptr, size_t len) {
|
extern "C" void xorDigest(unsigned char *digest, const void *ptr, size_t len) {
|
||||||
SHA1_CTX ctx;
|
SHA1_CTX ctx;
|
||||||
unsigned char hash[20], *s = ptr;
|
unsigned char hash[20];
|
||||||
|
const unsigned char *s = (const unsigned char*)ptr;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
SHA1Init(&ctx);
|
SHA1Init(&ctx);
|
||||||
@ -76,7 +77,7 @@ void xorDigest(unsigned char *digest, void *ptr, size_t len) {
|
|||||||
|
|
||||||
void xorStringObjectDigest(unsigned char *digest, robj *o) {
|
void xorStringObjectDigest(unsigned char *digest, robj *o) {
|
||||||
o = getDecodedObject(o);
|
o = getDecodedObject(o);
|
||||||
xorDigest(digest,ptrFromObj(o),sdslen(ptrFromObj(o)));
|
xorDigest(digest,(const unsigned char*)ptrFromObj(o),sdslen(szFromObj(o)));
|
||||||
decrRefCount(o);
|
decrRefCount(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ void xorStringObjectDigest(unsigned char *digest, robj *o) {
|
|||||||
*/
|
*/
|
||||||
void mixDigest(unsigned char *digest, void *ptr, size_t len) {
|
void mixDigest(unsigned char *digest, void *ptr, size_t len) {
|
||||||
SHA1_CTX ctx;
|
SHA1_CTX ctx;
|
||||||
char *s = ptr;
|
char *s = (char*)ptr;
|
||||||
|
|
||||||
xorDigest(digest,s,len);
|
xorDigest(digest,s,len);
|
||||||
SHA1Init(&ctx);
|
SHA1Init(&ctx);
|
||||||
@ -106,7 +107,7 @@ void mixDigest(unsigned char *digest, void *ptr, size_t len) {
|
|||||||
|
|
||||||
void mixStringObjectDigest(unsigned char *digest, robj *o) {
|
void mixStringObjectDigest(unsigned char *digest, robj *o) {
|
||||||
o = getDecodedObject(o);
|
o = getDecodedObject(o);
|
||||||
mixDigest(digest,ptrFromObj(o),sdslen(ptrFromObj(o)));
|
mixDigest(digest,ptrFromObj(o),sdslen(szFromObj(o)));
|
||||||
decrRefCount(o);
|
decrRefCount(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o)
|
|||||||
unsigned char eledigest[20];
|
unsigned char eledigest[20];
|
||||||
|
|
||||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
unsigned char *zl = ptrFromObj(o);
|
unsigned char *zl = (unsigned char*)ptrFromObj(o);
|
||||||
unsigned char *eptr, *sptr;
|
unsigned char *eptr, *sptr;
|
||||||
unsigned char *vstr;
|
unsigned char *vstr;
|
||||||
unsigned int vlen;
|
unsigned int vlen;
|
||||||
@ -178,13 +179,13 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o)
|
|||||||
zzlNext(zl,&eptr,&sptr);
|
zzlNext(zl,&eptr,&sptr);
|
||||||
}
|
}
|
||||||
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||||
zset *zs = ptrFromObj(o);
|
zset *zs = (zset*)ptrFromObj(o);
|
||||||
dictIterator *di = dictGetIterator(zs->pdict);
|
dictIterator *di = dictGetIterator(zs->pdict);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds sdsele = dictGetKey(de);
|
sds sdsele = (sds)dictGetKey(de);
|
||||||
double *score = dictGetVal(de);
|
double *score = (double*)dictGetVal(de);
|
||||||
|
|
||||||
snprintf(buf,sizeof(buf),"%.17g",*score);
|
snprintf(buf,sizeof(buf),"%.17g",*score);
|
||||||
memset(eledigest,0,20);
|
memset(eledigest,0,20);
|
||||||
@ -214,7 +215,7 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o)
|
|||||||
hashTypeReleaseIterator(hi);
|
hashTypeReleaseIterator(hi);
|
||||||
} else if (o->type == OBJ_STREAM) {
|
} else if (o->type == OBJ_STREAM) {
|
||||||
streamIterator si;
|
streamIterator si;
|
||||||
streamIteratorStart(&si,ptrFromObj(o),NULL,NULL,0);
|
streamIteratorStart(&si,(stream*)ptrFromObj(o),NULL,NULL,0);
|
||||||
streamID id;
|
streamID id;
|
||||||
int64_t numfields;
|
int64_t numfields;
|
||||||
|
|
||||||
@ -235,7 +236,7 @@ void xorObjectDigest(redisDb *db, robj *keyobj, unsigned char *digest, robj *o)
|
|||||||
streamIteratorStop(&si);
|
streamIteratorStop(&si);
|
||||||
} else if (o->type == OBJ_MODULE) {
|
} else if (o->type == OBJ_MODULE) {
|
||||||
RedisModuleDigest md;
|
RedisModuleDigest md;
|
||||||
moduleValue *mv = ptrFromObj(o);
|
moduleValue *mv = (moduleValue*)ptrFromObj(o);
|
||||||
moduleType *mt = mv->type;
|
moduleType *mt = mv->type;
|
||||||
moduleInitDigestContext(md);
|
moduleInitDigestContext(md);
|
||||||
if (mt->digest) {
|
if (mt->digest) {
|
||||||
@ -281,12 +282,12 @@ void computeDatasetDigest(unsigned char *final) {
|
|||||||
robj *keyobj, *o;
|
robj *keyobj, *o;
|
||||||
|
|
||||||
memset(digest,0,20); /* This key-val digest */
|
memset(digest,0,20); /* This key-val digest */
|
||||||
key = dictGetKey(de);
|
key = (sds)dictGetKey(de);
|
||||||
keyobj = createStringObject(key,sdslen(key));
|
keyobj = createStringObject(key,sdslen(key));
|
||||||
|
|
||||||
mixDigest(digest,key,sdslen(key));
|
mixDigest(digest,key,sdslen(key));
|
||||||
|
|
||||||
o = dictGetVal(de);
|
o = (robj*)dictGetVal(de);
|
||||||
xorObjectDigest(db,keyobj,digest,o);
|
xorObjectDigest(db,keyobj,digest,o);
|
||||||
|
|
||||||
/* We can finally xor the key-val digest to the final digest */
|
/* We can finally xor the key-val digest to the final digest */
|
||||||
@ -298,7 +299,7 @@ void computeDatasetDigest(unsigned char *final) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void debugCommand(client *c) {
|
void debugCommand(client *c) {
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"help")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"ASSERT -- Crash by assertion failed.",
|
"ASSERT -- Crash by assertion failed.",
|
||||||
"CHANGE-REPL-ID -- Change the replication IDs of the instance. Dangerous, should be used only for testing the replication subsystem.",
|
"CHANGE-REPL-ID -- Change the replication IDs of the instance. Dangerous, should be used only for testing the replication subsystem.",
|
||||||
@ -326,12 +327,12 @@ void debugCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"segfault")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"segfault")) {
|
||||||
*((char*)-1) = 'x';
|
*((char*)-1) = 'x';
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"panic")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"panic")) {
|
||||||
serverPanic("DEBUG PANIC called at Unix time %ld", time(NULL));
|
serverPanic("DEBUG PANIC called at Unix time %ld", time(NULL));
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"restart") ||
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"restart") ||
|
||||||
!strcasecmp(ptrFromObj(c->argv[1]),"crash-and-recover"))
|
!strcasecmp(szFromObj(c->argv[1]),"crash-and-recover"))
|
||||||
{
|
{
|
||||||
long long delay = 0;
|
long long delay = 0;
|
||||||
if (c->argc >= 3) {
|
if (c->argc >= 3) {
|
||||||
@ -339,21 +340,21 @@ NULL
|
|||||||
!= C_OK) return;
|
!= C_OK) return;
|
||||||
if (delay < 0) delay = 0;
|
if (delay < 0) delay = 0;
|
||||||
}
|
}
|
||||||
int flags = !strcasecmp(ptrFromObj(c->argv[1]),"restart") ?
|
int flags = !strcasecmp(szFromObj(c->argv[1]),"restart") ?
|
||||||
(RESTART_SERVER_GRACEFULLY|RESTART_SERVER_CONFIG_REWRITE) :
|
(RESTART_SERVER_GRACEFULLY|RESTART_SERVER_CONFIG_REWRITE) :
|
||||||
RESTART_SERVER_NONE;
|
RESTART_SERVER_NONE;
|
||||||
restartServer(flags,delay);
|
restartServer(flags,delay);
|
||||||
addReplyError(c,"failed to restart the server. Check server logs.");
|
addReplyError(c,"failed to restart the server. Check server logs.");
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"oom")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"oom")) {
|
||||||
void *ptr = zmalloc(ULONG_MAX, MALLOC_LOCAL); /* Should trigger an out of memory. */
|
void *ptr = zmalloc(ULONG_MAX, MALLOC_LOCAL); /* Should trigger an out of memory. */
|
||||||
zfree(ptr);
|
zfree(ptr);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"assert")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"assert")) {
|
||||||
serverAssertWithInfo(c,c->argv[0],1 == 2);
|
serverAssertWithInfo(c,c->argv[0],1 == 2);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"log") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"log") && c->argc == 3) {
|
||||||
serverLog(LL_WARNING, "DEBUG LOG: %s", (char*)ptrFromObj(c->argv[2]));
|
serverLog(LL_WARNING, "DEBUG LOG: %s", (char*)ptrFromObj(c->argv[2]));
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"reload")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"reload")) {
|
||||||
rdbSaveInfo rsi, *rsiptr;
|
rdbSaveInfo rsi, *rsiptr;
|
||||||
rsiptr = rdbPopulateSaveInfo(&rsi);
|
rsiptr = rdbPopulateSaveInfo(&rsi);
|
||||||
if (rdbSave(rsiptr) != C_OK) {
|
if (rdbSave(rsiptr) != C_OK) {
|
||||||
@ -371,7 +372,7 @@ NULL
|
|||||||
}
|
}
|
||||||
serverLog(LL_WARNING,"DB reloaded by DEBUG RELOAD");
|
serverLog(LL_WARNING,"DB reloaded by DEBUG RELOAD");
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"loadaof")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"loadaof")) {
|
||||||
if (server.aof_state != AOF_OFF) flushAppendOnlyFile(1);
|
if (server.aof_state != AOF_OFF) flushAppendOnlyFile(1);
|
||||||
emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
||||||
protectClient(c);
|
protectClient(c);
|
||||||
@ -384,23 +385,23 @@ NULL
|
|||||||
server.dirty = 0; /* Prevent AOF / replication */
|
server.dirty = 0; /* Prevent AOF / replication */
|
||||||
serverLog(LL_WARNING,"Append Only File loaded by DEBUG LOADAOF");
|
serverLog(LL_WARNING,"Append Only File loaded by DEBUG LOADAOF");
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"object") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"object") && c->argc == 3) {
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
robj *val;
|
robj *val;
|
||||||
char *strenc;
|
const char *strenc;
|
||||||
|
|
||||||
if ((de = dictFind(c->db->pdict,ptrFromObj(c->argv[2]))) == NULL) {
|
if ((de = dictFind(c->db->pdict,ptrFromObj(c->argv[2]))) == NULL) {
|
||||||
addReply(c,shared.nokeyerr);
|
addReply(c,shared.nokeyerr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
val = dictGetVal(de);
|
val = (robj*)dictGetVal(de);
|
||||||
strenc = strEncoding(val->encoding);
|
strenc = strEncoding(val->encoding);
|
||||||
|
|
||||||
char extra[138] = {0};
|
char extra[138] = {0};
|
||||||
if (val->encoding == OBJ_ENCODING_QUICKLIST) {
|
if (val->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||||
char *nextra = extra;
|
char *nextra = extra;
|
||||||
int remaining = sizeof(extra);
|
int remaining = sizeof(extra);
|
||||||
quicklist *ql = val->m_ptr;
|
quicklist *ql = (quicklist*)val->m_ptr;
|
||||||
/* Add number of quicklist nodes */
|
/* Add number of quicklist nodes */
|
||||||
int used = snprintf(nextra, remaining, " ql_nodes:%lu", ql->len);
|
int used = snprintf(nextra, remaining, " ql_nodes:%lu", ql->len);
|
||||||
nextra += used;
|
nextra += used;
|
||||||
@ -436,7 +437,7 @@ NULL
|
|||||||
(void*)val, val->refcount,
|
(void*)val, val->refcount,
|
||||||
strenc, rdbSavedObjectLen(val),
|
strenc, rdbSavedObjectLen(val),
|
||||||
val->lru, estimateObjectIdleTime(val)/1000, extra);
|
val->lru, estimateObjectIdleTime(val)/1000, extra);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"sdslen") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"sdslen") && c->argc == 3) {
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
robj *val;
|
robj *val;
|
||||||
sds key;
|
sds key;
|
||||||
@ -445,8 +446,8 @@ NULL
|
|||||||
addReply(c,shared.nokeyerr);
|
addReply(c,shared.nokeyerr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
val = dictGetVal(de);
|
val = (robj*)dictGetVal(de);
|
||||||
key = dictGetKey(de);
|
key = (sds)dictGetKey(de);
|
||||||
|
|
||||||
if (val->type != OBJ_STRING || !sdsEncodedObject(val)) {
|
if (val->type != OBJ_STRING || !sdsEncodedObject(val)) {
|
||||||
addReplyError(c,"Not an sds encoded string.");
|
addReplyError(c,"Not an sds encoded string.");
|
||||||
@ -457,11 +458,11 @@ NULL
|
|||||||
(long long) sdslen(key),
|
(long long) sdslen(key),
|
||||||
(long long) sdsavail(key),
|
(long long) sdsavail(key),
|
||||||
(long long) sdsZmallocSize(key),
|
(long long) sdsZmallocSize(key),
|
||||||
(long long) sdslen(ptrFromObj(val)),
|
(long long) sdslen(szFromObj(val)),
|
||||||
(long long) sdsavail(ptrFromObj(val)),
|
(long long) sdsavail(szFromObj(val)),
|
||||||
(long long) getStringObjectSdsUsedMemory(val));
|
(long long) getStringObjectSdsUsedMemory(val));
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"ziplist") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"ziplist") && c->argc == 3) {
|
||||||
robj *o;
|
robj *o;
|
||||||
|
|
||||||
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nokeyerr))
|
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nokeyerr))
|
||||||
@ -470,10 +471,10 @@ NULL
|
|||||||
if (o->encoding != OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding != OBJ_ENCODING_ZIPLIST) {
|
||||||
addReplyError(c,"Not an sds encoded string.");
|
addReplyError(c,"Not an sds encoded string.");
|
||||||
} else {
|
} else {
|
||||||
ziplistRepr(ptrFromObj(o));
|
ziplistRepr((unsigned char*)ptrFromObj(o));
|
||||||
addReplyStatus(c,"Ziplist structure printed on stdout");
|
addReplyStatus(c,"Ziplist structure printed on stdout");
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"populate") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"populate") &&
|
||||||
c->argc >= 3 && c->argc <= 5) {
|
c->argc >= 3 && c->argc <= 5) {
|
||||||
long keys, j;
|
long keys, j;
|
||||||
robj *key, *val;
|
robj *key, *val;
|
||||||
@ -507,7 +508,7 @@ NULL
|
|||||||
decrRefCount(key);
|
decrRefCount(key);
|
||||||
}
|
}
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"digest") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"digest") && c->argc == 2) {
|
||||||
/* DEBUG DIGEST (form without keys specified) */
|
/* DEBUG DIGEST (form without keys specified) */
|
||||||
unsigned char digest[20];
|
unsigned char digest[20];
|
||||||
sds d = sdsempty();
|
sds d = sdsempty();
|
||||||
@ -516,7 +517,7 @@ NULL
|
|||||||
for (int i = 0; i < 20; i++) d = sdscatprintf(d, "%02x",digest[i]);
|
for (int i = 0; i < 20; i++) d = sdscatprintf(d, "%02x",digest[i]);
|
||||||
addReplyStatus(c,d);
|
addReplyStatus(c,d);
|
||||||
sdsfree(d);
|
sdsfree(d);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"digest-value") && c->argc >= 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"digest-value") && c->argc >= 2) {
|
||||||
/* DEBUG DIGEST-VALUE key key key ... key. */
|
/* DEBUG DIGEST-VALUE key key key ... key. */
|
||||||
addReplyArrayLen(c,c->argc-2);
|
addReplyArrayLen(c,c->argc-2);
|
||||||
for (int j = 2; j < c->argc; j++) {
|
for (int j = 2; j < c->argc; j++) {
|
||||||
@ -530,10 +531,10 @@ NULL
|
|||||||
addReplyStatus(c,d);
|
addReplyStatus(c,d);
|
||||||
sdsfree(d);
|
sdsfree(d);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"protocol") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"protocol") && c->argc == 3) {
|
||||||
/* DEBUG PROTOCOL [string|integer|double|bignum|null|array|set|map|
|
/* DEBUG PROTOCOL [string|integer|double|bignum|null|array|set|map|
|
||||||
* attrib|push|verbatim|true|false|state|err|bloberr] */
|
* attrib|push|verbatim|true|false|state|err|bloberr] */
|
||||||
char *name = ptrFromObj(c->argv[2]);
|
char *name = szFromObj(c->argv[2]);
|
||||||
if (!strcasecmp(name,"string")) {
|
if (!strcasecmp(name,"string")) {
|
||||||
addReplyBulkCString(c,"Hello World");
|
addReplyBulkCString(c,"Hello World");
|
||||||
} else if (!strcasecmp(name,"integer")) {
|
} else if (!strcasecmp(name,"integer")) {
|
||||||
@ -582,8 +583,8 @@ NULL
|
|||||||
} else {
|
} else {
|
||||||
addReplyError(c,"Wrong protocol type name. Please use one of the following: string|integer|double|bignum|null|array|set|map|attrib|push|verbatim|true|false|state|err|bloberr");
|
addReplyError(c,"Wrong protocol type name. Please use one of the following: string|integer|double|bignum|null|array|set|map|attrib|push|verbatim|true|false|state|err|bloberr");
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"sleep") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"sleep") && c->argc == 3) {
|
||||||
double dtime = strtod(ptrFromObj(c->argv[2]),NULL);
|
double dtime = strtod(szFromObj(c->argv[2]),NULL);
|
||||||
long long utime = dtime*1000000;
|
long long utime = dtime*1000000;
|
||||||
struct timespec tv;
|
struct timespec tv;
|
||||||
|
|
||||||
@ -591,24 +592,24 @@ NULL
|
|||||||
tv.tv_nsec = (utime % 1000000) * 1000;
|
tv.tv_nsec = (utime % 1000000) * 1000;
|
||||||
nanosleep(&tv, NULL);
|
nanosleep(&tv, NULL);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"set-active-expire") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"set-active-expire") &&
|
||||||
c->argc == 3)
|
c->argc == 3)
|
||||||
{
|
{
|
||||||
server.active_expire_enabled = atoi(ptrFromObj(c->argv[2]));
|
server.active_expire_enabled = atoi(szFromObj(c->argv[2]));
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"lua-always-replicate-commands") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"lua-always-replicate-commands") &&
|
||||||
c->argc == 3)
|
c->argc == 3)
|
||||||
{
|
{
|
||||||
server.lua_always_replicate_commands = atoi(ptrFromObj(c->argv[2]));
|
server.lua_always_replicate_commands = atoi(szFromObj(c->argv[2]));
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"error") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"error") && c->argc == 3) {
|
||||||
sds errstr = sdsnewlen("-",1);
|
sds errstr = sdsnewlen("-",1);
|
||||||
|
|
||||||
errstr = sdscatsds(errstr,ptrFromObj(c->argv[2]));
|
errstr = sdscatsds(errstr,szFromObj(c->argv[2]));
|
||||||
errstr = sdsmapchars(errstr,"\n\r"," ",2); /* no newlines in errors. */
|
errstr = sdsmapchars(errstr,"\n\r"," ",2); /* no newlines in errors. */
|
||||||
errstr = sdscatlen(errstr,"\r\n",2);
|
errstr = sdscatlen(errstr,"\r\n",2);
|
||||||
addReplySds(c,errstr);
|
addReplySds(c,errstr);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"structsize") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"structsize") && c->argc == 2) {
|
||||||
sds sizes = sdsempty();
|
sds sizes = sdsempty();
|
||||||
sizes = sdscatprintf(sizes,"bits:%d ",(sizeof(void*) == 8)?64:32);
|
sizes = sdscatprintf(sizes,"bits:%d ",(sizeof(void*) == 8)?64:32);
|
||||||
sizes = sdscatprintf(sizes,"robj:%d ",(int)sizeof(robj));
|
sizes = sdscatprintf(sizes,"robj:%d ",(int)sizeof(robj));
|
||||||
@ -619,7 +620,7 @@ NULL
|
|||||||
sizes = sdscatprintf(sizes,"sdshdr32:%d ",(int)sizeof(struct sdshdr32));
|
sizes = sdscatprintf(sizes,"sdshdr32:%d ",(int)sizeof(struct sdshdr32));
|
||||||
sizes = sdscatprintf(sizes,"sdshdr64:%d ",(int)sizeof(struct sdshdr64));
|
sizes = sdscatprintf(sizes,"sdshdr64:%d ",(int)sizeof(struct sdshdr64));
|
||||||
addReplyBulkSds(c,sizes);
|
addReplyBulkSds(c,sizes);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"htstats") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"htstats") && c->argc == 3) {
|
||||||
long dbid;
|
long dbid;
|
||||||
sds stats = sdsempty();
|
sds stats = sdsempty();
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
@ -640,7 +641,7 @@ NULL
|
|||||||
stats = sdscat(stats,buf);
|
stats = sdscat(stats,buf);
|
||||||
|
|
||||||
addReplyBulkSds(c,stats);
|
addReplyBulkSds(c,stats);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"htstats-key") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"htstats-key") && c->argc == 3) {
|
||||||
robj *o;
|
robj *o;
|
||||||
dict *ht = NULL;
|
dict *ht = NULL;
|
||||||
|
|
||||||
@ -651,12 +652,12 @@ NULL
|
|||||||
switch (o->encoding) {
|
switch (o->encoding) {
|
||||||
case OBJ_ENCODING_SKIPLIST:
|
case OBJ_ENCODING_SKIPLIST:
|
||||||
{
|
{
|
||||||
zset *zs = ptrFromObj(o);
|
zset *zs = (zset*)ptrFromObj(o);
|
||||||
ht = zs->pdict;
|
ht = zs->pdict;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJ_ENCODING_HT:
|
case OBJ_ENCODING_HT:
|
||||||
ht = ptrFromObj(o);
|
ht = (dict*)ptrFromObj(o);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,12 +669,12 @@ NULL
|
|||||||
dictGetStats(buf,sizeof(buf),ht);
|
dictGetStats(buf,sizeof(buf),ht);
|
||||||
addReplyBulkCString(c,buf);
|
addReplyBulkCString(c,buf);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"change-repl-id") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"change-repl-id") && c->argc == 2) {
|
||||||
serverLog(LL_WARNING,"Changing replication IDs after receiving DEBUG change-repl-id");
|
serverLog(LL_WARNING,"Changing replication IDs after receiving DEBUG change-repl-id");
|
||||||
changeReplicationId();
|
changeReplicationId();
|
||||||
clearReplicationId2();
|
clearReplicationId2();
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"stringmatch-test") && c->argc == 2)
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"stringmatch-test") && c->argc == 2)
|
||||||
{
|
{
|
||||||
stringmatchlen_fuzz_test();
|
stringmatchlen_fuzz_test();
|
||||||
addReplyStatus(c,"Apparently Redis did not crash: test passed");
|
addReplyStatus(c,"Apparently Redis did not crash: test passed");
|
||||||
@ -727,9 +728,9 @@ void serverLogObjectDebugInfo(const robj *o) {
|
|||||||
serverLog(LL_WARNING,"Object encoding: %d", o->encoding);
|
serverLog(LL_WARNING,"Object encoding: %d", o->encoding);
|
||||||
serverLog(LL_WARNING,"Object refcount: %d", o->refcount);
|
serverLog(LL_WARNING,"Object refcount: %d", o->refcount);
|
||||||
if (o->type == OBJ_STRING && sdsEncodedObject(o)) {
|
if (o->type == OBJ_STRING && sdsEncodedObject(o)) {
|
||||||
serverLog(LL_WARNING,"Object raw string len: %zu", sdslen(ptrFromObj(o)));
|
serverLog(LL_WARNING,"Object raw string len: %zu", sdslen(szFromObj(o)));
|
||||||
if (sdslen(ptrFromObj(o)) < 4096) {
|
if (sdslen(szFromObj(o)) < 4096) {
|
||||||
sds repr = sdscatrepr(sdsempty(),ptrFromObj(o),sdslen(ptrFromObj(o)));
|
sds repr = sdscatrepr(sdsempty(),szFromObj(o),sdslen(szFromObj(o)));
|
||||||
serverLog(LL_WARNING,"Object raw string content: %s", repr);
|
serverLog(LL_WARNING,"Object raw string content: %s", repr);
|
||||||
sdsfree(repr);
|
sdsfree(repr);
|
||||||
}
|
}
|
||||||
@ -1149,8 +1150,8 @@ void logStackTrace(ucontext_t *uc) {
|
|||||||
trace_size = backtrace(trace+1, 100);
|
trace_size = backtrace(trace+1, 100);
|
||||||
|
|
||||||
if (getMcontextEip(uc) != NULL) {
|
if (getMcontextEip(uc) != NULL) {
|
||||||
char *msg1 = "EIP:\n";
|
const char *msg1 = "EIP:\n";
|
||||||
char *msg2 = "\nBacktrace:\n";
|
const char *msg2 = "\nBacktrace:\n";
|
||||||
if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */};
|
if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */};
|
||||||
trace[0] = getMcontextEip(uc);
|
trace[0] = getMcontextEip(uc);
|
||||||
backtrace_symbols_fd(trace, 1, fd);
|
backtrace_symbols_fd(trace, 1, fd);
|
||||||
@ -1195,7 +1196,7 @@ void logCurrentClient(void) {
|
|||||||
key = getDecodedObject(cc->argv[1]);
|
key = getDecodedObject(cc->argv[1]);
|
||||||
de = dictFind(cc->db->pdict, ptrFromObj(key));
|
de = dictFind(cc->db->pdict, ptrFromObj(key));
|
||||||
if (de) {
|
if (de) {
|
||||||
val = dictGetVal(de);
|
val = (robj*)dictGetVal(de);
|
||||||
serverLog(LL_WARNING,"key '%s' found in DB containing the following object:", (char*)ptrFromObj(key));
|
serverLog(LL_WARNING,"key '%s' found in DB containing the following object:", (char*)ptrFromObj(key));
|
||||||
serverLogObjectDebugInfo(val);
|
serverLogObjectDebugInfo(val);
|
||||||
}
|
}
|
||||||
@ -1256,7 +1257,7 @@ int memtest_test_linux_anonymous_maps(void) {
|
|||||||
int errors = 0;
|
int errors = 0;
|
||||||
for (j = 0; j < regions; j++) {
|
for (j = 0; j < regions; j++) {
|
||||||
if (write(fd,".",1) == -1) { /* Nothing to do. */ }
|
if (write(fd,".",1) == -1) { /* Nothing to do. */ }
|
||||||
errors += memtest_preserving_test((void*)start_vect[j],size_vect[j],1);
|
errors += memtest_preserving_test((unsigned long*)start_vect[j],size_vect[j],1);
|
||||||
if (write(fd, errors ? "E" : "O",1) == -1) { /* Nothing to do. */ }
|
if (write(fd, errors ? "E" : "O",1) == -1) { /* Nothing to do. */ }
|
||||||
}
|
}
|
||||||
if (write(fd,"\n",1) == -1) { /* Nothing to do. */ }
|
if (write(fd,"\n",1) == -1) { /* Nothing to do. */ }
|
||||||
@ -1275,7 +1276,7 @@ int memtest_test_linux_anonymous_maps(void) {
|
|||||||
* and the call offset if they appear to be valid. */
|
* and the call offset if they appear to be valid. */
|
||||||
void dumpX86Calls(void *addr, size_t len) {
|
void dumpX86Calls(void *addr, size_t len) {
|
||||||
size_t j;
|
size_t j;
|
||||||
unsigned char *p = addr;
|
unsigned char *p = (unsigned char*)addr;
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
/* Hash table to best-effort avoid printing the same symbol
|
/* Hash table to best-effort avoid printing the same symbol
|
||||||
* multiple times. */
|
* multiple times. */
|
||||||
@ -1404,7 +1405,7 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
|
|||||||
|
|
||||||
void serverLogHexDump(int level, const char *descr, void *value, size_t len) {
|
void serverLogHexDump(int level, const char *descr, void *value, size_t len) {
|
||||||
char buf[65], *b;
|
char buf[65], *b;
|
||||||
unsigned char *v = value;
|
unsigned char *v = (unsigned char*)value;
|
||||||
char charset[] = "0123456789abcdef";
|
char charset[] = "0123456789abcdef";
|
||||||
|
|
||||||
serverLog(level,"%s (hexdump of %zu bytes):", descr, len);
|
serverLog(level,"%s (hexdump of %zu bytes):", descr, len);
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
/* this method was added to jemalloc in order to help us understand which
|
/* this method was added to jemalloc in order to help us understand which
|
||||||
* pointers are worthwhile moving and which aren't */
|
* pointers are worthwhile moving and which aren't */
|
||||||
int je_get_defrag_hint(void* ptr, int *bin_util, int *run_util);
|
extern "C" int je_get_defrag_hint(void* ptr, int *bin_util, int *run_util);
|
||||||
|
|
||||||
/* forward declarations*/
|
/* forward declarations*/
|
||||||
void defragDictBucketCallback(void *privdata, dictEntry **bucketref);
|
void defragDictBucketCallback(void *privdata, dictEntry **bucketref);
|
||||||
@ -107,7 +107,7 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
|
|||||||
|
|
||||||
/* try to defrag robj (only if not an EMBSTR type (handled below). */
|
/* try to defrag robj (only if not an EMBSTR type (handled below). */
|
||||||
if (ob->type!=OBJ_STRING || ob->encoding!=OBJ_ENCODING_EMBSTR) {
|
if (ob->type!=OBJ_STRING || ob->encoding!=OBJ_ENCODING_EMBSTR) {
|
||||||
if ((ret = activeDefragAlloc(ob))) {
|
if ((ret = (robj*)activeDefragAlloc(ob))) {
|
||||||
ob = ret;
|
ob = ret;
|
||||||
(*defragged)++;
|
(*defragged)++;
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
|
|||||||
} else if (ob->encoding==OBJ_ENCODING_EMBSTR) {
|
} else if (ob->encoding==OBJ_ENCODING_EMBSTR) {
|
||||||
/* The sds is embedded in the object allocation, calculate the
|
/* The sds is embedded in the object allocation, calculate the
|
||||||
* offset and update the pointer in the new allocation. */
|
* offset and update the pointer in the new allocation. */
|
||||||
if ((ret = activeDefragAlloc(ob))) {
|
if ((ret = (robj*)activeDefragAlloc(ob))) {
|
||||||
(*defragged)++;
|
(*defragged)++;
|
||||||
}
|
}
|
||||||
} else if (ob->encoding!=OBJ_ENCODING_INT) {
|
} else if (ob->encoding!=OBJ_ENCODING_INT) {
|
||||||
@ -145,7 +145,7 @@ long dictIterDefragEntry(dictIterator *iter) {
|
|||||||
/* Handle the next entry (if there is one), and update the pointer in the
|
/* Handle the next entry (if there is one), and update the pointer in the
|
||||||
* current entry. */
|
* current entry. */
|
||||||
if (iter->nextEntry) {
|
if (iter->nextEntry) {
|
||||||
dictEntry *newde = activeDefragAlloc(iter->nextEntry);
|
dictEntry *newde = (dictEntry*)activeDefragAlloc(iter->nextEntry);
|
||||||
if (newde) {
|
if (newde) {
|
||||||
defragged++;
|
defragged++;
|
||||||
iter->nextEntry = newde;
|
iter->nextEntry = newde;
|
||||||
@ -155,7 +155,7 @@ long dictIterDefragEntry(dictIterator *iter) {
|
|||||||
/* handle the case of the first entry in the hash bucket. */
|
/* handle the case of the first entry in the hash bucket. */
|
||||||
ht = &iter->d->ht[iter->table];
|
ht = &iter->d->ht[iter->table];
|
||||||
if (ht->table[iter->index] == iter->entry) {
|
if (ht->table[iter->index] == iter->entry) {
|
||||||
dictEntry *newde = activeDefragAlloc(iter->entry);
|
dictEntry *newde = (dictEntry*)activeDefragAlloc(iter->entry);
|
||||||
if (newde) {
|
if (newde) {
|
||||||
iter->entry = newde;
|
iter->entry = newde;
|
||||||
ht->table[iter->index] = newde;
|
ht->table[iter->index] = newde;
|
||||||
@ -172,12 +172,12 @@ long dictDefragTables(dict* d) {
|
|||||||
dictEntry **newtable;
|
dictEntry **newtable;
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
/* handle the first hash table */
|
/* handle the first hash table */
|
||||||
newtable = activeDefragAlloc(d->ht[0].table);
|
newtable = (dictEntry**)activeDefragAlloc(d->ht[0].table);
|
||||||
if (newtable)
|
if (newtable)
|
||||||
defragged++, d->ht[0].table = newtable;
|
defragged++, d->ht[0].table = newtable;
|
||||||
/* handle the second hash table */
|
/* handle the second hash table */
|
||||||
if (d->ht[1].table) {
|
if (d->ht[1].table) {
|
||||||
newtable = activeDefragAlloc(d->ht[1].table);
|
newtable = (dictEntry**)activeDefragAlloc(d->ht[1].table);
|
||||||
if (newtable)
|
if (newtable)
|
||||||
defragged++, d->ht[1].table = newtable;
|
defragged++, d->ht[1].table = newtable;
|
||||||
}
|
}
|
||||||
@ -188,13 +188,13 @@ long dictDefragTables(dict* d) {
|
|||||||
void zslUpdateNode(zskiplist *zsl, zskiplistNode *oldnode, zskiplistNode *newnode, zskiplistNode **update) {
|
void zslUpdateNode(zskiplist *zsl, zskiplistNode *oldnode, zskiplistNode *newnode, zskiplistNode **update) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < zsl->level; i++) {
|
for (i = 0; i < zsl->level; i++) {
|
||||||
if (update[i]->level[i].forward == oldnode)
|
if (update[i]->level(i)->forward == oldnode)
|
||||||
update[i]->level[i].forward = newnode;
|
update[i]->level(i)->forward = newnode;
|
||||||
}
|
}
|
||||||
serverAssert(zsl->header!=oldnode);
|
serverAssert(zsl->header!=oldnode);
|
||||||
if (newnode->level[0].forward) {
|
if (newnode->level(0)->forward) {
|
||||||
serverAssert(newnode->level[0].forward->backward==oldnode);
|
serverAssert(newnode->level(0)->forward->backward==oldnode);
|
||||||
newnode->level[0].forward->backward = newnode;
|
newnode->level(0)->forward->backward = newnode;
|
||||||
} else {
|
} else {
|
||||||
serverAssert(zsl->tail==oldnode);
|
serverAssert(zsl->tail==oldnode);
|
||||||
zsl->tail = newnode;
|
zsl->tail = newnode;
|
||||||
@ -217,25 +217,25 @@ double *zslDefrag(zskiplist *zsl, double score, sds oldele, sds newele) {
|
|||||||
* and all pointers that need to be updated if we'll end up moving the skiplist node. */
|
* and all pointers that need to be updated if we'll end up moving the skiplist node. */
|
||||||
x = zsl->header;
|
x = zsl->header;
|
||||||
for (i = zsl->level-1; i >= 0; i--) {
|
for (i = zsl->level-1; i >= 0; i--) {
|
||||||
while (x->level[i].forward &&
|
while (x->level(i)->forward &&
|
||||||
x->level[i].forward->ele != oldele && /* make sure not to access the
|
x->level(i)->forward->ele != oldele && /* make sure not to access the
|
||||||
->obj pointer if it matches
|
->obj pointer if it matches
|
||||||
oldele */
|
oldele */
|
||||||
(x->level[i].forward->score < score ||
|
(x->level(i)->forward->score < score ||
|
||||||
(x->level[i].forward->score == score &&
|
(x->level(i)->forward->score == score &&
|
||||||
sdscmp(x->level[i].forward->ele,ele) < 0)))
|
sdscmp(x->level(i)->forward->ele,ele) < 0)))
|
||||||
x = x->level[i].forward;
|
x = x->level(i)->forward;
|
||||||
update[i] = x;
|
update[i] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the robj pointer inside the skip list record. */
|
/* update the robj pointer inside the skip list record. */
|
||||||
x = x->level[0].forward;
|
x = x->level(0)->forward;
|
||||||
serverAssert(x && score == x->score && x->ele==oldele);
|
serverAssert(x && score == x->score && x->ele==oldele);
|
||||||
if (newele)
|
if (newele)
|
||||||
x->ele = newele;
|
x->ele = newele;
|
||||||
|
|
||||||
/* try to defrag the skiplist record itself */
|
/* try to defrag the skiplist record itself */
|
||||||
newx = activeDefragAlloc(x);
|
newx = (zskiplistNode*)activeDefragAlloc(x);
|
||||||
if (newx) {
|
if (newx) {
|
||||||
zslUpdateNode(zsl, x, newx, update);
|
zslUpdateNode(zsl, x, newx, update);
|
||||||
return &newx->score;
|
return &newx->score;
|
||||||
@ -249,7 +249,7 @@ long activeDefragZsetEntry(zset *zs, dictEntry *de) {
|
|||||||
sds newsds;
|
sds newsds;
|
||||||
double* newscore;
|
double* newscore;
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
sds sdsele = dictGetKey(de);
|
sds sdsele = (sds)dictGetKey(de);
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
defragged++, de->key = newsds;
|
defragged++, de->key = newsds;
|
||||||
newscore = zslDefrag(zs->zsl, *(double*)dictGetVal(de), sdsele, newsds);
|
newscore = zslDefrag(zs->zsl, *(double*)dictGetVal(de), sdsele, newsds);
|
||||||
@ -272,16 +272,16 @@ long activeDefragSdsDict(dict* d, int val_type) {
|
|||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
di = dictGetIterator(d);
|
di = dictGetIterator(d);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds sdsele = dictGetKey(de), newsds;
|
sds sdsele = (sds)dictGetKey(de), newsds;
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
de->key = newsds, defragged++;
|
de->key = newsds, defragged++;
|
||||||
/* defrag the value */
|
/* defrag the value */
|
||||||
if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
|
if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
|
||||||
sdsele = dictGetVal(de);
|
sdsele = (sds)dictGetVal(de);
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
de->v.val = newsds, defragged++;
|
de->v.val = newsds, defragged++;
|
||||||
} else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
|
} else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
|
||||||
robj *newele, *ele = dictGetVal(de);
|
robj *newele, *ele = (robj*)dictGetVal(de);
|
||||||
if ((newele = activeDefragStringOb(ele, &defragged)))
|
if ((newele = activeDefragStringOb(ele, &defragged)))
|
||||||
de->v.val = newele;
|
de->v.val = newele;
|
||||||
} else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
|
} else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
|
||||||
@ -300,7 +300,7 @@ long activeDefragList(list *l, int val_type) {
|
|||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
listNode *ln, *newln;
|
listNode *ln, *newln;
|
||||||
for (ln = l->head; ln; ln = ln->next) {
|
for (ln = l->head; ln; ln = ln->next) {
|
||||||
if ((newln = activeDefragAlloc(ln))) {
|
if ((newln = (listNode*)activeDefragAlloc(ln))) {
|
||||||
if (newln->prev)
|
if (newln->prev)
|
||||||
newln->prev->next = newln;
|
newln->prev->next = newln;
|
||||||
else
|
else
|
||||||
@ -313,11 +313,11 @@ long activeDefragList(list *l, int val_type) {
|
|||||||
defragged++;
|
defragged++;
|
||||||
}
|
}
|
||||||
if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
|
if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
|
||||||
sds newsds, sdsele = ln->value;
|
sds newsds, sdsele = (sds)ln->value;
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
ln->value = newsds, defragged++;
|
ln->value = newsds, defragged++;
|
||||||
} else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
|
} else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
|
||||||
robj *newele, *ele = ln->value;
|
robj *newele, *ele = (robj*)ln->value;
|
||||||
if ((newele = activeDefragStringOb(ele, &defragged)))
|
if ((newele = activeDefragStringOb(ele, &defragged)))
|
||||||
ln->value = newele;
|
ln->value = newele;
|
||||||
} else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
|
} else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
|
||||||
@ -338,7 +338,7 @@ long activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
/* Defrag the list and it's sds values */
|
/* Defrag the list and it's sds values */
|
||||||
for (ln = l->head; ln; ln = ln->next) {
|
for (ln = l->head; ln; ln = ln->next) {
|
||||||
if ((newln = activeDefragAlloc(ln))) {
|
if ((newln = (listNode*)activeDefragAlloc(ln))) {
|
||||||
if (newln->prev)
|
if (newln->prev)
|
||||||
newln->prev->next = newln;
|
newln->prev->next = newln;
|
||||||
else
|
else
|
||||||
@ -350,7 +350,7 @@ long activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) {
|
|||||||
ln = newln;
|
ln = newln;
|
||||||
defragged++;
|
defragged++;
|
||||||
}
|
}
|
||||||
sdsele = ln->value;
|
sdsele = (sds)ln->value;
|
||||||
if ((newsds = activeDefragSds(sdsele))) {
|
if ((newsds = activeDefragSds(sdsele))) {
|
||||||
/* When defragging an sds value, we need to update the dict key */
|
/* When defragging an sds value, we need to update the dict key */
|
||||||
unsigned int hash = dictGetHash(d, sdsele);
|
unsigned int hash = dictGetHash(d, sdsele);
|
||||||
@ -364,11 +364,11 @@ long activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) {
|
|||||||
di = dictGetIterator(d);
|
di = dictGetIterator(d);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
if (dict_val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
|
if (dict_val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) {
|
||||||
sds newsds, sdsele = dictGetVal(de);
|
sds newsds, sdsele = (sds)dictGetVal(de);
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
de->v.val = newsds, defragged++;
|
de->v.val = newsds, defragged++;
|
||||||
} else if (dict_val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
|
} else if (dict_val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) {
|
||||||
robj *newele, *ele = dictGetVal(de);
|
robj *newele, *ele = (robj*)dictGetVal(de);
|
||||||
if ((newele = activeDefragStringOb(ele, &defragged)))
|
if ((newele = activeDefragStringOb(ele, &defragged)))
|
||||||
de->v.val = newele, defragged++;
|
de->v.val = newele, defragged++;
|
||||||
} else if (dict_val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
|
} else if (dict_val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) {
|
||||||
@ -394,7 +394,7 @@ dictEntry* replaceSateliteDictKeyPtrAndOrDefragDictEntry(dict *d, sds oldkey, sd
|
|||||||
dictEntry **deref = dictFindEntryRefByPtrAndHash(d, oldkey, hash);
|
dictEntry **deref = dictFindEntryRefByPtrAndHash(d, oldkey, hash);
|
||||||
if (deref) {
|
if (deref) {
|
||||||
dictEntry *de = *deref;
|
dictEntry *de = *deref;
|
||||||
dictEntry *newde = activeDefragAlloc(de);
|
dictEntry *newde = (dictEntry*)activeDefragAlloc(de);
|
||||||
if (newde) {
|
if (newde) {
|
||||||
de = *deref = newde;
|
de = *deref = newde;
|
||||||
(*defragged)++;
|
(*defragged)++;
|
||||||
@ -411,7 +411,7 @@ long activeDefragQuickListNodes(quicklist *ql) {
|
|||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
unsigned char *newzl;
|
unsigned char *newzl;
|
||||||
while (node) {
|
while (node) {
|
||||||
if ((newnode = activeDefragAlloc(node))) {
|
if ((newnode = (quicklistNode*)activeDefragAlloc(node))) {
|
||||||
if (newnode->prev)
|
if (newnode->prev)
|
||||||
newnode->prev->next = newnode;
|
newnode->prev->next = newnode;
|
||||||
else
|
else
|
||||||
@ -423,7 +423,7 @@ long activeDefragQuickListNodes(quicklist *ql) {
|
|||||||
node = newnode;
|
node = newnode;
|
||||||
defragged++;
|
defragged++;
|
||||||
}
|
}
|
||||||
if ((newzl = activeDefragAlloc(node->zl)))
|
if ((newzl = (unsigned char*)activeDefragAlloc(node->zl)))
|
||||||
defragged++, node->zl = newzl;
|
defragged++, node->zl = newzl;
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
@ -434,12 +434,12 @@ long activeDefragQuickListNodes(quicklist *ql) {
|
|||||||
* oart of the main dictionary scan. this is needed in order to prevent latency
|
* oart of the main dictionary scan. this is needed in order to prevent latency
|
||||||
* spikes when handling large items */
|
* spikes when handling large items */
|
||||||
void defragLater(redisDb *db, dictEntry *kde) {
|
void defragLater(redisDb *db, dictEntry *kde) {
|
||||||
sds key = sdsdup(dictGetKey(kde));
|
sds key = sdsdup((sds)dictGetKey(kde));
|
||||||
listAddNodeTail(db->defrag_later, key);
|
listAddNodeTail(db->defrag_later, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
long scanLaterList(robj *ob) {
|
long scanLaterList(robj *ob) {
|
||||||
quicklist *ql = ptrFromObj(ob);
|
quicklist *ql = (quicklist*)ptrFromObj(ob);
|
||||||
if (ob->type != OBJ_LIST || ob->encoding != OBJ_ENCODING_QUICKLIST)
|
if (ob->type != OBJ_LIST || ob->encoding != OBJ_ENCODING_QUICKLIST)
|
||||||
return 0;
|
return 0;
|
||||||
server.stat_active_defrag_scanned+=ql->len;
|
server.stat_active_defrag_scanned+=ql->len;
|
||||||
@ -453,7 +453,7 @@ typedef struct {
|
|||||||
|
|
||||||
void scanLaterZsetCallback(void *privdata, const dictEntry *_de) {
|
void scanLaterZsetCallback(void *privdata, const dictEntry *_de) {
|
||||||
dictEntry *de = (dictEntry*)_de;
|
dictEntry *de = (dictEntry*)_de;
|
||||||
scanLaterZsetData *data = privdata;
|
scanLaterZsetData *data = (scanLaterZsetData*)privdata;
|
||||||
data->defragged += activeDefragZsetEntry(data->zs, de);
|
data->defragged += activeDefragZsetEntry(data->zs, de);
|
||||||
server.stat_active_defrag_scanned++;
|
server.stat_active_defrag_scanned++;
|
||||||
}
|
}
|
||||||
@ -470,8 +470,8 @@ long scanLaterZset(robj *ob, unsigned long *cursor) {
|
|||||||
|
|
||||||
void scanLaterSetCallback(void *privdata, const dictEntry *_de) {
|
void scanLaterSetCallback(void *privdata, const dictEntry *_de) {
|
||||||
dictEntry *de = (dictEntry*)_de;
|
dictEntry *de = (dictEntry*)_de;
|
||||||
long *defragged = privdata;
|
long *defragged = (long*)privdata;
|
||||||
sds sdsele = dictGetKey(de), newsds;
|
sds sdsele = (sds)dictGetKey(de), newsds;
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
(*defragged)++, de->key = newsds;
|
(*defragged)++, de->key = newsds;
|
||||||
server.stat_active_defrag_scanned++;
|
server.stat_active_defrag_scanned++;
|
||||||
@ -481,18 +481,18 @@ long scanLaterSet(robj *ob, unsigned long *cursor) {
|
|||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
if (ob->type != OBJ_SET || ob->encoding != OBJ_ENCODING_HT)
|
if (ob->type != OBJ_SET || ob->encoding != OBJ_ENCODING_HT)
|
||||||
return 0;
|
return 0;
|
||||||
dict *d = ptrFromObj(ob);
|
dict *d = (dict*)ptrFromObj(ob);
|
||||||
*cursor = dictScan(d, *cursor, scanLaterSetCallback, defragDictBucketCallback, &defragged);
|
*cursor = dictScan(d, *cursor, scanLaterSetCallback, defragDictBucketCallback, &defragged);
|
||||||
return defragged;
|
return defragged;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scanLaterHashCallback(void *privdata, const dictEntry *_de) {
|
void scanLaterHashCallback(void *privdata, const dictEntry *_de) {
|
||||||
dictEntry *de = (dictEntry*)_de;
|
dictEntry *de = (dictEntry*)_de;
|
||||||
long *defragged = privdata;
|
long *defragged = (long*)privdata;
|
||||||
sds sdsele = dictGetKey(de), newsds;
|
sds sdsele = (sds)dictGetKey(de), newsds;
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
(*defragged)++, de->key = newsds;
|
(*defragged)++, de->key = newsds;
|
||||||
sdsele = dictGetVal(de);
|
sdsele = (sds)dictGetVal(de);
|
||||||
if ((newsds = activeDefragSds(sdsele)))
|
if ((newsds = activeDefragSds(sdsele)))
|
||||||
(*defragged)++, de->v.val = newsds;
|
(*defragged)++, de->v.val = newsds;
|
||||||
server.stat_active_defrag_scanned++;
|
server.stat_active_defrag_scanned++;
|
||||||
@ -502,17 +502,17 @@ long scanLaterHash(robj *ob, unsigned long *cursor) {
|
|||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
if (ob->type != OBJ_HASH || ob->encoding != OBJ_ENCODING_HT)
|
if (ob->type != OBJ_HASH || ob->encoding != OBJ_ENCODING_HT)
|
||||||
return 0;
|
return 0;
|
||||||
dict *d = ptrFromObj(ob);
|
dict *d = (dict*)ptrFromObj(ob);
|
||||||
*cursor = dictScan(d, *cursor, scanLaterHashCallback, defragDictBucketCallback, &defragged);
|
*cursor = dictScan(d, *cursor, scanLaterHashCallback, defragDictBucketCallback, &defragged);
|
||||||
return defragged;
|
return defragged;
|
||||||
}
|
}
|
||||||
|
|
||||||
long defragQuicklist(redisDb *db, dictEntry *kde) {
|
long defragQuicklist(redisDb *db, dictEntry *kde) {
|
||||||
robj *ob = dictGetVal(kde);
|
robj *ob = (robj*)dictGetVal(kde);
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
quicklist *ql = ptrFromObj(ob), *newql;
|
quicklist *ql = (quicklist*)ptrFromObj(ob), *newql;
|
||||||
serverAssert(ob->type == OBJ_LIST && ob->encoding == OBJ_ENCODING_QUICKLIST);
|
serverAssert(ob->type == OBJ_LIST && ob->encoding == OBJ_ENCODING_QUICKLIST);
|
||||||
if ((newql = activeDefragAlloc(ql)))
|
if ((newql = (quicklist*)activeDefragAlloc(ql)))
|
||||||
defragged++, ob->m_ptr = ql = newql;
|
defragged++, ob->m_ptr = ql = newql;
|
||||||
if (ql->len > server.active_defrag_max_scan_fields)
|
if (ql->len > server.active_defrag_max_scan_fields)
|
||||||
defragLater(db, kde);
|
defragLater(db, kde);
|
||||||
@ -522,7 +522,7 @@ long defragQuicklist(redisDb *db, dictEntry *kde) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
|
long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
|
||||||
robj *ob = dictGetVal(kde);
|
robj *ob = (robj*)dictGetVal(kde);
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
zset *zs = (zset*)ptrFromObj(ob);
|
zset *zs = (zset*)ptrFromObj(ob);
|
||||||
zset *newzs;
|
zset *newzs;
|
||||||
@ -531,11 +531,11 @@ long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
struct zskiplistNode *newheader;
|
struct zskiplistNode *newheader;
|
||||||
serverAssert(ob->type == OBJ_ZSET && ob->encoding == OBJ_ENCODING_SKIPLIST);
|
serverAssert(ob->type == OBJ_ZSET && ob->encoding == OBJ_ENCODING_SKIPLIST);
|
||||||
if ((newzs = activeDefragAlloc(zs)))
|
if ((newzs = (zset*)activeDefragAlloc(zs)))
|
||||||
defragged++, ob->m_ptr = zs = newzs;
|
defragged++, ob->m_ptr = zs = newzs;
|
||||||
if ((newzsl = activeDefragAlloc(zs->zsl)))
|
if ((newzsl = (zskiplist*)activeDefragAlloc(zs->zsl)))
|
||||||
defragged++, zs->zsl = newzsl;
|
defragged++, zs->zsl = newzsl;
|
||||||
if ((newheader = activeDefragAlloc(zs->zsl->header)))
|
if ((newheader = (zskiplistNode*)activeDefragAlloc(zs->zsl->header)))
|
||||||
defragged++, zs->zsl->header = newheader;
|
defragged++, zs->zsl->header = newheader;
|
||||||
if (dictSize(zs->pdict) > server.active_defrag_max_scan_fields)
|
if (dictSize(zs->pdict) > server.active_defrag_max_scan_fields)
|
||||||
defragLater(db, kde);
|
defragLater(db, kde);
|
||||||
@ -547,7 +547,7 @@ long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
|
|||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
}
|
}
|
||||||
/* handle the dict struct */
|
/* handle the dict struct */
|
||||||
if ((newdict = activeDefragAlloc(zs->pdict)))
|
if ((newdict = (dict*)activeDefragAlloc(zs->pdict)))
|
||||||
defragged++, zs->pdict = newdict;
|
defragged++, zs->pdict = newdict;
|
||||||
/* defrag the dict tables */
|
/* defrag the dict tables */
|
||||||
defragged += dictDefragTables(zs->pdict);
|
defragged += dictDefragTables(zs->pdict);
|
||||||
@ -556,44 +556,44 @@ long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
|
|||||||
|
|
||||||
long defragHash(redisDb *db, dictEntry *kde) {
|
long defragHash(redisDb *db, dictEntry *kde) {
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
robj *ob = dictGetVal(kde);
|
robj *ob = (robj*)dictGetVal(kde);
|
||||||
dict *d, *newd;
|
dict *d, *newd;
|
||||||
serverAssert(ob->type == OBJ_HASH && ob->encoding == OBJ_ENCODING_HT);
|
serverAssert(ob->type == OBJ_HASH && ob->encoding == OBJ_ENCODING_HT);
|
||||||
d = ptrFromObj(ob);
|
d = (dict*)ptrFromObj(ob);
|
||||||
if (dictSize(d) > server.active_defrag_max_scan_fields)
|
if (dictSize(d) > server.active_defrag_max_scan_fields)
|
||||||
defragLater(db, kde);
|
defragLater(db, kde);
|
||||||
else
|
else
|
||||||
defragged += activeDefragSdsDict(d, DEFRAG_SDS_DICT_VAL_IS_SDS);
|
defragged += activeDefragSdsDict(d, DEFRAG_SDS_DICT_VAL_IS_SDS);
|
||||||
/* handle the dict struct */
|
/* handle the dict struct */
|
||||||
if ((newd = activeDefragAlloc(ptrFromObj(ob))))
|
if ((newd = (dict*)activeDefragAlloc(ptrFromObj(ob))))
|
||||||
defragged++, ob->m_ptr = newd;
|
defragged++, ob->m_ptr = newd;
|
||||||
/* defrag the dict tables */
|
/* defrag the dict tables */
|
||||||
defragged += dictDefragTables(ptrFromObj(ob));
|
defragged += dictDefragTables((dict*)ptrFromObj(ob));
|
||||||
return defragged;
|
return defragged;
|
||||||
}
|
}
|
||||||
|
|
||||||
long defragSet(redisDb *db, dictEntry *kde) {
|
long defragSet(redisDb *db, dictEntry *kde) {
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
robj *ob = dictGetVal(kde);
|
robj *ob = (robj*)dictGetVal(kde);
|
||||||
dict *d, *newd;
|
dict *d, *newd;
|
||||||
serverAssert(ob->type == OBJ_SET && ob->encoding == OBJ_ENCODING_HT);
|
serverAssert(ob->type == OBJ_SET && ob->encoding == OBJ_ENCODING_HT);
|
||||||
d = ptrFromObj(ob);
|
d = (dict*)ptrFromObj(ob);
|
||||||
if (dictSize(d) > server.active_defrag_max_scan_fields)
|
if (dictSize(d) > server.active_defrag_max_scan_fields)
|
||||||
defragLater(db, kde);
|
defragLater(db, kde);
|
||||||
else
|
else
|
||||||
defragged += activeDefragSdsDict(d, DEFRAG_SDS_DICT_NO_VAL);
|
defragged += activeDefragSdsDict(d, DEFRAG_SDS_DICT_NO_VAL);
|
||||||
/* handle the dict struct */
|
/* handle the dict struct */
|
||||||
if ((newd = activeDefragAlloc(ptrFromObj(ob))))
|
if ((newd = (dict*)activeDefragAlloc(ptrFromObj(ob))))
|
||||||
defragged++, ob->m_ptr = newd;
|
defragged++, ob->m_ptr = newd;
|
||||||
/* defrag the dict tables */
|
/* defrag the dict tables */
|
||||||
defragged += dictDefragTables(ptrFromObj(ob));
|
defragged += dictDefragTables((dict*)ptrFromObj(ob));
|
||||||
return defragged;
|
return defragged;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Defrag callback for radix tree iterator, called for each node,
|
/* Defrag callback for radix tree iterator, called for each node,
|
||||||
* used in order to defrag the nodes allocations. */
|
* used in order to defrag the nodes allocations. */
|
||||||
int defragRaxNode(raxNode **noderef) {
|
int defragRaxNode(raxNode **noderef) {
|
||||||
raxNode *newnode = activeDefragAlloc(*noderef);
|
raxNode *newnode = (raxNode*)activeDefragAlloc(*noderef);
|
||||||
if (newnode) {
|
if (newnode) {
|
||||||
*noderef = newnode;
|
*noderef = newnode;
|
||||||
return 1;
|
return 1;
|
||||||
@ -611,7 +611,7 @@ int scanLaterStraemListpacks(robj *ob, unsigned long *cursor, long long endtime,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream *s = ptrFromObj(ob);
|
stream *s = (stream*)ptrFromObj(ob);
|
||||||
raxStart(&ri,s->prax);
|
raxStart(&ri,s->prax);
|
||||||
if (*cursor == 0) {
|
if (*cursor == 0) {
|
||||||
/* if cursor is 0, we start new iteration */
|
/* if cursor is 0, we start new iteration */
|
||||||
@ -662,8 +662,8 @@ typedef void *(raxDefragFunction)(raxIterator *ri, void *privdata, long *defragg
|
|||||||
long defragRadixTree(rax **raxref, int defrag_data, raxDefragFunction *element_cb, void *element_cb_data) {
|
long defragRadixTree(rax **raxref, int defrag_data, raxDefragFunction *element_cb, void *element_cb_data) {
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
raxIterator ri;
|
raxIterator ri;
|
||||||
rax* rax;
|
::rax* rax;
|
||||||
if ((rax = activeDefragAlloc(*raxref)))
|
if ((rax = (::rax*)activeDefragAlloc(*raxref)))
|
||||||
defragged++, *raxref = rax;
|
defragged++, *raxref = rax;
|
||||||
rax = *raxref;
|
rax = *raxref;
|
||||||
raxStart(&ri,rax);
|
raxStart(&ri,rax);
|
||||||
@ -690,10 +690,10 @@ typedef struct {
|
|||||||
|
|
||||||
void* defragStreamConsumerPendingEntry(raxIterator *ri, void *privdata, long *defragged) {
|
void* defragStreamConsumerPendingEntry(raxIterator *ri, void *privdata, long *defragged) {
|
||||||
UNUSED(defragged);
|
UNUSED(defragged);
|
||||||
PendingEntryContext *ctx = privdata;
|
PendingEntryContext *ctx = (PendingEntryContext*)privdata;
|
||||||
streamNACK *nack = ri->data, *newnack;
|
streamNACK *nack = (streamNACK*)ri->data, *newnack;
|
||||||
nack->consumer = ctx->c; /* update nack pointer to consumer */
|
nack->consumer = ctx->c; /* update nack pointer to consumer */
|
||||||
newnack = activeDefragAlloc(nack);
|
newnack = (streamNACK*)activeDefragAlloc(nack);
|
||||||
if (newnack) {
|
if (newnack) {
|
||||||
/* update consumer group pointer to the nack */
|
/* update consumer group pointer to the nack */
|
||||||
void *prev;
|
void *prev;
|
||||||
@ -705,12 +705,12 @@ void* defragStreamConsumerPendingEntry(raxIterator *ri, void *privdata, long *de
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* defragStreamConsumer(raxIterator *ri, void *privdata, long *defragged) {
|
void* defragStreamConsumer(raxIterator *ri, void *privdata, long *defragged) {
|
||||||
streamConsumer *c = ri->data;
|
streamConsumer *c = (streamConsumer*)ri->data;
|
||||||
streamCG *cg = privdata;
|
streamCG *cg = (streamCG*)privdata;
|
||||||
void *newc = activeDefragAlloc(c);
|
void *newc = activeDefragAlloc(c);
|
||||||
if (newc) {
|
if (newc) {
|
||||||
/* note: we don't increment 'defragged' that's done by the caller */
|
/* note: we don't increment 'defragged' that's done by the caller */
|
||||||
c = newc;
|
c = (streamConsumer*)newc;
|
||||||
}
|
}
|
||||||
sds newsds = activeDefragSds(c->name);
|
sds newsds = activeDefragSds(c->name);
|
||||||
if (newsds)
|
if (newsds)
|
||||||
@ -723,7 +723,7 @@ void* defragStreamConsumer(raxIterator *ri, void *privdata, long *defragged) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* defragStreamConsumerGroup(raxIterator *ri, void *privdata, long *defragged) {
|
void* defragStreamConsumerGroup(raxIterator *ri, void *privdata, long *defragged) {
|
||||||
streamCG *cg = ri->data;
|
streamCG *cg = (streamCG*)ri->data;
|
||||||
UNUSED(privdata);
|
UNUSED(privdata);
|
||||||
if (cg->consumers)
|
if (cg->consumers)
|
||||||
*defragged += defragRadixTree(&cg->consumers, 0, defragStreamConsumer, cg);
|
*defragged += defragRadixTree(&cg->consumers, 0, defragStreamConsumer, cg);
|
||||||
@ -734,16 +734,16 @@ void* defragStreamConsumerGroup(raxIterator *ri, void *privdata, long *defragged
|
|||||||
|
|
||||||
long defragStream(redisDb *db, dictEntry *kde) {
|
long defragStream(redisDb *db, dictEntry *kde) {
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
robj *ob = dictGetVal(kde);
|
robj *ob = (robj*)dictGetVal(kde);
|
||||||
serverAssert(ob->type == OBJ_STREAM && ob->encoding == OBJ_ENCODING_STREAM);
|
serverAssert(ob->type == OBJ_STREAM && ob->encoding == OBJ_ENCODING_STREAM);
|
||||||
stream *s = ptrFromObj(ob), *news;
|
stream *s = (stream*)ptrFromObj(ob), *news;
|
||||||
|
|
||||||
/* handle the main struct */
|
/* handle the main struct */
|
||||||
if ((news = activeDefragAlloc(s)))
|
if ((news = (stream*)activeDefragAlloc(s)))
|
||||||
defragged++, ob->m_ptr = s = news;
|
defragged++, ob->m_ptr = s = news;
|
||||||
|
|
||||||
if (raxSize(s->prax) > server.active_defrag_max_scan_fields) {
|
if (raxSize(s->prax) > server.active_defrag_max_scan_fields) {
|
||||||
rax *newrax = activeDefragAlloc(s->prax);
|
rax *newrax = (rax*)activeDefragAlloc(s->prax);
|
||||||
if (newrax)
|
if (newrax)
|
||||||
defragged++, s->prax = newrax;
|
defragged++, s->prax = newrax;
|
||||||
defragLater(db, kde);
|
defragLater(db, kde);
|
||||||
@ -759,7 +759,7 @@ long defragStream(redisDb *db, dictEntry *kde) {
|
|||||||
* all the various pointers it has. Returns a stat of how many pointers were
|
* all the various pointers it has. Returns a stat of how many pointers were
|
||||||
* moved. */
|
* moved. */
|
||||||
long defragKey(redisDb *db, dictEntry *de) {
|
long defragKey(redisDb *db, dictEntry *de) {
|
||||||
sds keysds = dictGetKey(de);
|
sds keysds = (sds)dictGetKey(de);
|
||||||
robj *newob, *ob;
|
robj *newob, *ob;
|
||||||
unsigned char *newzl;
|
unsigned char *newzl;
|
||||||
long defragged = 0;
|
long defragged = 0;
|
||||||
@ -778,7 +778,7 @@ long defragKey(redisDb *db, dictEntry *de) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try to defrag robj and / or string value. */
|
/* Try to defrag robj and / or string value. */
|
||||||
ob = dictGetVal(de);
|
ob = (robj*)dictGetVal(de);
|
||||||
if ((newob = activeDefragStringOb(ob, &defragged))) {
|
if ((newob = activeDefragStringOb(ob, &defragged))) {
|
||||||
de->v.val = newob;
|
de->v.val = newob;
|
||||||
ob = newob;
|
ob = newob;
|
||||||
@ -790,7 +790,7 @@ long defragKey(redisDb *db, dictEntry *de) {
|
|||||||
if (ob->encoding == OBJ_ENCODING_QUICKLIST) {
|
if (ob->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||||
defragged += defragQuicklist(db, de);
|
defragged += defragQuicklist(db, de);
|
||||||
} else if (ob->encoding == OBJ_ENCODING_ZIPLIST) {
|
} else if (ob->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
if ((newzl = activeDefragAlloc(ptrFromObj(ob))))
|
if ((newzl = (unsigned char*)activeDefragAlloc(ptrFromObj(ob))))
|
||||||
defragged++, ob->m_ptr = newzl;
|
defragged++, ob->m_ptr = newzl;
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown list encoding");
|
serverPanic("Unknown list encoding");
|
||||||
@ -799,15 +799,15 @@ long defragKey(redisDb *db, dictEntry *de) {
|
|||||||
if (ob->encoding == OBJ_ENCODING_HT) {
|
if (ob->encoding == OBJ_ENCODING_HT) {
|
||||||
defragged += defragSet(db, de);
|
defragged += defragSet(db, de);
|
||||||
} else if (ob->encoding == OBJ_ENCODING_INTSET) {
|
} else if (ob->encoding == OBJ_ENCODING_INTSET) {
|
||||||
intset *newis, *is = ptrFromObj(ob);
|
intset *newis, *is = (intset*)ptrFromObj(ob);
|
||||||
if ((newis = activeDefragAlloc(is)))
|
if ((newis = (intset*)activeDefragAlloc(is)))
|
||||||
defragged++, ob->m_ptr = newis;
|
defragged++, ob->m_ptr = newis;
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown set encoding");
|
serverPanic("Unknown set encoding");
|
||||||
}
|
}
|
||||||
} else if (ob->type == OBJ_ZSET) {
|
} else if (ob->type == OBJ_ZSET) {
|
||||||
if (ob->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (ob->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
if ((newzl = activeDefragAlloc(ptrFromObj(ob))))
|
if ((newzl = (unsigned char*)activeDefragAlloc(ptrFromObj(ob))))
|
||||||
defragged++, ob->m_ptr = newzl;
|
defragged++, ob->m_ptr = newzl;
|
||||||
} else if (ob->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else if (ob->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||||
defragged += defragZsetSkiplist(db, de);
|
defragged += defragZsetSkiplist(db, de);
|
||||||
@ -816,7 +816,7 @@ long defragKey(redisDb *db, dictEntry *de) {
|
|||||||
}
|
}
|
||||||
} else if (ob->type == OBJ_HASH) {
|
} else if (ob->type == OBJ_HASH) {
|
||||||
if (ob->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (ob->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
if ((newzl = activeDefragAlloc(ptrFromObj(ob))))
|
if ((newzl = (unsigned char*)activeDefragAlloc(ptrFromObj(ob))))
|
||||||
defragged++, ob->m_ptr = newzl;
|
defragged++, ob->m_ptr = newzl;
|
||||||
} else if (ob->encoding == OBJ_ENCODING_HT) {
|
} else if (ob->encoding == OBJ_ENCODING_HT) {
|
||||||
defragged += defragHash(db, de);
|
defragged += defragHash(db, de);
|
||||||
@ -851,7 +851,7 @@ void defragDictBucketCallback(void *privdata, dictEntry **bucketref) {
|
|||||||
UNUSED(privdata); /* NOTE: this function is also used by both activeDefragCycle and scanLaterHash, etc. don't use privdata */
|
UNUSED(privdata); /* NOTE: this function is also used by both activeDefragCycle and scanLaterHash, etc. don't use privdata */
|
||||||
while(*bucketref) {
|
while(*bucketref) {
|
||||||
dictEntry *de = *bucketref, *newde;
|
dictEntry *de = *bucketref, *newde;
|
||||||
if ((newde = activeDefragAlloc(de))) {
|
if ((newde = (dictEntry*)activeDefragAlloc(de))) {
|
||||||
*bucketref = newde;
|
*bucketref = newde;
|
||||||
}
|
}
|
||||||
bucketref = &(*bucketref)->next;
|
bucketref = &(*bucketref)->next;
|
||||||
@ -896,7 +896,7 @@ long defragOtherGlobals() {
|
|||||||
* and 1 if time is up and more work is needed. */
|
* and 1 if time is up and more work is needed. */
|
||||||
int defragLaterItem(dictEntry *de, unsigned long *cursor, long long endtime) {
|
int defragLaterItem(dictEntry *de, unsigned long *cursor, long long endtime) {
|
||||||
if (de) {
|
if (de) {
|
||||||
robj *ob = dictGetVal(de);
|
robj *ob = (robj*)dictGetVal(de);
|
||||||
if (ob->type == OBJ_LIST) {
|
if (ob->type == OBJ_LIST) {
|
||||||
server.stat_active_defrag_hits += scanLaterList(ob);
|
server.stat_active_defrag_hits += scanLaterList(ob);
|
||||||
*cursor = 0; /* list has no scan, we must finish it in one go */
|
*cursor = 0; /* list has no scan, we must finish it in one go */
|
||||||
@ -934,7 +934,7 @@ int defragLaterStep(redisDb *db, long long endtime) {
|
|||||||
/* Move on to next key */
|
/* Move on to next key */
|
||||||
if (current_key) {
|
if (current_key) {
|
||||||
serverAssert(current_key == head->value);
|
serverAssert(current_key == head->value);
|
||||||
sdsfree(head->value);
|
sdsfree((sds)head->value);
|
||||||
listDelNode(db->defrag_later, head);
|
listDelNode(db->defrag_later, head);
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
current_key = NULL;
|
current_key = NULL;
|
||||||
@ -946,7 +946,7 @@ int defragLaterStep(redisDb *db, long long endtime) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* start a new key */
|
/* start a new key */
|
||||||
current_key = head->value;
|
current_key = (sds)head->value;
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -39,6 +39,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#error "C++ Only"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __DICT_H
|
#ifndef __DICT_H
|
||||||
#define __DICT_H
|
#define __DICT_H
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ void evictionPoolAlloc(void) {
|
|||||||
struct evictionPoolEntry *ep;
|
struct evictionPoolEntry *ep;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
ep = zmalloc(sizeof(*ep)*EVPOOL_SIZE, MALLOC_LOCAL);
|
ep = (evictionPoolEntry*)zmalloc(sizeof(*ep)*EVPOOL_SIZE, MALLOC_LOCAL);
|
||||||
for (j = 0; j < EVPOOL_SIZE; j++) {
|
for (j = 0; j < EVPOOL_SIZE; j++) {
|
||||||
ep[j].idle = 0;
|
ep[j].idle = 0;
|
||||||
ep[j].key = NULL;
|
ep[j].key = NULL;
|
||||||
@ -161,7 +161,7 @@ void evictionPoolAlloc(void) {
|
|||||||
|
|
||||||
void evictionPoolPopulate(int dbid, dict *sampledict, dict *keydict, struct evictionPoolEntry *pool) {
|
void evictionPoolPopulate(int dbid, dict *sampledict, dict *keydict, struct evictionPoolEntry *pool) {
|
||||||
int j, k, count;
|
int j, k, count;
|
||||||
dictEntry *samples[server.maxmemory_samples];
|
dictEntry **samples = (dictEntry**)alloca(server.maxmemory_samples * sizeof(dictEntry*));
|
||||||
|
|
||||||
count = dictGetSomeKeys(sampledict,samples,server.maxmemory_samples);
|
count = dictGetSomeKeys(sampledict,samples,server.maxmemory_samples);
|
||||||
for (j = 0; j < count; j++) {
|
for (j = 0; j < count; j++) {
|
||||||
@ -171,14 +171,14 @@ void evictionPoolPopulate(int dbid, dict *sampledict, dict *keydict, struct evic
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
de = samples[j];
|
de = samples[j];
|
||||||
key = dictGetKey(de);
|
key = (sds)dictGetKey(de);
|
||||||
|
|
||||||
/* If the dictionary we are sampling from is not the main
|
/* If the dictionary we are sampling from is not the main
|
||||||
* dictionary (but the expires one) we need to lookup the key
|
* dictionary (but the expires one) we need to lookup the key
|
||||||
* again in the key dictionary to obtain the value object. */
|
* again in the key dictionary to obtain the value object. */
|
||||||
if (server.maxmemory_policy != MAXMEMORY_VOLATILE_TTL) {
|
if (server.maxmemory_policy != MAXMEMORY_VOLATILE_TTL) {
|
||||||
if (sampledict != keydict) de = dictFind(keydict, key);
|
if (sampledict != keydict) de = dictFind(keydict, key);
|
||||||
o = dictGetVal(de);
|
o = (robj*)dictGetVal(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the idle time according to the policy. This is called
|
/* Calculate the idle time according to the policy. This is called
|
||||||
@ -360,7 +360,7 @@ size_t freeMemoryGetNotCountedMemory(void) {
|
|||||||
|
|
||||||
listRewind(server.slaves,&li);
|
listRewind(server.slaves,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *slave = listNodeValue(ln);
|
client *slave = (client*)listNodeValue(ln);
|
||||||
overhead += getClientOutputBufferMemoryUsage(slave);
|
overhead += getClientOutputBufferMemoryUsage(slave);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -521,7 +521,7 @@ int freeMemoryIfNeeded(void) {
|
|||||||
/* If the key exists, is our pick. Otherwise it is
|
/* If the key exists, is our pick. Otherwise it is
|
||||||
* a ghost and we need to try the next element. */
|
* a ghost and we need to try the next element. */
|
||||||
if (de) {
|
if (de) {
|
||||||
bestkey = dictGetKey(de);
|
bestkey = (sds)dictGetKey(de);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* Ghost... Iterate again. */
|
/* Ghost... Iterate again. */
|
||||||
@ -544,7 +544,7 @@ int freeMemoryIfNeeded(void) {
|
|||||||
db->pdict : db->expires;
|
db->pdict : db->expires;
|
||||||
if (dictSize(dict) != 0) {
|
if (dictSize(dict) != 0) {
|
||||||
de = dictGetRandomKey(dict);
|
de = dictGetRandomKey(dict);
|
||||||
bestkey = dictGetKey(de);
|
bestkey = (sds)dictGetKey(de);
|
||||||
bestdbid = j;
|
bestdbid = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
@ -54,7 +54,7 @@
|
|||||||
int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
|
int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
|
||||||
long long t = dictGetSignedIntegerVal(de);
|
long long t = dictGetSignedIntegerVal(de);
|
||||||
if (now > t) {
|
if (now > t) {
|
||||||
sds key = dictGetKey(de);
|
sds key = (sds)dictGetKey(de);
|
||||||
robj *keyobj = createStringObject(key,sdslen(key));
|
robj *keyobj = createStringObject(key,sdslen(key));
|
||||||
|
|
||||||
propagateExpire(db,keyobj,server.lazyfree_lazy_expire);
|
propagateExpire(db,keyobj,server.lazyfree_lazy_expire);
|
||||||
@ -290,7 +290,7 @@ void expireSlaveKeys(void) {
|
|||||||
mstime_t start = mstime();
|
mstime_t start = mstime();
|
||||||
while(1) {
|
while(1) {
|
||||||
dictEntry *de = dictGetRandomKey(slaveKeysWithExpire);
|
dictEntry *de = dictGetRandomKey(slaveKeysWithExpire);
|
||||||
sds keyname = dictGetKey(de);
|
sds keyname = (sds)dictGetKey(de);
|
||||||
uint64_t dbids = dictGetUnsignedIntegerVal(de);
|
uint64_t dbids = dictGetUnsignedIntegerVal(de);
|
||||||
uint64_t new_dbids = 0;
|
uint64_t new_dbids = 0;
|
||||||
|
|
||||||
@ -361,7 +361,7 @@ void rememberSlaveKeyWithExpire(redisDb *db, robj *key) {
|
|||||||
* in sync with the main DB. The keys will be removed by expireSlaveKeys()
|
* in sync with the main DB. The keys will be removed by expireSlaveKeys()
|
||||||
* as it scans to find keys to remove. */
|
* as it scans to find keys to remove. */
|
||||||
if (de->key == ptrFromObj(key)) {
|
if (de->key == ptrFromObj(key)) {
|
||||||
de->key = sdsdup(ptrFromObj(key));
|
de->key = sdsdup(szFromObj(key));
|
||||||
dictSetUnsignedIntegerVal(de,0);
|
dictSetUnsignedIntegerVal(de,0);
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ int zslValueLteMax(double value, zrangespec *spec);
|
|||||||
|
|
||||||
/* Create a new array of geoPoints. */
|
/* Create a new array of geoPoints. */
|
||||||
geoArray *geoArrayCreate(void) {
|
geoArray *geoArrayCreate(void) {
|
||||||
geoArray *ga = zmalloc(sizeof(*ga), MALLOC_SHARED);
|
geoArray *ga = (geoArray*)zmalloc(sizeof(*ga), MALLOC_SHARED);
|
||||||
/* It gets allocated on first geoArrayAppend() call. */
|
/* It gets allocated on first geoArrayAppend() call. */
|
||||||
ga->array = NULL;
|
ga->array = NULL;
|
||||||
ga->buckets = 0;
|
ga->buckets = 0;
|
||||||
@ -64,7 +64,7 @@ geoArray *geoArrayCreate(void) {
|
|||||||
geoPoint *geoArrayAppend(geoArray *ga) {
|
geoPoint *geoArrayAppend(geoArray *ga) {
|
||||||
if (ga->used == ga->buckets) {
|
if (ga->used == ga->buckets) {
|
||||||
ga->buckets = (ga->buckets == 0) ? 8 : ga->buckets*2;
|
ga->buckets = (ga->buckets == 0) ? 8 : ga->buckets*2;
|
||||||
ga->array = zrealloc(ga->array,sizeof(geoPoint)*ga->buckets, MALLOC_SHARED);
|
ga->array = (geoPoint*)zrealloc(ga->array,sizeof(geoPoint)*ga->buckets, MALLOC_SHARED);
|
||||||
}
|
}
|
||||||
geoPoint *gp = ga->array+ga->used;
|
geoPoint *gp = ga->array+ga->used;
|
||||||
ga->used++;
|
ga->used++;
|
||||||
@ -83,7 +83,7 @@ void geoArrayFree(geoArray *ga) {
|
|||||||
* Helpers
|
* Helpers
|
||||||
* ==================================================================== */
|
* ==================================================================== */
|
||||||
int decodeGeohash(double bits, double *xy) {
|
int decodeGeohash(double bits, double *xy) {
|
||||||
GeoHashBits hash = { .bits = (uint64_t)bits, .step = GEO_STEP_MAX };
|
GeoHashBits hash = { (uint64_t)bits, GEO_STEP_MAX };
|
||||||
return geohashDecodeToLongLatWGS84(hash, xy);
|
return geohashDecodeToLongLatWGS84(hash, xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ int extractLongLatOrReply(client *c, robj **argv, double *xy) {
|
|||||||
int longLatFromMember(robj *zobj, robj *member, double *xy) {
|
int longLatFromMember(robj *zobj, robj *member, double *xy) {
|
||||||
double score = 0;
|
double score = 0;
|
||||||
|
|
||||||
if (zsetScore(zobj, ptrFromObj(member), &score) == C_ERR) return C_ERR;
|
if (zsetScore(zobj, szFromObj(member), &score) == C_ERR) return C_ERR;
|
||||||
if (!decodeGeohash(score, xy)) return C_ERR;
|
if (!decodeGeohash(score, xy)) return C_ERR;
|
||||||
return C_OK;
|
return C_OK;
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ int longLatFromMember(robj *zobj, robj *member, double *xy) {
|
|||||||
* If the unit is not valid, an error is reported to the client, and a value
|
* If the unit is not valid, an error is reported to the client, and a value
|
||||||
* less than zero is returned. */
|
* less than zero is returned. */
|
||||||
double extractUnitOrReply(client *c, robj *unit) {
|
double extractUnitOrReply(client *c, robj *unit) {
|
||||||
char *u = ptrFromObj(unit);
|
char *u = szFromObj(unit);
|
||||||
|
|
||||||
if (!strcmp(u, "m")) {
|
if (!strcmp(u, "m")) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -225,12 +225,12 @@ int geoAppendIfWithinRadius(geoArray *ga, double lon, double lat, double radius,
|
|||||||
int geoGetPointsInRange(robj *zobj, double min, double max, double lon, double lat, double radius, geoArray *ga) {
|
int geoGetPointsInRange(robj *zobj, double min, double max, double lon, double lat, double radius, geoArray *ga) {
|
||||||
/* minex 0 = include min in range; maxex 1 = exclude max in range */
|
/* minex 0 = include min in range; maxex 1 = exclude max in range */
|
||||||
/* That's: min <= val < max */
|
/* That's: min <= val < max */
|
||||||
zrangespec range = { .min = min, .max = max, .minex = 0, .maxex = 1 };
|
zrangespec range = { min, max, 0, 1 };
|
||||||
size_t origincount = ga->used;
|
size_t origincount = ga->used;
|
||||||
sds member;
|
sds member;
|
||||||
|
|
||||||
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
unsigned char *zl = zobj->m_ptr;
|
unsigned char *zl = (unsigned char*)zobj->m_ptr;
|
||||||
unsigned char *eptr, *sptr;
|
unsigned char *eptr, *sptr;
|
||||||
unsigned char *vstr = NULL;
|
unsigned char *vstr = NULL;
|
||||||
unsigned int vlen = 0;
|
unsigned int vlen = 0;
|
||||||
@ -259,7 +259,7 @@ int geoGetPointsInRange(robj *zobj, double min, double max, double lon, double l
|
|||||||
zzlNext(zl, &eptr, &sptr);
|
zzlNext(zl, &eptr, &sptr);
|
||||||
}
|
}
|
||||||
} else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||||
zset *zs = zobj->m_ptr;
|
zset *zs = (zset*)zobj->m_ptr;
|
||||||
zskiplist *zsl = zs->zsl;
|
zskiplist *zsl = zs->zsl;
|
||||||
zskiplistNode *ln;
|
zskiplistNode *ln;
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ int geoGetPointsInRange(robj *zobj, double min, double max, double lon, double l
|
|||||||
ele = sdsdup(ele);
|
ele = sdsdup(ele);
|
||||||
if (geoAppendIfWithinRadius(ga,lon,lat,radius,ln->score,ele)
|
if (geoAppendIfWithinRadius(ga,lon,lat,radius,ln->score,ele)
|
||||||
== C_ERR) sdsfree(ele);
|
== C_ERR) sdsfree(ele);
|
||||||
ln = ln->level[0].forward;
|
ln = ln->level(0)->forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ga->used - origincount;
|
return ga->used - origincount;
|
||||||
@ -382,7 +382,7 @@ int membersOfAllNeighbors(robj *zobj, GeoHashRadius n, double lon, double lat, d
|
|||||||
|
|
||||||
/* Sort comparators for qsort() */
|
/* Sort comparators for qsort() */
|
||||||
static int sort_gp_asc(const void *a, const void *b) {
|
static int sort_gp_asc(const void *a, const void *b) {
|
||||||
const struct geoPoint *gpa = a, *gpb = b;
|
const struct geoPoint *gpa = (geoPoint*)a, *gpb = (geoPoint*)b;
|
||||||
/* We can't do adist - bdist because they are doubles and
|
/* We can't do adist - bdist because they are doubles and
|
||||||
* the comparator returns an int. */
|
* the comparator returns an int. */
|
||||||
if (gpa->dist > gpb->dist)
|
if (gpa->dist > gpb->dist)
|
||||||
@ -413,7 +413,7 @@ void geoaddCommand(client *c) {
|
|||||||
|
|
||||||
int elements = (c->argc - 2) / 3;
|
int elements = (c->argc - 2) / 3;
|
||||||
int argc = 2+elements*2; /* ZADD key score ele ... */
|
int argc = 2+elements*2; /* ZADD key score ele ... */
|
||||||
robj **argv = zcalloc(argc*sizeof(robj*), MALLOC_LOCAL);
|
robj **argv = (robj**)zcalloc(argc*sizeof(robj*), MALLOC_LOCAL);
|
||||||
argv[0] = createRawStringObject("zadd",4);
|
argv[0] = createRawStringObject("zadd",4);
|
||||||
argv[1] = c->argv[1]; /* key */
|
argv[1] = c->argv[1]; /* key */
|
||||||
incrRefCount(argv[1]);
|
incrRefCount(argv[1]);
|
||||||
@ -504,7 +504,7 @@ void georadiusGeneric(client *c, int flags) {
|
|||||||
if (c->argc > base_args) {
|
if (c->argc > base_args) {
|
||||||
int remaining = c->argc - base_args;
|
int remaining = c->argc - base_args;
|
||||||
for (int i = 0; i < remaining; i++) {
|
for (int i = 0; i < remaining; i++) {
|
||||||
char *arg = ptrFromObj(c->argv[base_args + i]);
|
char *arg = szFromObj(c->argv[base_args + i]);
|
||||||
if (!strcasecmp(arg, "withdist")) {
|
if (!strcasecmp(arg, "withdist")) {
|
||||||
withdist = 1;
|
withdist = 1;
|
||||||
} else if (!strcasecmp(arg, "withhash")) {
|
} else if (!strcasecmp(arg, "withhash")) {
|
||||||
@ -639,7 +639,7 @@ void georadiusGeneric(client *c, int flags) {
|
|||||||
|
|
||||||
if (returned_items) {
|
if (returned_items) {
|
||||||
zobj = createZsetObject();
|
zobj = createZsetObject();
|
||||||
zs = zobj->m_ptr;
|
zs = (zset*)zobj->m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < returned_items; i++) {
|
for (i = 0; i < returned_items; i++) {
|
||||||
@ -697,7 +697,7 @@ void georadiusbymemberroCommand(client *c) {
|
|||||||
* Returns an array with an 11 characters geohash representation of the
|
* Returns an array with an 11 characters geohash representation of the
|
||||||
* position of the specified elements. */
|
* position of the specified elements. */
|
||||||
void geohashCommand(client *c) {
|
void geohashCommand(client *c) {
|
||||||
char *geoalphabet= "0123456789bcdefghjkmnpqrstuvwxyz";
|
const char *geoalphabet= "0123456789bcdefghjkmnpqrstuvwxyz";
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
/* Look up the requested zset */
|
/* Look up the requested zset */
|
||||||
@ -709,7 +709,7 @@ void geohashCommand(client *c) {
|
|||||||
addReplyArrayLen(c,c->argc-2);
|
addReplyArrayLen(c,c->argc-2);
|
||||||
for (j = 2; j < c->argc; j++) {
|
for (j = 2; j < c->argc; j++) {
|
||||||
double score;
|
double score;
|
||||||
if (!zobj || zsetScore(zobj, ptrFromObj(c->argv[j]), &score) == C_ERR) {
|
if (!zobj || zsetScore(zobj, szFromObj(c->argv[j]), &score) == C_ERR) {
|
||||||
addReplyNull(c);
|
addReplyNull(c);
|
||||||
} else {
|
} else {
|
||||||
/* The internal format we use for geocoding is a bit different
|
/* The internal format we use for geocoding is a bit different
|
||||||
@ -762,7 +762,7 @@ void geoposCommand(client *c) {
|
|||||||
addReplyArrayLen(c,c->argc-2);
|
addReplyArrayLen(c,c->argc-2);
|
||||||
for (j = 2; j < c->argc; j++) {
|
for (j = 2; j < c->argc; j++) {
|
||||||
double score;
|
double score;
|
||||||
if (!zobj || zsetScore(zobj, ptrFromObj(c->argv[j]), &score) == C_ERR) {
|
if (!zobj || zsetScore(zobj, szFromObj(c->argv[j]), &score) == C_ERR) {
|
||||||
addReplyNullArray(c);
|
addReplyNullArray(c);
|
||||||
} else {
|
} else {
|
||||||
/* Decode... */
|
/* Decode... */
|
||||||
@ -802,8 +802,8 @@ void geodistCommand(client *c) {
|
|||||||
|
|
||||||
/* Get the scores. We need both otherwise NULL is returned. */
|
/* Get the scores. We need both otherwise NULL is returned. */
|
||||||
double score1, score2, xyxy[4];
|
double score1, score2, xyxy[4];
|
||||||
if (zsetScore(zobj, ptrFromObj(c->argv[2]), &score1) == C_ERR ||
|
if (zsetScore(zobj, szFromObj(c->argv[2]), &score1) == C_ERR ||
|
||||||
zsetScore(zobj, ptrFromObj(c->argv[3]), &score2) == C_ERR)
|
zsetScore(zobj, szFromObj(c->argv[3]), &score2) == C_ERR)
|
||||||
{
|
{
|
||||||
addReplyNull(c);
|
addReplyNull(c);
|
||||||
return;
|
return;
|
97
src/gopher.c
97
src/gopher.c
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "server.h"
|
|
||||||
|
|
||||||
/* Emit an item in Gopher directory listing format:
|
|
||||||
* <type><descr><TAB><selector><TAB><hostname><TAB><port>
|
|
||||||
* If descr or selector are NULL, then the "(NULL)" string is used instead. */
|
|
||||||
void addReplyGopherItem(client *c, const char *type, const char *descr,
|
|
||||||
const char *selector, const char *hostname, int port)
|
|
||||||
{
|
|
||||||
sds item = sdscatfmt(sdsempty(),"%s%s\t%s\t%s\t%i\r\n",
|
|
||||||
type, descr,
|
|
||||||
selector ? selector : "(NULL)",
|
|
||||||
hostname ? hostname : "(NULL)",
|
|
||||||
port);
|
|
||||||
addReplyProto(c,item,sdslen(item));
|
|
||||||
sdsfree(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is called by processInputBuffer() when an inline request is processed
|
|
||||||
* with Gopher mode enabled, and the request happens to have zero or just one
|
|
||||||
* argument. In such case we get the relevant key and reply using the Gopher
|
|
||||||
* protocol. */
|
|
||||||
void processGopherRequest(client *c) {
|
|
||||||
robj *keyname = c->argc == 0 ? createStringObject("/",1) : c->argv[0];
|
|
||||||
robj *o = lookupKeyRead(c->db,keyname);
|
|
||||||
|
|
||||||
/* If there is no such key, return with a Gopher error. */
|
|
||||||
if (o == NULL || o->type != OBJ_STRING) {
|
|
||||||
char *errstr;
|
|
||||||
if (o == NULL)
|
|
||||||
errstr = "Error: no content at the specified key";
|
|
||||||
else
|
|
||||||
errstr = "Error: selected key type is invalid "
|
|
||||||
"for Gopher output";
|
|
||||||
addReplyGopherItem(c,"i",errstr,NULL,NULL,0);
|
|
||||||
addReplyGopherItem(c,"i","Redis Gopher server",NULL,NULL,0);
|
|
||||||
} else {
|
|
||||||
addReply(c,o);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup, also make sure to emit the final ".CRLF" line. Note that
|
|
||||||
* the connection will be closed immediately after this because the client
|
|
||||||
* will be flagged with CLIENT_CLOSE_AFTER_REPLY, in accordance with the
|
|
||||||
* Gopher protocol. */
|
|
||||||
if (c->argc == 0) decrRefCount(keyname);
|
|
||||||
|
|
||||||
/* Note that in theory we should terminate the Gopher request with
|
|
||||||
* ".<CR><LF>" (called Lastline in the RFC) like that:
|
|
||||||
*
|
|
||||||
* addReplyProto(c,".\r\n",3);
|
|
||||||
*
|
|
||||||
* However after examining the current clients landscape, it's probably
|
|
||||||
* going to do more harm than good for several reasons:
|
|
||||||
*
|
|
||||||
* 1. Clients should not have any issue with missing .<CR><LF> as for
|
|
||||||
* specification, and in the real world indeed certain servers
|
|
||||||
* implementations never used to send the terminator.
|
|
||||||
*
|
|
||||||
* 2. Redis does not know if it's serving a text file or a binary file:
|
|
||||||
* at the same time clients will not remove the ".<CR><LF>" bytes at
|
|
||||||
* tne end when downloading a binary file from the server, so adding
|
|
||||||
* the "Lastline" terminator without knowing the content is just
|
|
||||||
* dangerous.
|
|
||||||
*
|
|
||||||
* 3. The utility gopher2redis.rb that we provide for Redis, and any
|
|
||||||
* other similar tool you may use as Gopher authoring system for
|
|
||||||
* Redis, can just add the "Lastline" when needed.
|
|
||||||
*/
|
|
||||||
}
|
|
@ -184,7 +184,9 @@ struct hllhdr {
|
|||||||
uint8_t encoding; /* HLL_DENSE or HLL_SPARSE. */
|
uint8_t encoding; /* HLL_DENSE or HLL_SPARSE. */
|
||||||
uint8_t notused[3]; /* Reserved for future use, must be zero. */
|
uint8_t notused[3]; /* Reserved for future use, must be zero. */
|
||||||
uint8_t card[8]; /* Cached cardinality, little endian. */
|
uint8_t card[8]; /* Cached cardinality, little endian. */
|
||||||
uint8_t registers[]; /* Data bytes. */
|
uint8_t *registers() { /* Data bytes. */
|
||||||
|
return reinterpret_cast<uint8_t*>(this+1);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The cached cardinality MSB is used to signal validity of the cached value. */
|
/* The cached cardinality MSB is used to signal validity of the cached value. */
|
||||||
@ -205,7 +207,7 @@ struct hllhdr {
|
|||||||
#define HLL_RAW 255 /* Only used internally, never exposed. */
|
#define HLL_RAW 255 /* Only used internally, never exposed. */
|
||||||
#define HLL_MAX_ENCODING 1
|
#define HLL_MAX_ENCODING 1
|
||||||
|
|
||||||
static char *invalid_hll_err = "-INVALIDOBJ Corrupted HLL object detected\r\n";
|
static const char *invalid_hll_err = "-INVALIDOBJ Corrupted HLL object detected\r\n";
|
||||||
|
|
||||||
/* =========================== Low level bit macros ========================= */
|
/* =========================== Low level bit macros ========================= */
|
||||||
|
|
||||||
@ -582,7 +584,7 @@ void hllDenseRegHisto(uint8_t *registers, int* reghisto) {
|
|||||||
* The function returns C_OK if the sparse representation was valid,
|
* The function returns C_OK if the sparse representation was valid,
|
||||||
* otherwise C_ERR is returned if the representation was corrupted. */
|
* otherwise C_ERR is returned if the representation was corrupted. */
|
||||||
int hllSparseToDense(robj *o) {
|
int hllSparseToDense(robj *o) {
|
||||||
sds sparse = ptrFromObj(o), dense;
|
sds sparse = szFromObj(o), dense;
|
||||||
struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse;
|
struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse;
|
||||||
int idx = 0, runlen, regval;
|
int idx = 0, runlen, regval;
|
||||||
uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse);
|
uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse);
|
||||||
@ -616,7 +618,7 @@ int hllSparseToDense(robj *o) {
|
|||||||
regval = HLL_SPARSE_VAL_VALUE(p);
|
regval = HLL_SPARSE_VAL_VALUE(p);
|
||||||
if ((runlen + idx) > HLL_REGISTERS) break; /* Overflow. */
|
if ((runlen + idx) > HLL_REGISTERS) break; /* Overflow. */
|
||||||
while(runlen--) {
|
while(runlen--) {
|
||||||
HLL_DENSE_SET_REGISTER(hdr->registers,idx,regval);
|
HLL_DENSE_SET_REGISTER(hdr->registers(),idx,regval);
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
@ -631,7 +633,7 @@ int hllSparseToDense(robj *o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free the old representation and set the new one. */
|
/* Free the old representation and set the new one. */
|
||||||
sdsfree(ptrFromObj(o));
|
sdsfree(szFromObj(o));
|
||||||
o->m_ptr = dense;
|
o->m_ptr = dense;
|
||||||
return C_OK;
|
return C_OK;
|
||||||
}
|
}
|
||||||
@ -656,6 +658,13 @@ int hllSparseSet(robj *o, long index, uint8_t count) {
|
|||||||
uint8_t oldcount, *sparse, *end, *p, *prev, *next;
|
uint8_t oldcount, *sparse, *end, *p, *prev, *next;
|
||||||
long first, span;
|
long first, span;
|
||||||
long is_zero = 0, is_xzero = 0, is_val = 0, runlen = 0;
|
long is_zero = 0, is_xzero = 0, is_val = 0, runlen = 0;
|
||||||
|
uint8_t seq[5], *n = nullptr;
|
||||||
|
int last;
|
||||||
|
int len;
|
||||||
|
int seqlen = 0;
|
||||||
|
int oldlen = 0;
|
||||||
|
int deltalen = 0;
|
||||||
|
int scanlen = 0;
|
||||||
|
|
||||||
/* If the count is too big to be representable by the sparse representation
|
/* If the count is too big to be representable by the sparse representation
|
||||||
* switch to dense representation. */
|
* switch to dense representation. */
|
||||||
@ -666,12 +675,12 @@ int hllSparseSet(robj *o, long index, uint8_t count) {
|
|||||||
* into XZERO-VAL-XZERO). Make sure there is enough space right now
|
* into XZERO-VAL-XZERO). Make sure there is enough space right now
|
||||||
* so that the pointers we take during the execution of the function
|
* so that the pointers we take during the execution of the function
|
||||||
* will be valid all the time. */
|
* will be valid all the time. */
|
||||||
o->m_ptr = sdsMakeRoomFor(ptrFromObj(o),3);
|
o->m_ptr = sdsMakeRoomFor(szFromObj(o),3);
|
||||||
|
|
||||||
/* Step 1: we need to locate the opcode we need to modify to check
|
/* Step 1: we need to locate the opcode we need to modify to check
|
||||||
* if a value update is actually needed. */
|
* if a value update is actually needed. */
|
||||||
sparse = p = ((uint8_t*)ptrFromObj(o)) + HLL_HDR_SIZE;
|
sparse = p = ((uint8_t*)ptrFromObj(o)) + HLL_HDR_SIZE;
|
||||||
end = p + sdslen(ptrFromObj(o)) - HLL_HDR_SIZE;
|
end = p + sdslen(szFromObj(o)) - HLL_HDR_SIZE;
|
||||||
|
|
||||||
first = 0;
|
first = 0;
|
||||||
prev = NULL; /* Points to previous opcode at the end of the loop. */
|
prev = NULL; /* Points to previous opcode at the end of the loop. */
|
||||||
@ -774,9 +783,8 @@ int hllSparseSet(robj *o, long index, uint8_t count) {
|
|||||||
* with 'newlen' as length. Later the new sequence is inserted in place
|
* with 'newlen' as length. Later the new sequence is inserted in place
|
||||||
* of the old one, possibly moving what is on the right a few bytes
|
* of the old one, possibly moving what is on the right a few bytes
|
||||||
* if the new sequence is longer than the older one. */
|
* if the new sequence is longer than the older one. */
|
||||||
uint8_t seq[5], *n = seq;
|
n = seq;
|
||||||
int last = first+span-1; /* Last register covered by the sequence. */
|
last = first+span-1; /* Last register covered by the sequence. */
|
||||||
int len;
|
|
||||||
|
|
||||||
if (is_zero || is_xzero) {
|
if (is_zero || is_xzero) {
|
||||||
/* Handle splitting of ZERO / XZERO. */
|
/* Handle splitting of ZERO / XZERO. */
|
||||||
@ -824,14 +832,14 @@ int hllSparseSet(robj *o, long index, uint8_t count) {
|
|||||||
*
|
*
|
||||||
* Note that we already allocated space on the sds string
|
* Note that we already allocated space on the sds string
|
||||||
* calling sdsMakeRoomFor(). */
|
* calling sdsMakeRoomFor(). */
|
||||||
int seqlen = n-seq;
|
seqlen = n-seq;
|
||||||
int oldlen = is_xzero ? 2 : 1;
|
oldlen = is_xzero ? 2 : 1;
|
||||||
int deltalen = seqlen-oldlen;
|
deltalen = seqlen-oldlen;
|
||||||
|
|
||||||
if (deltalen > 0 &&
|
if (deltalen > 0 &&
|
||||||
sdslen(ptrFromObj(o))+deltalen > server.hll_sparse_max_bytes) goto promote;
|
sdslen(szFromObj(o))+deltalen > server.hll_sparse_max_bytes) goto promote;
|
||||||
if (deltalen && next) memmove(next+deltalen,next,end-next);
|
if (deltalen && next) memmove(next+deltalen,next,end-next);
|
||||||
sdsIncrLen(ptrFromObj(o),deltalen);
|
sdsIncrLen(szFromObj(o),deltalen);
|
||||||
memcpy(p,seq,seqlen);
|
memcpy(p,seq,seqlen);
|
||||||
end += deltalen;
|
end += deltalen;
|
||||||
|
|
||||||
@ -842,7 +850,7 @@ updated:
|
|||||||
* may not be optimal: adjacent VAL opcodes can sometimes be merged into
|
* may not be optimal: adjacent VAL opcodes can sometimes be merged into
|
||||||
* a single one. */
|
* a single one. */
|
||||||
p = prev ? prev : sparse;
|
p = prev ? prev : sparse;
|
||||||
int scanlen = 5; /* Scan up to 5 upcodes starting from prev. */
|
scanlen = 5; /* Scan up to 5 upcodes starting from prev. */
|
||||||
while (p < end && scanlen--) {
|
while (p < end && scanlen--) {
|
||||||
if (HLL_SPARSE_IS_XZERO(p)) {
|
if (HLL_SPARSE_IS_XZERO(p)) {
|
||||||
p += 2;
|
p += 2;
|
||||||
@ -861,7 +869,7 @@ updated:
|
|||||||
if (len <= HLL_SPARSE_VAL_MAX_LEN) {
|
if (len <= HLL_SPARSE_VAL_MAX_LEN) {
|
||||||
HLL_SPARSE_VAL_SET(p+1,v1,len);
|
HLL_SPARSE_VAL_SET(p+1,v1,len);
|
||||||
memmove(p,p+1,end-p);
|
memmove(p,p+1,end-p);
|
||||||
sdsIncrLen(ptrFromObj(o),-1);
|
sdsIncrLen(szFromObj(o),-1);
|
||||||
end--;
|
end--;
|
||||||
/* After a merge we reiterate without incrementing 'p'
|
/* After a merge we reiterate without incrementing 'p'
|
||||||
* in order to try to merge the just merged value with
|
* in order to try to merge the just merged value with
|
||||||
@ -874,13 +882,13 @@ updated:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Invalidate the cached cardinality. */
|
/* Invalidate the cached cardinality. */
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
HLL_INVALIDATE_CACHE(hdr);
|
HLL_INVALIDATE_CACHE(hdr);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
promote: /* Promote to dense representation. */
|
promote: /* Promote to dense representation. */
|
||||||
if (hllSparseToDense(o) == C_ERR) return -1; /* Corrupted HLL. */
|
if (hllSparseToDense(o) == C_ERR) return -1; /* Corrupted HLL. */
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
|
|
||||||
/* We need to call hllDenseAdd() to perform the operation after the
|
/* We need to call hllDenseAdd() to perform the operation after the
|
||||||
* conversion. However the result must be 1, since if we need to
|
* conversion. However the result must be 1, since if we need to
|
||||||
@ -889,7 +897,7 @@ promote: /* Promote to dense representation. */
|
|||||||
* Note that this in turn means that PFADD will make sure the command
|
* Note that this in turn means that PFADD will make sure the command
|
||||||
* is propagated to slaves / AOF, so if there is a sparse -> dense
|
* is propagated to slaves / AOF, so if there is a sparse -> dense
|
||||||
* conversion, it will be performed in all the slaves as well. */
|
* conversion, it will be performed in all the slaves as well. */
|
||||||
int dense_retval = hllDenseSet(hdr->registers,index,count);
|
int dense_retval = hllDenseSet(hdr->registers(),index,count);
|
||||||
serverAssert(dense_retval == 1);
|
serverAssert(dense_retval == 1);
|
||||||
return dense_retval;
|
return dense_retval;
|
||||||
}
|
}
|
||||||
@ -1007,7 +1015,7 @@ double hllTau(double x) {
|
|||||||
* pointed by 'invalid' is set to non-zero, otherwise it is left untouched.
|
* pointed by 'invalid' is set to non-zero, otherwise it is left untouched.
|
||||||
*
|
*
|
||||||
* hllCount() supports a special internal-only encoding of HLL_RAW, that
|
* hllCount() supports a special internal-only encoding of HLL_RAW, that
|
||||||
* is, hdr->registers will point to an uint8_t array of HLL_REGISTERS element.
|
* is, hdr->registers() will point to an uint8_t array of HLL_REGISTERS element.
|
||||||
* This is useful in order to speedup PFCOUNT when called against multiple
|
* This is useful in order to speedup PFCOUNT when called against multiple
|
||||||
* keys (no need to work with 6-bit integers encoding). */
|
* keys (no need to work with 6-bit integers encoding). */
|
||||||
uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
|
uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
|
||||||
@ -1023,12 +1031,12 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
|
|||||||
|
|
||||||
/* Compute register histogram */
|
/* Compute register histogram */
|
||||||
if (hdr->encoding == HLL_DENSE) {
|
if (hdr->encoding == HLL_DENSE) {
|
||||||
hllDenseRegHisto(hdr->registers,reghisto);
|
hllDenseRegHisto(hdr->registers(),reghisto);
|
||||||
} else if (hdr->encoding == HLL_SPARSE) {
|
} else if (hdr->encoding == HLL_SPARSE) {
|
||||||
hllSparseRegHisto(hdr->registers,
|
hllSparseRegHisto(hdr->registers(),
|
||||||
sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,reghisto);
|
sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,reghisto);
|
||||||
} else if (hdr->encoding == HLL_RAW) {
|
} else if (hdr->encoding == HLL_RAW) {
|
||||||
hllRawRegHisto(hdr->registers,reghisto);
|
hllRawRegHisto(hdr->registers(),reghisto);
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown HyperLogLog encoding in hllCount()");
|
serverPanic("Unknown HyperLogLog encoding in hllCount()");
|
||||||
}
|
}
|
||||||
@ -1049,9 +1057,9 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
|
|||||||
|
|
||||||
/* Call hllDenseAdd() or hllSparseAdd() according to the HLL encoding. */
|
/* Call hllDenseAdd() or hllSparseAdd() according to the HLL encoding. */
|
||||||
int hllAdd(robj *o, unsigned char *ele, size_t elesize) {
|
int hllAdd(robj *o, unsigned char *ele, size_t elesize) {
|
||||||
struct hllhdr *hdr = ptrFromObj(o);
|
struct hllhdr *hdr = (hllhdr*)ptrFromObj(o);
|
||||||
switch(hdr->encoding) {
|
switch(hdr->encoding) {
|
||||||
case HLL_DENSE: return hllDenseAdd(hdr->registers,ele,elesize);
|
case HLL_DENSE: return hllDenseAdd(hdr->registers(),ele,elesize);
|
||||||
case HLL_SPARSE: return hllSparseAdd(o,ele,elesize);
|
case HLL_SPARSE: return hllSparseAdd(o,ele,elesize);
|
||||||
default: return -1; /* Invalid representation. */
|
default: return -1; /* Invalid representation. */
|
||||||
}
|
}
|
||||||
@ -1066,18 +1074,18 @@ int hllAdd(robj *o, unsigned char *ele, size_t elesize) {
|
|||||||
* If the HyperLogLog is sparse and is found to be invalid, C_ERR
|
* If the HyperLogLog is sparse and is found to be invalid, C_ERR
|
||||||
* is returned, otherwise the function always succeeds. */
|
* is returned, otherwise the function always succeeds. */
|
||||||
int hllMerge(uint8_t *max, size_t cmax, robj *hll) {
|
int hllMerge(uint8_t *max, size_t cmax, robj *hll) {
|
||||||
struct hllhdr *hdr = ptrFromObj(hll);
|
struct hllhdr *hdr = (hllhdr*)ptrFromObj(hll);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (hdr->encoding == HLL_DENSE) {
|
if (hdr->encoding == HLL_DENSE) {
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
|
|
||||||
for (i = 0; i < HLL_REGISTERS; i++) {
|
for (i = 0; i < HLL_REGISTERS; i++) {
|
||||||
HLL_DENSE_GET_REGISTER(val,hdr->registers,i);
|
HLL_DENSE_GET_REGISTER(val,hdr->registers(),i);
|
||||||
if (val > max[i]) max[i] = val;
|
if (val > max[i]) max[i] = val;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint8_t *p = ptrFromObj(hll), *end = p + sdslen(ptrFromObj(hll));
|
uint8_t *p = (uint8_t*)ptrFromObj(hll), *end = p + sdslen(szFromObj(hll));
|
||||||
long runlen, regval;
|
long runlen, regval;
|
||||||
|
|
||||||
p += HLL_HDR_SIZE;
|
p += HLL_HDR_SIZE;
|
||||||
@ -1139,7 +1147,7 @@ robj *createHLLObject(void) {
|
|||||||
|
|
||||||
/* Create the actual object. */
|
/* Create the actual object. */
|
||||||
o = createObject(OBJ_STRING,s);
|
o = createObject(OBJ_STRING,s);
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
memcpy(hdr->magic,"HYLL",4);
|
memcpy(hdr->magic,"HYLL",4);
|
||||||
hdr->encoding = HLL_SPARSE;
|
hdr->encoding = HLL_SPARSE;
|
||||||
return o;
|
return o;
|
||||||
@ -1157,7 +1165,7 @@ int isHLLObjectOrReply(client *c, robj *o) {
|
|||||||
|
|
||||||
if (!sdsEncodedObject(o)) goto invalid;
|
if (!sdsEncodedObject(o)) goto invalid;
|
||||||
if (stringObjectLen(o) < sizeof(*hdr)) goto invalid;
|
if (stringObjectLen(o) < sizeof(*hdr)) goto invalid;
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
|
|
||||||
/* Magic should be "HYLL". */
|
/* Magic should be "HYLL". */
|
||||||
if (hdr->magic[0] != 'H' || hdr->magic[1] != 'Y' ||
|
if (hdr->magic[0] != 'H' || hdr->magic[1] != 'Y' ||
|
||||||
@ -1199,7 +1207,7 @@ void pfaddCommand(client *c) {
|
|||||||
/* Perform the low level ADD operation for every element. */
|
/* Perform the low level ADD operation for every element. */
|
||||||
for (j = 2; j < c->argc; j++) {
|
for (j = 2; j < c->argc; j++) {
|
||||||
int retval = hllAdd(o, (unsigned char*)ptrFromObj(c->argv[j]),
|
int retval = hllAdd(o, (unsigned char*)ptrFromObj(c->argv[j]),
|
||||||
sdslen(ptrFromObj(c->argv[j])));
|
sdslen(szFromObj(c->argv[j])));
|
||||||
switch(retval) {
|
switch(retval) {
|
||||||
case 1:
|
case 1:
|
||||||
updated++;
|
updated++;
|
||||||
@ -1209,7 +1217,7 @@ void pfaddCommand(client *c) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
if (updated) {
|
if (updated) {
|
||||||
signalModifiedKey(c->db,c->argv[1]);
|
signalModifiedKey(c->db,c->argv[1]);
|
||||||
notifyKeyspaceEvent(NOTIFY_STRING,"pfadd",c->argv[1],c->db->id);
|
notifyKeyspaceEvent(NOTIFY_STRING,"pfadd",c->argv[1],c->db->id);
|
||||||
@ -1271,7 +1279,7 @@ void pfcountCommand(client *c) {
|
|||||||
o = dbUnshareStringValue(c->db,c->argv[1],o);
|
o = dbUnshareStringValue(c->db,c->argv[1],o);
|
||||||
|
|
||||||
/* Check if the cached cardinality is valid. */
|
/* Check if the cached cardinality is valid. */
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
if (HLL_VALID_CACHE(hdr)) {
|
if (HLL_VALID_CACHE(hdr)) {
|
||||||
/* Just return the cached value. */
|
/* Just return the cached value. */
|
||||||
card = (uint64_t)hdr->card[0];
|
card = (uint64_t)hdr->card[0];
|
||||||
@ -1328,7 +1336,7 @@ void pfmergeCommand(client *c) {
|
|||||||
|
|
||||||
/* If at least one involved HLL is dense, use the dense representation
|
/* If at least one involved HLL is dense, use the dense representation
|
||||||
* as target ASAP to save time and avoid the conversion step. */
|
* as target ASAP to save time and avoid the conversion step. */
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
if (hdr->encoding == HLL_DENSE) use_dense = 1;
|
if (hdr->encoding == HLL_DENSE) use_dense = 1;
|
||||||
|
|
||||||
/* Merge with this HLL with our 'max' HHL by setting max[i]
|
/* Merge with this HLL with our 'max' HHL by setting max[i]
|
||||||
@ -1365,13 +1373,13 @@ void pfmergeCommand(client *c) {
|
|||||||
* invalidate the cached value. */
|
* invalidate the cached value. */
|
||||||
for (j = 0; j < HLL_REGISTERS; j++) {
|
for (j = 0; j < HLL_REGISTERS; j++) {
|
||||||
if (max[j] == 0) continue;
|
if (max[j] == 0) continue;
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
switch(hdr->encoding) {
|
switch(hdr->encoding) {
|
||||||
case HLL_DENSE: hllDenseSet(hdr->registers,j,max[j]); break;
|
case HLL_DENSE: hllDenseSet(hdr->registers(),j,max[j]); break;
|
||||||
case HLL_SPARSE: hllSparseSet(o,j,max[j]); break;
|
case HLL_SPARSE: hllSparseSet(o,j,max[j]); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hdr = ptrFromObj(o); /* ptrFromObj(o) may be different now, as a side effect of
|
hdr = (hllhdr*)ptrFromObj(o); /* ptrFromObj(o) may be different now, as a side effect of
|
||||||
last hllSparseSet() call. */
|
last hllSparseSet() call. */
|
||||||
HLL_INVALIDATE_CACHE(hdr);
|
HLL_INVALIDATE_CACHE(hdr);
|
||||||
|
|
||||||
@ -1395,6 +1403,10 @@ void pfselftestCommand(client *c) {
|
|||||||
struct hllhdr *hdr = (struct hllhdr*) bitcounters, *hdr2;
|
struct hllhdr *hdr = (struct hllhdr*) bitcounters, *hdr2;
|
||||||
robj *o = NULL;
|
robj *o = NULL;
|
||||||
uint8_t bytecounters[HLL_REGISTERS];
|
uint8_t bytecounters[HLL_REGISTERS];
|
||||||
|
int64_t checkpoint = 1;
|
||||||
|
uint64_t seed = 0;
|
||||||
|
uint64_t ele;
|
||||||
|
double relerr = 0;
|
||||||
|
|
||||||
/* Test 1: access registers.
|
/* Test 1: access registers.
|
||||||
* The test is conceived to test that the different counters of our data
|
* The test is conceived to test that the different counters of our data
|
||||||
@ -1407,13 +1419,13 @@ void pfselftestCommand(client *c) {
|
|||||||
unsigned int r = rand() & HLL_REGISTER_MAX;
|
unsigned int r = rand() & HLL_REGISTER_MAX;
|
||||||
|
|
||||||
bytecounters[i] = r;
|
bytecounters[i] = r;
|
||||||
HLL_DENSE_SET_REGISTER(hdr->registers,i,r);
|
HLL_DENSE_SET_REGISTER(hdr->registers(),i,r);
|
||||||
}
|
}
|
||||||
/* Check that we are able to retrieve the same values. */
|
/* Check that we are able to retrieve the same values. */
|
||||||
for (i = 0; i < HLL_REGISTERS; i++) {
|
for (i = 0; i < HLL_REGISTERS; i++) {
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
|
||||||
HLL_DENSE_GET_REGISTER(val,hdr->registers,i);
|
HLL_DENSE_GET_REGISTER(val,hdr->registers(),i);
|
||||||
if (val != bytecounters[i]) {
|
if (val != bytecounters[i]) {
|
||||||
addReplyErrorFormat(c,
|
addReplyErrorFormat(c,
|
||||||
"TESTFAILED Register %d should be %d but is %d",
|
"TESTFAILED Register %d should be %d but is %d",
|
||||||
@ -1433,21 +1445,20 @@ void pfselftestCommand(client *c) {
|
|||||||
*
|
*
|
||||||
* The test is performed with both dense and sparse HLLs at the same
|
* The test is performed with both dense and sparse HLLs at the same
|
||||||
* time also verifying that the computed cardinality is the same. */
|
* time also verifying that the computed cardinality is the same. */
|
||||||
memset(hdr->registers,0,HLL_DENSE_SIZE-HLL_HDR_SIZE);
|
memset(hdr->registers(),0,HLL_DENSE_SIZE-HLL_HDR_SIZE);
|
||||||
o = createHLLObject();
|
o = createHLLObject();
|
||||||
double relerr = 1.04/sqrt(HLL_REGISTERS);
|
relerr = 1.04/sqrt(HLL_REGISTERS);
|
||||||
int64_t checkpoint = 1;
|
checkpoint = 1;
|
||||||
uint64_t seed = (uint64_t)rand() | (uint64_t)rand() << 32;
|
seed = (uint64_t)rand() | (uint64_t)rand() << 32;
|
||||||
uint64_t ele;
|
|
||||||
for (j = 1; j <= 10000000; j++) {
|
for (j = 1; j <= 10000000; j++) {
|
||||||
ele = j ^ seed;
|
ele = j ^ seed;
|
||||||
hllDenseAdd(hdr->registers,(unsigned char*)&ele,sizeof(ele));
|
hllDenseAdd(hdr->registers(),(unsigned char*)&ele,sizeof(ele));
|
||||||
hllAdd(o,(unsigned char*)&ele,sizeof(ele));
|
hllAdd(o,(unsigned char*)&ele,sizeof(ele));
|
||||||
|
|
||||||
/* Make sure that for small cardinalities we use sparse
|
/* Make sure that for small cardinalities we use sparse
|
||||||
* encoding. */
|
* encoding. */
|
||||||
if (j == checkpoint && j < server.hll_sparse_max_bytes/2) {
|
if (j == checkpoint && j < server.hll_sparse_max_bytes/2) {
|
||||||
hdr2 = ptrFromObj(o);
|
hdr2 = (hllhdr*)ptrFromObj(o);
|
||||||
if (hdr2->encoding != HLL_SPARSE) {
|
if (hdr2->encoding != HLL_SPARSE) {
|
||||||
addReplyError(c, "TESTFAILED sparse encoding not used");
|
addReplyError(c, "TESTFAILED sparse encoding not used");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -1455,7 +1466,7 @@ void pfselftestCommand(client *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check that dense and sparse representations agree. */
|
/* Check that dense and sparse representations agree. */
|
||||||
if (j == checkpoint && hllCount(hdr,NULL) != hllCount(ptrFromObj(o),NULL)) {
|
if (j == checkpoint && hllCount(hdr,NULL) != hllCount((hllhdr*)ptrFromObj(o),NULL)) {
|
||||||
addReplyError(c, "TESTFAILED dense/sparse disagree");
|
addReplyError(c, "TESTFAILED dense/sparse disagree");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1494,7 +1505,7 @@ cleanup:
|
|||||||
/* PFDEBUG <subcommand> <key> ... args ...
|
/* PFDEBUG <subcommand> <key> ... args ...
|
||||||
* Different debugging related operations about the HLL implementation. */
|
* Different debugging related operations about the HLL implementation. */
|
||||||
void pfdebugCommand(client *c) {
|
void pfdebugCommand(client *c) {
|
||||||
char *cmd = ptrFromObj(c->argv[1]);
|
char *cmd = szFromObj(c->argv[1]);
|
||||||
struct hllhdr *hdr;
|
struct hllhdr *hdr;
|
||||||
robj *o;
|
robj *o;
|
||||||
int j;
|
int j;
|
||||||
@ -1506,7 +1517,7 @@ void pfdebugCommand(client *c) {
|
|||||||
}
|
}
|
||||||
if (isHLLObjectOrReply(c,o) != C_OK) return;
|
if (isHLLObjectOrReply(c,o) != C_OK) return;
|
||||||
o = dbUnshareStringValue(c->db,c->argv[2],o);
|
o = dbUnshareStringValue(c->db,c->argv[2],o);
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
|
|
||||||
/* PFDEBUG GETREG <key> */
|
/* PFDEBUG GETREG <key> */
|
||||||
if (!strcasecmp(cmd,"getreg")) {
|
if (!strcasecmp(cmd,"getreg")) {
|
||||||
@ -1520,12 +1531,12 @@ void pfdebugCommand(client *c) {
|
|||||||
server.dirty++; /* Force propagation on encoding change. */
|
server.dirty++; /* Force propagation on encoding change. */
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr = ptrFromObj(o);
|
hdr = (hllhdr*)ptrFromObj(o);
|
||||||
addReplyArrayLen(c,HLL_REGISTERS);
|
addReplyArrayLen(c,HLL_REGISTERS);
|
||||||
for (j = 0; j < HLL_REGISTERS; j++) {
|
for (j = 0; j < HLL_REGISTERS; j++) {
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
|
|
||||||
HLL_DENSE_GET_REGISTER(val,hdr->registers,j);
|
HLL_DENSE_GET_REGISTER(val,hdr->registers(),j);
|
||||||
addReplyLongLong(c,val);
|
addReplyLongLong(c,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1533,7 +1544,7 @@ void pfdebugCommand(client *c) {
|
|||||||
else if (!strcasecmp(cmd,"decode")) {
|
else if (!strcasecmp(cmd,"decode")) {
|
||||||
if (c->argc != 3) goto arityerr;
|
if (c->argc != 3) goto arityerr;
|
||||||
|
|
||||||
uint8_t *p = ptrFromObj(o), *end = p+sdslen(ptrFromObj(o));
|
uint8_t *p = (uint8_t*)ptrFromObj(o), *end = p+sdslen(szFromObj(o));
|
||||||
sds decoded = sdsempty();
|
sds decoded = sdsempty();
|
||||||
|
|
||||||
if (hdr->encoding != HLL_SPARSE) {
|
if (hdr->encoding != HLL_SPARSE) {
|
||||||
@ -1566,7 +1577,7 @@ void pfdebugCommand(client *c) {
|
|||||||
}
|
}
|
||||||
/* PFDEBUG ENCODING <key> */
|
/* PFDEBUG ENCODING <key> */
|
||||||
else if (!strcasecmp(cmd,"encoding")) {
|
else if (!strcasecmp(cmd,"encoding")) {
|
||||||
char *encodingstr[2] = {"dense","sparse"};
|
const char *encodingstr[2] = {"dense","sparse"};
|
||||||
if (c->argc != 3) goto arityerr;
|
if (c->argc != 3) goto arityerr;
|
||||||
|
|
||||||
addReplyStatus(c,encodingstr[hdr->encoding]);
|
addReplyStatus(c,encodingstr[hdr->encoding]);
|
@ -38,11 +38,11 @@
|
|||||||
/* Dictionary type for latency events. */
|
/* Dictionary type for latency events. */
|
||||||
int dictStringKeyCompare(void *privdata, const void *key1, const void *key2) {
|
int dictStringKeyCompare(void *privdata, const void *key1, const void *key2) {
|
||||||
UNUSED(privdata);
|
UNUSED(privdata);
|
||||||
return strcmp(key1,key2) == 0;
|
return strcmp((const char*)key1,(const char*)key2) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t dictStringHash(const void *key) {
|
uint64_t dictStringHash(const void *key) {
|
||||||
return dictGenHashFunction(key, strlen(key));
|
return dictGenHashFunction(key, strlen((const char*)key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void dictVanillaFree(void *privdata, void *val);
|
void dictVanillaFree(void *privdata, void *val);
|
||||||
@ -96,13 +96,13 @@ void latencyMonitorInit(void) {
|
|||||||
* is a macro that only adds the sample if the latency is higher than
|
* is a macro that only adds the sample if the latency is higher than
|
||||||
* server.latency_monitor_threshold. */
|
* server.latency_monitor_threshold. */
|
||||||
void latencyAddSample(const char *event, mstime_t latency) {
|
void latencyAddSample(const char *event, mstime_t latency) {
|
||||||
struct latencyTimeSeries *ts = dictFetchValue(server.latency_events,event);
|
struct latencyTimeSeries *ts = (latencyTimeSeries*)dictFetchValue(server.latency_events,event);
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
int prev;
|
int prev;
|
||||||
|
|
||||||
/* Create the time series if it does not exist. */
|
/* Create the time series if it does not exist. */
|
||||||
if (ts == NULL) {
|
if (ts == NULL) {
|
||||||
ts = zmalloc(sizeof(*ts), MALLOC_SHARED);
|
ts = (latencyTimeSeries*)zmalloc(sizeof(*ts), MALLOC_SHARED);
|
||||||
ts->idx = 0;
|
ts->idx = 0;
|
||||||
ts->max = 0;
|
ts->max = 0;
|
||||||
memset(ts->samples,0,sizeof(ts->samples));
|
memset(ts->samples,0,sizeof(ts->samples));
|
||||||
@ -139,7 +139,7 @@ int latencyResetEvent(char *event_to_reset) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.latency_events);
|
di = dictGetSafeIterator(server.latency_events);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
char *event = dictGetKey(de);
|
char *event = (char*)dictGetKey(de);
|
||||||
|
|
||||||
if (event_to_reset == NULL || strcasecmp(event,event_to_reset) == 0) {
|
if (event_to_reset == NULL || strcasecmp(event,event_to_reset) == 0) {
|
||||||
dictDelete(server.latency_events, event);
|
dictDelete(server.latency_events, event);
|
||||||
@ -158,7 +158,7 @@ int latencyResetEvent(char *event_to_reset) {
|
|||||||
* If the specified event has no elements the structure is populate with
|
* If the specified event has no elements the structure is populate with
|
||||||
* zero values. */
|
* zero values. */
|
||||||
void analyzeLatencyForEvent(char *event, struct latencyStats *ls) {
|
void analyzeLatencyForEvent(char *event, struct latencyStats *ls) {
|
||||||
struct latencyTimeSeries *ts = dictFetchValue(server.latency_events,event);
|
struct latencyTimeSeries *ts = (latencyTimeSeries*)dictFetchValue(server.latency_events,event);
|
||||||
int j;
|
int j;
|
||||||
uint64_t sum;
|
uint64_t sum;
|
||||||
|
|
||||||
@ -251,8 +251,8 @@ sds createLatencyReport(void) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(server.latency_events);
|
di = dictGetSafeIterator(server.latency_events);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
char *event = dictGetKey(de);
|
char *event = (char*)dictGetKey(de);
|
||||||
struct latencyTimeSeries *ts = dictGetVal(de);
|
struct latencyTimeSeries *ts = (latencyTimeSeries*)dictGetVal(de);
|
||||||
struct latencyStats ls;
|
struct latencyStats ls;
|
||||||
|
|
||||||
if (ts == NULL) continue;
|
if (ts == NULL) continue;
|
||||||
@ -273,7 +273,7 @@ sds createLatencyReport(void) {
|
|||||||
|
|
||||||
/* Fork */
|
/* Fork */
|
||||||
if (!strcasecmp(event,"fork")) {
|
if (!strcasecmp(event,"fork")) {
|
||||||
char *fork_quality;
|
const char *fork_quality;
|
||||||
if (server.stat_fork_rate < 10) {
|
if (server.stat_fork_rate < 10) {
|
||||||
fork_quality = "terrible";
|
fork_quality = "terrible";
|
||||||
advise_better_vm = 1;
|
advise_better_vm = 1;
|
||||||
@ -500,8 +500,8 @@ void latencyCommandReplyWithLatestEvents(client *c) {
|
|||||||
addReplyArrayLen(c,dictSize(server.latency_events));
|
addReplyArrayLen(c,dictSize(server.latency_events));
|
||||||
di = dictGetIterator(server.latency_events);
|
di = dictGetIterator(server.latency_events);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
char *event = dictGetKey(de);
|
char *event = (char*)dictGetKey(de);
|
||||||
struct latencyTimeSeries *ts = dictGetVal(de);
|
struct latencyTimeSeries *ts = (latencyTimeSeries*)dictGetVal(de);
|
||||||
int last = (ts->idx + LATENCY_TS_LEN - 1) % LATENCY_TS_LEN;
|
int last = (ts->idx + LATENCY_TS_LEN - 1) % LATENCY_TS_LEN;
|
||||||
|
|
||||||
addReplyArrayLen(c,4);
|
addReplyArrayLen(c,4);
|
||||||
@ -579,15 +579,15 @@ NULL
|
|||||||
};
|
};
|
||||||
struct latencyTimeSeries *ts;
|
struct latencyTimeSeries *ts;
|
||||||
|
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[1]),"history") && c->argc == 3) {
|
if (!strcasecmp(szFromObj(c->argv[1]),"history") && c->argc == 3) {
|
||||||
/* LATENCY HISTORY <event> */
|
/* LATENCY HISTORY <event> */
|
||||||
ts = dictFetchValue(server.latency_events,ptrFromObj(c->argv[2]));
|
ts = (latencyTimeSeries*)dictFetchValue(server.latency_events,ptrFromObj(c->argv[2]));
|
||||||
if (ts == NULL) {
|
if (ts == NULL) {
|
||||||
addReplyArrayLen(c,0);
|
addReplyArrayLen(c,0);
|
||||||
} else {
|
} else {
|
||||||
latencyCommandReplyWithSamples(c,ts);
|
latencyCommandReplyWithSamples(c,ts);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"graph") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"graph") && c->argc == 3) {
|
||||||
/* LATENCY GRAPH <event> */
|
/* LATENCY GRAPH <event> */
|
||||||
sds graph;
|
sds graph;
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
@ -595,22 +595,22 @@ NULL
|
|||||||
|
|
||||||
de = dictFind(server.latency_events,ptrFromObj(c->argv[2]));
|
de = dictFind(server.latency_events,ptrFromObj(c->argv[2]));
|
||||||
if (de == NULL) goto nodataerr;
|
if (de == NULL) goto nodataerr;
|
||||||
ts = dictGetVal(de);
|
ts = (latencyTimeSeries*)dictGetVal(de);
|
||||||
event = dictGetKey(de);
|
event = (char*)dictGetKey(de);
|
||||||
|
|
||||||
graph = latencyCommandGenSparkeline(event,ts);
|
graph = latencyCommandGenSparkeline(event,ts);
|
||||||
addReplyBulkCString(c,graph);
|
addReplyBulkCString(c,graph);
|
||||||
sdsfree(graph);
|
sdsfree(graph);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"latest") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"latest") && c->argc == 2) {
|
||||||
/* LATENCY LATEST */
|
/* LATENCY LATEST */
|
||||||
latencyCommandReplyWithLatestEvents(c);
|
latencyCommandReplyWithLatestEvents(c);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"doctor") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"doctor") && c->argc == 2) {
|
||||||
/* LATENCY DOCTOR */
|
/* LATENCY DOCTOR */
|
||||||
sds report = createLatencyReport();
|
sds report = createLatencyReport();
|
||||||
|
|
||||||
addReplyBulkCBuffer(c,report,sdslen(report));
|
addReplyBulkCBuffer(c,report,sdslen(report));
|
||||||
sdsfree(report);
|
sdsfree(report);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"reset") && c->argc >= 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"reset") && c->argc >= 2) {
|
||||||
/* LATENCY RESET */
|
/* LATENCY RESET */
|
||||||
if (c->argc == 2) {
|
if (c->argc == 2) {
|
||||||
addReplyLongLong(c,latencyResetEvent(NULL));
|
addReplyLongLong(c,latencyResetEvent(NULL));
|
||||||
@ -618,10 +618,10 @@ NULL
|
|||||||
int j, resets = 0;
|
int j, resets = 0;
|
||||||
|
|
||||||
for (j = 2; j < c->argc; j++)
|
for (j = 2; j < c->argc; j++)
|
||||||
resets += latencyResetEvent(ptrFromObj(c->argv[j]));
|
resets += latencyResetEvent(szFromObj(c->argv[j]));
|
||||||
addReplyLongLong(c,resets);
|
addReplyLongLong(c,resets);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"help") && c->argc >= 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"help") && c->argc >= 2) {
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else {
|
} else {
|
||||||
addReplySubcommandSyntaxError(c);
|
addReplySubcommandSyntaxError(c);
|
@ -30,16 +30,16 @@ size_t lazyfreeGetPendingObjectsCount(void) {
|
|||||||
* representing the list. */
|
* representing the list. */
|
||||||
size_t lazyfreeGetFreeEffort(robj *obj) {
|
size_t lazyfreeGetFreeEffort(robj *obj) {
|
||||||
if (obj->type == OBJ_LIST) {
|
if (obj->type == OBJ_LIST) {
|
||||||
quicklist *ql = ptrFromObj(obj);
|
quicklist *ql = (quicklist*)ptrFromObj(obj);
|
||||||
return ql->len;
|
return ql->len;
|
||||||
} else if (obj->type == OBJ_SET && obj->encoding == OBJ_ENCODING_HT) {
|
} else if (obj->type == OBJ_SET && obj->encoding == OBJ_ENCODING_HT) {
|
||||||
dict *ht = ptrFromObj(obj);
|
dict *ht = (dict*)ptrFromObj(obj);
|
||||||
return dictSize(ht);
|
return dictSize(ht);
|
||||||
} else if (obj->type == OBJ_ZSET && obj->encoding == OBJ_ENCODING_SKIPLIST){
|
} else if (obj->type == OBJ_ZSET && obj->encoding == OBJ_ENCODING_SKIPLIST){
|
||||||
zset *zs = ptrFromObj(obj);
|
zset *zs = (zset*)ptrFromObj(obj);
|
||||||
return zs->zsl->length;
|
return zs->zsl->length;
|
||||||
} else if (obj->type == OBJ_HASH && obj->encoding == OBJ_ENCODING_HT) {
|
} else if (obj->type == OBJ_HASH && obj->encoding == OBJ_ENCODING_HT) {
|
||||||
dict *ht = ptrFromObj(obj);
|
dict *ht = (dict*)ptrFromObj(obj);
|
||||||
return dictSize(ht);
|
return dictSize(ht);
|
||||||
} else {
|
} else {
|
||||||
return 1; /* Everything else is a single allocation. */
|
return 1; /* Everything else is a single allocation. */
|
||||||
@ -61,7 +61,7 @@ int dbAsyncDelete(redisDb *db, robj *key) {
|
|||||||
* the object synchronously. */
|
* the object synchronously. */
|
||||||
dictEntry *de = dictUnlink(db->pdict,ptrFromObj(key));
|
dictEntry *de = dictUnlink(db->pdict,ptrFromObj(key));
|
||||||
if (de) {
|
if (de) {
|
||||||
robj *val = dictGetVal(de);
|
robj *val = (robj*)dictGetVal(de);
|
||||||
size_t free_effort = lazyfreeGetFreeEffort(val);
|
size_t free_effort = lazyfreeGetFreeEffort(val);
|
||||||
|
|
||||||
/* If releasing the object is too much work, do it in the background
|
/* If releasing the object is too much work, do it in the background
|
56
src/lolwut.c
56
src/lolwut.c
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* This file implements the LOLWUT command. The command should do something
|
|
||||||
* fun and interesting, and should be replaced by a new implementation at
|
|
||||||
* each new version of Redis.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "server.h"
|
|
||||||
|
|
||||||
void lolwut5Command(client *c);
|
|
||||||
|
|
||||||
/* The default target for LOLWUT if no matching version was found.
|
|
||||||
* This is what unstable versions of Redis will display. */
|
|
||||||
void lolwutUnstableCommand(client *c) {
|
|
||||||
sds rendered = sdsnew("Redis ver. ");
|
|
||||||
rendered = sdscat(rendered,REDIS_VERSION);
|
|
||||||
rendered = sdscatlen(rendered,"\n",1);
|
|
||||||
addReplyBulkSds(c,rendered);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lolwutCommand(client *c) {
|
|
||||||
char *v = REDIS_VERSION;
|
|
||||||
if ((v[0] == '5' && v[1] == '.') ||
|
|
||||||
(v[0] == '4' && v[1] == '.' && v[2] == '9'))
|
|
||||||
lolwut5Command(c);
|
|
||||||
else
|
|
||||||
lolwutUnstableCommand(c);
|
|
||||||
}
|
|
282
src/lolwut5.c
282
src/lolwut5.c
@ -1,282 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* This file implements the LOLWUT command. The command should do something
|
|
||||||
* fun and interesting, and should be replaced by a new implementation at
|
|
||||||
* each new version of Redis.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "server.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
/* This structure represents our canvas. Drawing functions will take a pointer
|
|
||||||
* to a canvas to write to it. Later the canvas can be rendered to a string
|
|
||||||
* suitable to be printed on the screen, using unicode Braille characters. */
|
|
||||||
typedef struct lwCanvas {
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
char *pixels;
|
|
||||||
} lwCanvas;
|
|
||||||
|
|
||||||
/* Translate a group of 8 pixels (2x4 vertical rectangle) to the corresponding
|
|
||||||
* braille character. The byte should correspond to the pixels arranged as
|
|
||||||
* follows, where 0 is the least significant bit, and 7 the most significant
|
|
||||||
* bit:
|
|
||||||
*
|
|
||||||
* 0 3
|
|
||||||
* 1 4
|
|
||||||
* 2 5
|
|
||||||
* 6 7
|
|
||||||
*
|
|
||||||
* The corresponding utf8 encoded character is set into the three bytes
|
|
||||||
* pointed by 'output'.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
void lwTranslatePixelsGroup(int byte, char *output) {
|
|
||||||
int code = 0x2800 + byte;
|
|
||||||
/* Convert to unicode. This is in the U0800-UFFFF range, so we need to
|
|
||||||
* emit it like this in three bytes:
|
|
||||||
* 1110xxxx 10xxxxxx 10xxxxxx. */
|
|
||||||
output[0] = 0xE0 | (code >> 12); /* 1110-xxxx */
|
|
||||||
output[1] = 0x80 | ((code >> 6) & 0x3F); /* 10-xxxxxx */
|
|
||||||
output[2] = 0x80 | (code & 0x3F); /* 10-xxxxxx */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate and return a new canvas of the specified size. */
|
|
||||||
lwCanvas *lwCreateCanvas(int width, int height) {
|
|
||||||
lwCanvas *canvas = zmalloc(sizeof(*canvas), MALLOC_SHARED);
|
|
||||||
canvas->width = width;
|
|
||||||
canvas->height = height;
|
|
||||||
canvas->pixels = zmalloc(width*height, MALLOC_SHARED);
|
|
||||||
memset(canvas->pixels,0,width*height);
|
|
||||||
return canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the canvas created by lwCreateCanvas(). */
|
|
||||||
void lwFreeCanvas(lwCanvas *canvas) {
|
|
||||||
zfree(canvas->pixels);
|
|
||||||
zfree(canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a pixel to the specified color. Color is 0 or 1, where zero means no
|
|
||||||
* dot will be displyed, and 1 means dot will be displayed.
|
|
||||||
* Coordinates are arranged so that left-top corner is 0,0. You can write
|
|
||||||
* out of the size of the canvas without issues. */
|
|
||||||
void lwDrawPixel(lwCanvas *canvas, int x, int y, int color) {
|
|
||||||
if (x < 0 || x >= canvas->width ||
|
|
||||||
y < 0 || y >= canvas->height) return;
|
|
||||||
canvas->pixels[x+y*canvas->width] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the value of the specified pixel on the canvas. */
|
|
||||||
int lwGetPixel(lwCanvas *canvas, int x, int y) {
|
|
||||||
if (x < 0 || x >= canvas->width ||
|
|
||||||
y < 0 || y >= canvas->height) return 0;
|
|
||||||
return canvas->pixels[x+y*canvas->width];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw a line from x1,y1 to x2,y2 using the Bresenham algorithm. */
|
|
||||||
void lwDrawLine(lwCanvas *canvas, int x1, int y1, int x2, int y2, int color) {
|
|
||||||
int dx = abs(x2-x1);
|
|
||||||
int dy = abs(y2-y1);
|
|
||||||
int sx = (x1 < x2) ? 1 : -1;
|
|
||||||
int sy = (y1 < y2) ? 1 : -1;
|
|
||||||
int err = dx-dy, e2;
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
lwDrawPixel(canvas,x1,y1,color);
|
|
||||||
if (x1 == x2 && y1 == y2) break;
|
|
||||||
e2 = err*2;
|
|
||||||
if (e2 > -dy) {
|
|
||||||
err -= dy;
|
|
||||||
x1 += sx;
|
|
||||||
}
|
|
||||||
if (e2 < dx) {
|
|
||||||
err += dx;
|
|
||||||
y1 += sy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw a square centered at the specified x,y coordinates, with the specified
|
|
||||||
* rotation angle and size. In order to write a rotated square, we use the
|
|
||||||
* trivial fact that the parametric equation:
|
|
||||||
*
|
|
||||||
* x = sin(k)
|
|
||||||
* y = cos(k)
|
|
||||||
*
|
|
||||||
* Describes a circle for values going from 0 to 2*PI. So basically if we start
|
|
||||||
* at 45 degrees, that is k = PI/4, with the first point, and then we find
|
|
||||||
* the other three points incrementing K by PI/2 (90 degrees), we'll have the
|
|
||||||
* points of the square. In order to rotate the square, we just start with
|
|
||||||
* k = PI/4 + rotation_angle, and we are done.
|
|
||||||
*
|
|
||||||
* Of course the vanilla equations above will describe the square inside a
|
|
||||||
* circle of radius 1, so in order to draw larger squares we'll have to
|
|
||||||
* multiply the obtained coordinates, and then translate them. However this
|
|
||||||
* is much simpler than implementing the abstract concept of 2D shape and then
|
|
||||||
* performing the rotation/translation transformation, so for LOLWUT it's
|
|
||||||
* a good approach. */
|
|
||||||
void lwDrawSquare(lwCanvas *canvas, int x, int y, float size, float angle) {
|
|
||||||
int px[4], py[4];
|
|
||||||
|
|
||||||
/* Adjust the desired size according to the fact that the square inscribed
|
|
||||||
* into a circle of radius 1 has the side of length SQRT(2). This way
|
|
||||||
* size becomes a simple multiplication factor we can use with our
|
|
||||||
* coordinates to magnify them. */
|
|
||||||
size /= 1.4142135623;
|
|
||||||
size = round(size);
|
|
||||||
|
|
||||||
/* Compute the four points. */
|
|
||||||
float k = M_PI/4 + angle;
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
px[j] = round(sin(k) * size + x);
|
|
||||||
py[j] = round(cos(k) * size + y);
|
|
||||||
k += M_PI/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw the square. */
|
|
||||||
for (int j = 0; j < 4; j++)
|
|
||||||
lwDrawLine(canvas,px[j],py[j],px[(j+1)%4],py[(j+1)%4],1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Schotter, the output of LOLWUT of Redis 5, is a computer graphic art piece
|
|
||||||
* generated by Georg Nees in the 60s. It explores the relationship between
|
|
||||||
* caos and order.
|
|
||||||
*
|
|
||||||
* The function creates the canvas itself, depending on the columns available
|
|
||||||
* in the output display and the number of squares per row and per column
|
|
||||||
* requested by the caller. */
|
|
||||||
lwCanvas *lwDrawSchotter(int console_cols, int squares_per_row, int squares_per_col) {
|
|
||||||
/* Calculate the canvas size. */
|
|
||||||
int canvas_width = console_cols*2;
|
|
||||||
int padding = canvas_width > 4 ? 2 : 0;
|
|
||||||
float square_side = (float)(canvas_width-padding*2) / squares_per_row;
|
|
||||||
int canvas_height = square_side * squares_per_col + padding*2;
|
|
||||||
lwCanvas *canvas = lwCreateCanvas(canvas_width, canvas_height);
|
|
||||||
|
|
||||||
for (int y = 0; y < squares_per_col; y++) {
|
|
||||||
for (int x = 0; x < squares_per_row; x++) {
|
|
||||||
int sx = x * square_side + square_side/2 + padding;
|
|
||||||
int sy = y * square_side + square_side/2 + padding;
|
|
||||||
/* Rotate and translate randomly as we go down to lower
|
|
||||||
* rows. */
|
|
||||||
float angle = 0;
|
|
||||||
if (y > 1) {
|
|
||||||
float r1 = (float)rand() / RAND_MAX / squares_per_col * y;
|
|
||||||
float r2 = (float)rand() / RAND_MAX / squares_per_col * y;
|
|
||||||
float r3 = (float)rand() / RAND_MAX / squares_per_col * y;
|
|
||||||
if (rand() % 2) r1 = -r1;
|
|
||||||
if (rand() % 2) r2 = -r2;
|
|
||||||
if (rand() % 2) r3 = -r3;
|
|
||||||
angle = r1;
|
|
||||||
sx += r2*square_side/3;
|
|
||||||
sy += r3*square_side/3;
|
|
||||||
}
|
|
||||||
lwDrawSquare(canvas,sx,sy,square_side,angle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Converts the canvas to an SDS string representing the UTF8 characters to
|
|
||||||
* print to the terminal in order to obtain a graphical representaiton of the
|
|
||||||
* logical canvas. The actual returned string will require a terminal that is
|
|
||||||
* width/2 large and height/4 tall in order to hold the whole image without
|
|
||||||
* overflowing or scrolling, since each Barille character is 2x4. */
|
|
||||||
sds lwRenderCanvas(lwCanvas *canvas) {
|
|
||||||
sds text = sdsempty();
|
|
||||||
for (int y = 0; y < canvas->height; y += 4) {
|
|
||||||
for (int x = 0; x < canvas->width; x += 2) {
|
|
||||||
/* We need to emit groups of 8 bits according to a specific
|
|
||||||
* arrangement. See lwTranslatePixelsGroup() for more info. */
|
|
||||||
int byte = 0;
|
|
||||||
if (lwGetPixel(canvas,x,y)) byte |= (1<<0);
|
|
||||||
if (lwGetPixel(canvas,x,y+1)) byte |= (1<<1);
|
|
||||||
if (lwGetPixel(canvas,x,y+2)) byte |= (1<<2);
|
|
||||||
if (lwGetPixel(canvas,x+1,y)) byte |= (1<<3);
|
|
||||||
if (lwGetPixel(canvas,x+1,y+1)) byte |= (1<<4);
|
|
||||||
if (lwGetPixel(canvas,x+1,y+2)) byte |= (1<<5);
|
|
||||||
if (lwGetPixel(canvas,x,y+3)) byte |= (1<<6);
|
|
||||||
if (lwGetPixel(canvas,x+1,y+3)) byte |= (1<<7);
|
|
||||||
char unicode[3];
|
|
||||||
lwTranslatePixelsGroup(byte,unicode);
|
|
||||||
text = sdscatlen(text,unicode,3);
|
|
||||||
}
|
|
||||||
if (y != canvas->height-1) text = sdscatlen(text,"\n",1);
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The LOLWUT command:
|
|
||||||
*
|
|
||||||
* LOLWUT [terminal columns] [squares-per-row] [squares-per-col]
|
|
||||||
*
|
|
||||||
* By default the command uses 66 columns, 8 squares per row, 12 squares
|
|
||||||
* per column.
|
|
||||||
*/
|
|
||||||
void lolwut5Command(client *c) {
|
|
||||||
long cols = 66;
|
|
||||||
long squares_per_row = 8;
|
|
||||||
long squares_per_col = 12;
|
|
||||||
|
|
||||||
/* Parse the optional arguments if any. */
|
|
||||||
if (c->argc > 1 &&
|
|
||||||
getLongFromObjectOrReply(c,c->argv[1],&cols,NULL) != C_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (c->argc > 2 &&
|
|
||||||
getLongFromObjectOrReply(c,c->argv[2],&squares_per_row,NULL) != C_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (c->argc > 3 &&
|
|
||||||
getLongFromObjectOrReply(c,c->argv[3],&squares_per_col,NULL) != C_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Limits. We want LOLWUT to be always reasonably fast and cheap to execute
|
|
||||||
* so we have maximum number of columns, rows, and output resulution. */
|
|
||||||
if (cols < 1) cols = 1;
|
|
||||||
if (cols > 1000) cols = 1000;
|
|
||||||
if (squares_per_row < 1) squares_per_row = 1;
|
|
||||||
if (squares_per_row > 200) squares_per_row = 200;
|
|
||||||
if (squares_per_col < 1) squares_per_col = 1;
|
|
||||||
if (squares_per_col > 200) squares_per_col = 200;
|
|
||||||
|
|
||||||
/* Generate some computer art and reply. */
|
|
||||||
lwCanvas *canvas = lwDrawSchotter(cols,squares_per_row,squares_per_col);
|
|
||||||
sds rendered = lwRenderCanvas(canvas);
|
|
||||||
rendered = sdscat(rendered,
|
|
||||||
"\nGeorg Nees - schotter, plotter on paper, 1968. Redis ver. ");
|
|
||||||
rendered = sdscat(rendered,REDIS_VERSION);
|
|
||||||
rendered = sdscatlen(rendered,"\n",1);
|
|
||||||
addReplyBulkSds(c,rendered);
|
|
||||||
lwFreeCanvas(canvas);
|
|
||||||
}
|
|
@ -48,6 +48,10 @@
|
|||||||
|
|
||||||
#define LZF_VERSION 0x0105 /* 1.5, API version */
|
#define LZF_VERSION 0x0105 /* 1.5, API version */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compress in_len bytes stored at the memory block starting at
|
* Compress in_len bytes stored at the memory block starting at
|
||||||
* in_data and write the result to out_data, up to a maximum length
|
* in_data and write the result to out_data, up to a maximum length
|
||||||
@ -96,5 +100,9 @@ unsigned int
|
|||||||
lzf_decompress (const void *const in_data, unsigned int in_len,
|
lzf_decompress (const void *const in_data, unsigned int in_len,
|
||||||
void *out_data, unsigned int out_len);
|
void *out_data, unsigned int out_len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -58,12 +58,12 @@ void queueMultiCommand(client *c) {
|
|||||||
multiCmd *mc;
|
multiCmd *mc;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
c->mstate.commands = zrealloc(c->mstate.commands,
|
c->mstate.commands = (multiCmd*)zrealloc(c->mstate.commands,
|
||||||
sizeof(multiCmd)*(c->mstate.count+1), MALLOC_LOCAL);
|
sizeof(multiCmd)*(c->mstate.count+1), MALLOC_LOCAL);
|
||||||
mc = c->mstate.commands+c->mstate.count;
|
mc = c->mstate.commands+c->mstate.count;
|
||||||
mc->cmd = c->cmd;
|
mc->cmd = c->cmd;
|
||||||
mc->argc = c->argc;
|
mc->argc = c->argc;
|
||||||
mc->argv = zmalloc(sizeof(robj*)*c->argc, MALLOC_LOCAL);
|
mc->argv = (robj**)zmalloc(sizeof(robj*)*c->argc, MALLOC_LOCAL);
|
||||||
memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);
|
memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);
|
||||||
for (j = 0; j < c->argc; j++)
|
for (j = 0; j < c->argc; j++)
|
||||||
incrRefCount(mc->argv[j]);
|
incrRefCount(mc->argv[j]);
|
||||||
@ -201,7 +201,7 @@ void execCommand(client *c) {
|
|||||||
* rest was not. We need to make sure to at least terminate the
|
* rest was not. We need to make sure to at least terminate the
|
||||||
* backlog with the final EXEC. */
|
* backlog with the final EXEC. */
|
||||||
if (server.repl_backlog && was_master && !is_master) {
|
if (server.repl_backlog && was_master && !is_master) {
|
||||||
char *execcmd = "*1\r\n$4\r\nEXEC\r\n";
|
const char *execcmd = "*1\r\n$4\r\nEXEC\r\n";
|
||||||
feedReplicationBacklog(execcmd,strlen(execcmd));
|
feedReplicationBacklog(execcmd,strlen(execcmd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,12 +243,12 @@ void watchForKey(client *c, robj *key) {
|
|||||||
/* Check if we are already watching for this key */
|
/* Check if we are already watching for this key */
|
||||||
listRewind(c->watched_keys,&li);
|
listRewind(c->watched_keys,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
wk = listNodeValue(ln);
|
wk = (watchedKey*)listNodeValue(ln);
|
||||||
if (wk->db == c->db && equalStringObjects(key,wk->key))
|
if (wk->db == c->db && equalStringObjects(key,wk->key))
|
||||||
return; /* Key already watched */
|
return; /* Key already watched */
|
||||||
}
|
}
|
||||||
/* This key is not already watched in this DB. Let's add it */
|
/* This key is not already watched in this DB. Let's add it */
|
||||||
clients = dictFetchValue(c->db->watched_keys,key);
|
clients = (decltype(clients)) dictFetchValue(c->db->watched_keys,key);
|
||||||
if (!clients) {
|
if (!clients) {
|
||||||
clients = listCreate();
|
clients = listCreate();
|
||||||
dictAdd(c->db->watched_keys,key,clients);
|
dictAdd(c->db->watched_keys,key,clients);
|
||||||
@ -256,7 +256,7 @@ void watchForKey(client *c, robj *key) {
|
|||||||
}
|
}
|
||||||
listAddNodeTail(clients,c);
|
listAddNodeTail(clients,c);
|
||||||
/* Add the new key to the list of keys watched by this client */
|
/* Add the new key to the list of keys watched by this client */
|
||||||
wk = zmalloc(sizeof(*wk), MALLOC_SHARED);
|
wk = (watchedKey*)zmalloc(sizeof(*wk), MALLOC_SHARED);
|
||||||
wk->key = key;
|
wk->key = key;
|
||||||
wk->db = c->db;
|
wk->db = c->db;
|
||||||
incrRefCount(key);
|
incrRefCount(key);
|
||||||
@ -277,8 +277,8 @@ void unwatchAllKeys(client *c) {
|
|||||||
|
|
||||||
/* Lookup the watched key -> clients list and remove the client
|
/* Lookup the watched key -> clients list and remove the client
|
||||||
* from the list */
|
* from the list */
|
||||||
wk = listNodeValue(ln);
|
wk = (watchedKey*)listNodeValue(ln);
|
||||||
clients = dictFetchValue(wk->db->watched_keys, wk->key);
|
clients = (decltype(clients))dictFetchValue(wk->db->watched_keys, wk->key);
|
||||||
serverAssertWithInfo(c,NULL,clients != NULL);
|
serverAssertWithInfo(c,NULL,clients != NULL);
|
||||||
listDelNode(clients,listSearchKey(clients,c));
|
listDelNode(clients,listSearchKey(clients,c));
|
||||||
/* Kill the entry at all if this was the only client */
|
/* Kill the entry at all if this was the only client */
|
||||||
@ -300,14 +300,14 @@ void touchWatchedKey(redisDb *db, robj *key) {
|
|||||||
listNode *ln;
|
listNode *ln;
|
||||||
|
|
||||||
if (dictSize(db->watched_keys) == 0) return;
|
if (dictSize(db->watched_keys) == 0) return;
|
||||||
clients = dictFetchValue(db->watched_keys, key);
|
clients = (list*)dictFetchValue(db->watched_keys, key);
|
||||||
if (!clients) return;
|
if (!clients) return;
|
||||||
|
|
||||||
/* Mark all the clients watching this key as CLIENT_DIRTY_CAS */
|
/* Mark all the clients watching this key as CLIENT_DIRTY_CAS */
|
||||||
/* Check if we are already watching for this key */
|
/* Check if we are already watching for this key */
|
||||||
listRewind(clients,&li);
|
listRewind(clients,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *c = listNodeValue(ln);
|
client *c = (client*)listNodeValue(ln);
|
||||||
|
|
||||||
c->flags |= CLIENT_DIRTY_CAS;
|
c->flags |= CLIENT_DIRTY_CAS;
|
||||||
}
|
}
|
||||||
@ -325,10 +325,10 @@ void touchWatchedKeysOnFlush(int dbid) {
|
|||||||
/* For every client, check all the waited keys */
|
/* For every client, check all the waited keys */
|
||||||
listRewind(server.clients,&li1);
|
listRewind(server.clients,&li1);
|
||||||
while((ln = listNext(&li1))) {
|
while((ln = listNext(&li1))) {
|
||||||
client *c = listNodeValue(ln);
|
client *c = (client*)listNodeValue(ln);
|
||||||
listRewind(c->watched_keys,&li2);
|
listRewind(c->watched_keys,&li2);
|
||||||
while((ln = listNext(&li2))) {
|
while((ln = listNext(&li2))) {
|
||||||
watchedKey *wk = listNodeValue(ln);
|
watchedKey *wk = (watchedKey*)listNodeValue(ln);
|
||||||
|
|
||||||
/* For every watched key matching the specified DB, if the
|
/* For every watched key matching the specified DB, if the
|
||||||
* key exists, mark the client as dirty, as the key will be
|
* key exists, mark the client as dirty, as the key will be
|
@ -1991,17 +1991,6 @@ void processInputBuffer(client *c, int callFlags) {
|
|||||||
|
|
||||||
if (c->reqtype == PROTO_REQ_INLINE) {
|
if (c->reqtype == PROTO_REQ_INLINE) {
|
||||||
if (processInlineBuffer(c) != C_OK) break;
|
if (processInlineBuffer(c) != C_OK) break;
|
||||||
/* If the Gopher mode and we got zero or one argument, process
|
|
||||||
* the request in Gopher mode. */
|
|
||||||
if (server.gopher_enabled &&
|
|
||||||
((c->argc == 1 && ((char*)(ptrFromObj(c->argv[0])))[0] == '/') ||
|
|
||||||
c->argc == 0))
|
|
||||||
{
|
|
||||||
processGopherRequest(c);
|
|
||||||
resetClient(c);
|
|
||||||
c->flags |= CLIENT_CLOSE_AFTER_REPLY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (c->reqtype == PROTO_REQ_MULTIBULK) {
|
} else if (c->reqtype == PROTO_REQ_MULTIBULK) {
|
||||||
if (processMultibulkBuffer(c) != C_OK) break;
|
if (processMultibulkBuffer(c) != C_OK) break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -119,7 +119,7 @@ void notifyKeyspaceEvent(int type, const char *event, robj *key, int dbid) {
|
|||||||
len = ll2string(buf,sizeof(buf),dbid);
|
len = ll2string(buf,sizeof(buf),dbid);
|
||||||
chan = sdscatlen(chan, buf, len);
|
chan = sdscatlen(chan, buf, len);
|
||||||
chan = sdscatlen(chan, "__:", 3);
|
chan = sdscatlen(chan, "__:", 3);
|
||||||
chan = sdscatsds(chan, ptrFromObj(key));
|
chan = sdscatsds(chan, szFromObj(key));
|
||||||
chanobj = createObject(OBJ_STRING, chan);
|
chanobj = createObject(OBJ_STRING, chan);
|
||||||
pubsubPublishMessage(chanobj, eventobj);
|
pubsubPublishMessage(chanobj, eventobj);
|
||||||
decrRefCount(chanobj);
|
decrRefCount(chanobj);
|
||||||
@ -131,7 +131,7 @@ void notifyKeyspaceEvent(int type, const char *event, robj *key, int dbid) {
|
|||||||
if (len == -1) len = ll2string(buf,sizeof(buf),dbid);
|
if (len == -1) len = ll2string(buf,sizeof(buf),dbid);
|
||||||
chan = sdscatlen(chan, buf, len);
|
chan = sdscatlen(chan, buf, len);
|
||||||
chan = sdscatlen(chan, "__:", 3);
|
chan = sdscatlen(chan, "__:", 3);
|
||||||
chan = sdscatsds(chan, ptrFromObj(eventobj));
|
chan = sdscatsds(chan, szFromObj(eventobj));
|
||||||
chanobj = createObject(OBJ_STRING, chan);
|
chanobj = createObject(OBJ_STRING, chan);
|
||||||
pubsubPublishMessage(chanobj, key);
|
pubsubPublishMessage(chanobj, key);
|
||||||
decrRefCount(chanobj);
|
decrRefCount(chanobj);
|
@ -39,7 +39,7 @@
|
|||||||
/* ===================== Creation and parsing of objects ==================== */
|
/* ===================== Creation and parsing of objects ==================== */
|
||||||
|
|
||||||
robj *createObject(int type, void *ptr) {
|
robj *createObject(int type, void *ptr) {
|
||||||
robj *o = zmalloc(sizeof(*o), MALLOC_SHARED);
|
robj *o = (robj*)zmalloc(sizeof(*o), MALLOC_SHARED);
|
||||||
o->type = type;
|
o->type = type;
|
||||||
o->encoding = OBJ_ENCODING_RAW;
|
o->encoding = OBJ_ENCODING_RAW;
|
||||||
o->m_ptr = ptr;
|
o->m_ptr = ptr;
|
||||||
@ -85,8 +85,8 @@ robj *createEmbeddedStringObject(const char *ptr, size_t len) {
|
|||||||
size_t allocsize = sizeof(struct sdshdr8)+len+1;
|
size_t allocsize = sizeof(struct sdshdr8)+len+1;
|
||||||
if (allocsize < sizeof(void*))
|
if (allocsize < sizeof(void*))
|
||||||
allocsize = sizeof(void*);
|
allocsize = sizeof(void*);
|
||||||
robj *o = zmalloc(sizeof(robj)+allocsize-sizeof(o->m_ptr), MALLOC_SHARED);
|
robj *o = (robj*)zmalloc(sizeof(robj)+allocsize-sizeof(o->m_ptr), MALLOC_SHARED);
|
||||||
struct sdshdr8 *sh = (void*)(&o->m_ptr);
|
struct sdshdr8 *sh = (sdshdr8*)(&o->m_ptr);
|
||||||
|
|
||||||
o->type = OBJ_STRING;
|
o->type = OBJ_STRING;
|
||||||
o->encoding = OBJ_ENCODING_EMBSTR;
|
o->encoding = OBJ_ENCODING_EMBSTR;
|
||||||
@ -101,12 +101,12 @@ robj *createEmbeddedStringObject(const char *ptr, size_t len) {
|
|||||||
sh->alloc = len;
|
sh->alloc = len;
|
||||||
sh->flags = SDS_TYPE_8;
|
sh->flags = SDS_TYPE_8;
|
||||||
if (ptr == SDS_NOINIT)
|
if (ptr == SDS_NOINIT)
|
||||||
sh->buf[len] = '\0';
|
sh->buf()[len] = '\0';
|
||||||
else if (ptr) {
|
else if (ptr) {
|
||||||
memcpy(sh->buf,ptr,len);
|
memcpy(sh->buf(),ptr,len);
|
||||||
sh->buf[len] = '\0';
|
sh->buf()[len] = '\0';
|
||||||
} else {
|
} else {
|
||||||
memset(sh->buf,0,len+1);
|
memset(sh->buf(),0,len+1);
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -199,9 +199,9 @@ robj *dupStringObject(const robj *o) {
|
|||||||
|
|
||||||
switch(o->encoding) {
|
switch(o->encoding) {
|
||||||
case OBJ_ENCODING_RAW:
|
case OBJ_ENCODING_RAW:
|
||||||
return createRawStringObject(ptrFromObj(o),sdslen(ptrFromObj(o)));
|
return createRawStringObject(szFromObj(o),sdslen(szFromObj(o)));
|
||||||
case OBJ_ENCODING_EMBSTR:
|
case OBJ_ENCODING_EMBSTR:
|
||||||
return createEmbeddedStringObject(ptrFromObj(o),sdslen(ptrFromObj(o)));
|
return createEmbeddedStringObject(szFromObj(o),sdslen(szFromObj(o)));
|
||||||
case OBJ_ENCODING_INT:
|
case OBJ_ENCODING_INT:
|
||||||
d = createObject(OBJ_STRING, NULL);
|
d = createObject(OBJ_STRING, NULL);
|
||||||
d->encoding = OBJ_ENCODING_INT;
|
d->encoding = OBJ_ENCODING_INT;
|
||||||
@ -249,7 +249,7 @@ robj *createHashObject(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
robj *createZsetObject(void) {
|
robj *createZsetObject(void) {
|
||||||
zset *zs = zmalloc(sizeof(*zs), MALLOC_SHARED);
|
zset *zs = (zset*)zmalloc(sizeof(*zs), MALLOC_SHARED);
|
||||||
robj *o;
|
robj *o;
|
||||||
|
|
||||||
zs->pdict = dictCreate(&zsetDictType,NULL);
|
zs->pdict = dictCreate(&zsetDictType,NULL);
|
||||||
@ -274,7 +274,7 @@ robj *createStreamObject(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
robj *createModuleObject(moduleType *mt, void *value) {
|
robj *createModuleObject(moduleType *mt, void *value) {
|
||||||
moduleValue *mv = zmalloc(sizeof(*mv), MALLOC_SHARED);
|
moduleValue *mv = (moduleValue*)zmalloc(sizeof(*mv), MALLOC_SHARED);
|
||||||
mv->type = mt;
|
mv->type = mt;
|
||||||
mv->value = value;
|
mv->value = value;
|
||||||
return createObject(OBJ_MODULE,mv);
|
return createObject(OBJ_MODULE,mv);
|
||||||
@ -282,13 +282,13 @@ robj *createModuleObject(moduleType *mt, void *value) {
|
|||||||
|
|
||||||
void freeStringObject(robj *o) {
|
void freeStringObject(robj *o) {
|
||||||
if (o->encoding == OBJ_ENCODING_RAW) {
|
if (o->encoding == OBJ_ENCODING_RAW) {
|
||||||
sdsfree(ptrFromObj(o));
|
sdsfree(szFromObj(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeListObject(robj *o) {
|
void freeListObject(robj *o) {
|
||||||
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||||
quicklistRelease(ptrFromObj(o));
|
quicklistRelease((quicklist*)ptrFromObj(o));
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown list encoding type");
|
serverPanic("Unknown list encoding type");
|
||||||
}
|
}
|
||||||
@ -311,7 +311,7 @@ void freeZsetObject(robj *o) {
|
|||||||
zset *zs;
|
zset *zs;
|
||||||
switch (o->encoding) {
|
switch (o->encoding) {
|
||||||
case OBJ_ENCODING_SKIPLIST:
|
case OBJ_ENCODING_SKIPLIST:
|
||||||
zs = ptrFromObj(o);
|
zs = (zset*)ptrFromObj(o);
|
||||||
dictRelease(zs->pdict);
|
dictRelease(zs->pdict);
|
||||||
zslFree(zs->zsl);
|
zslFree(zs->zsl);
|
||||||
zfree(zs);
|
zfree(zs);
|
||||||
@ -339,13 +339,13 @@ void freeHashObject(robj *o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void freeModuleObject(robj *o) {
|
void freeModuleObject(robj *o) {
|
||||||
moduleValue *mv = ptrFromObj(o);
|
moduleValue *mv = (moduleValue*)ptrFromObj(o);
|
||||||
mv->type->free(mv->value);
|
mv->type->free(mv->value);
|
||||||
zfree(mv);
|
zfree(mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeStreamObject(robj *o) {
|
void freeStreamObject(robj *o) {
|
||||||
freeStream(ptrFromObj(o));
|
freeStream((stream*)ptrFromObj(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
void incrRefCount(robj *o) {
|
void incrRefCount(robj *o) {
|
||||||
@ -375,7 +375,7 @@ void decrRefCount(robj *o) {
|
|||||||
* as free method in data structures that expect a 'void free_object(void*)'
|
* as free method in data structures that expect a 'void free_object(void*)'
|
||||||
* prototype for the free method. */
|
* prototype for the free method. */
|
||||||
void decrRefCountVoid(void *o) {
|
void decrRefCountVoid(void *o) {
|
||||||
decrRefCount(o);
|
decrRefCount((robj*)o);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function set the ref count to zero without freeing the object.
|
/* This function set the ref count to zero without freeing the object.
|
||||||
@ -413,7 +413,7 @@ int isObjectRepresentableAsLongLong(robj *o, long long *llval) {
|
|||||||
if (llval) *llval = (long) ptrFromObj(o);
|
if (llval) *llval = (long) ptrFromObj(o);
|
||||||
return C_OK;
|
return C_OK;
|
||||||
} else {
|
} else {
|
||||||
return isSdsRepresentableAsLongLong(ptrFromObj(o),llval);
|
return isSdsRepresentableAsLongLong(szFromObj(o),llval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,16 +423,16 @@ int isObjectRepresentableAsLongLong(robj *o, long long *llval) {
|
|||||||
* wasting too much time in allocations when appending to the string. */
|
* wasting too much time in allocations when appending to the string. */
|
||||||
void trimStringObjectIfNeeded(robj *o) {
|
void trimStringObjectIfNeeded(robj *o) {
|
||||||
if (o->encoding == OBJ_ENCODING_RAW &&
|
if (o->encoding == OBJ_ENCODING_RAW &&
|
||||||
sdsavail(ptrFromObj(o)) > sdslen(ptrFromObj(o))/10)
|
sdsavail(szFromObj(o)) > sdslen(szFromObj(o))/10)
|
||||||
{
|
{
|
||||||
o->m_ptr = sdsRemoveFreeSpace(ptrFromObj(o));
|
o->m_ptr = sdsRemoveFreeSpace(szFromObj(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to encode a string object in order to save space */
|
/* Try to encode a string object in order to save space */
|
||||||
robj *tryObjectEncoding(robj *o) {
|
robj *tryObjectEncoding(robj *o) {
|
||||||
long value;
|
long value;
|
||||||
sds s = ptrFromObj(o);
|
sds s = szFromObj(o);
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Make sure this is a string object, the only type we encode
|
/* Make sure this is a string object, the only type we encode
|
||||||
@ -469,7 +469,7 @@ robj *tryObjectEncoding(robj *o) {
|
|||||||
incrRefCount(shared.integers[value]);
|
incrRefCount(shared.integers[value]);
|
||||||
return shared.integers[value];
|
return shared.integers[value];
|
||||||
} else {
|
} else {
|
||||||
if (o->encoding == OBJ_ENCODING_RAW) sdsfree(ptrFromObj(o));
|
if (o->encoding == OBJ_ENCODING_RAW) sdsfree(szFromObj(o));
|
||||||
o->encoding = OBJ_ENCODING_INT;
|
o->encoding = OBJ_ENCODING_INT;
|
||||||
o->m_ptr = (void*) value;
|
o->m_ptr = (void*) value;
|
||||||
return o;
|
return o;
|
||||||
@ -542,14 +542,14 @@ int compareStringObjectsWithFlags(robj *a, robj *b, int flags) {
|
|||||||
|
|
||||||
if (a == b) return 0;
|
if (a == b) return 0;
|
||||||
if (sdsEncodedObject(a)) {
|
if (sdsEncodedObject(a)) {
|
||||||
astr = ptrFromObj(a);
|
astr = szFromObj(a);
|
||||||
alen = sdslen(astr);
|
alen = sdslen(astr);
|
||||||
} else {
|
} else {
|
||||||
alen = ll2string(bufa,sizeof(bufa),(long) ptrFromObj(a));
|
alen = ll2string(bufa,sizeof(bufa),(long) ptrFromObj(a));
|
||||||
astr = bufa;
|
astr = bufa;
|
||||||
}
|
}
|
||||||
if (sdsEncodedObject(b)) {
|
if (sdsEncodedObject(b)) {
|
||||||
bstr = ptrFromObj(b);
|
bstr = szFromObj(b);
|
||||||
blen = sdslen(bstr);
|
blen = sdslen(bstr);
|
||||||
} else {
|
} else {
|
||||||
blen = ll2string(bufb,sizeof(bufb),(long) ptrFromObj(b));
|
blen = ll2string(bufb,sizeof(bufb),(long) ptrFromObj(b));
|
||||||
@ -595,7 +595,7 @@ int equalStringObjects(robj *a, robj *b) {
|
|||||||
size_t stringObjectLen(robj *o) {
|
size_t stringObjectLen(robj *o) {
|
||||||
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
||||||
if (sdsEncodedObject(o)) {
|
if (sdsEncodedObject(o)) {
|
||||||
return sdslen(ptrFromObj(o));
|
return sdslen(szFromObj(o));
|
||||||
} else {
|
} else {
|
||||||
return sdigits10((long)ptrFromObj(o));
|
return sdigits10((long)ptrFromObj(o));
|
||||||
}
|
}
|
||||||
@ -611,10 +611,10 @@ int getDoubleFromObject(const robj *o, double *target) {
|
|||||||
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
||||||
if (sdsEncodedObject(o)) {
|
if (sdsEncodedObject(o)) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
value = strtod(ptrFromObj(o), &eptr);
|
value = strtod(szFromObj(o), &eptr);
|
||||||
if (sdslen(ptrFromObj(o)) == 0 ||
|
if (sdslen(szFromObj(o)) == 0 ||
|
||||||
isspace(((const char*)ptrFromObj(o))[0]) ||
|
isspace(((const char*)szFromObj(o))[0]) ||
|
||||||
(size_t)(eptr-(char*)ptrFromObj(o)) != sdslen(ptrFromObj(o)) ||
|
(size_t)(eptr-(char*)szFromObj(o)) != sdslen(szFromObj(o)) ||
|
||||||
(errno == ERANGE &&
|
(errno == ERANGE &&
|
||||||
(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
|
(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
|
||||||
isnan(value))
|
isnan(value))
|
||||||
@ -653,16 +653,16 @@ int getLongDoubleFromObject(robj *o, long double *target) {
|
|||||||
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
||||||
if (sdsEncodedObject(o)) {
|
if (sdsEncodedObject(o)) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
value = strtold(ptrFromObj(o), &eptr);
|
value = strtold(szFromObj(o), &eptr);
|
||||||
if (sdslen(ptrFromObj(o)) == 0 ||
|
if (sdslen(szFromObj(o)) == 0 ||
|
||||||
isspace(((const char*)ptrFromObj(o))[0]) ||
|
isspace(((const char*)szFromObj(o))[0]) ||
|
||||||
(size_t)(eptr-(char*)ptrFromObj(o)) != sdslen(ptrFromObj(o)) ||
|
(size_t)(eptr-(char*)szFromObj(o)) != sdslen(szFromObj(o)) ||
|
||||||
(errno == ERANGE &&
|
(errno == ERANGE &&
|
||||||
(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
|
(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
|
||||||
isnan(value))
|
isnan(value))
|
||||||
return C_ERR;
|
return C_ERR;
|
||||||
} else if (o->encoding == OBJ_ENCODING_INT) {
|
} else if (o->encoding == OBJ_ENCODING_INT) {
|
||||||
value = (long)ptrFromObj(o);
|
value = (long)szFromObj(o);
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown string encoding");
|
serverPanic("Unknown string encoding");
|
||||||
}
|
}
|
||||||
@ -693,7 +693,7 @@ int getLongLongFromObject(robj *o, long long *target) {
|
|||||||
} else {
|
} else {
|
||||||
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
|
||||||
if (sdsEncodedObject(o)) {
|
if (sdsEncodedObject(o)) {
|
||||||
if (string2ll(ptrFromObj(o),sdslen(ptrFromObj(o)),&value) == 0) return C_ERR;
|
if (string2ll(szFromObj(o),sdslen(szFromObj(o)),&value) == 0) return C_ERR;
|
||||||
} else if (o->encoding == OBJ_ENCODING_INT) {
|
} else if (o->encoding == OBJ_ENCODING_INT) {
|
||||||
value = (long)ptrFromObj(o);
|
value = (long)ptrFromObj(o);
|
||||||
} else {
|
} else {
|
||||||
@ -734,7 +734,7 @@ int getLongFromObjectOrReply(client *c, robj *o, long *target, const char *msg)
|
|||||||
return C_OK;
|
return C_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strEncoding(int encoding) {
|
const char *strEncoding(int encoding) {
|
||||||
switch(encoding) {
|
switch(encoding) {
|
||||||
case OBJ_ENCODING_RAW: return "raw";
|
case OBJ_ENCODING_RAW: return "raw";
|
||||||
case OBJ_ENCODING_INT: return "int";
|
case OBJ_ENCODING_INT: return "int";
|
||||||
@ -790,15 +790,15 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
if(o->encoding == OBJ_ENCODING_INT) {
|
if(o->encoding == OBJ_ENCODING_INT) {
|
||||||
asize = sizeof(*o);
|
asize = sizeof(*o);
|
||||||
} else if(o->encoding == OBJ_ENCODING_RAW) {
|
} else if(o->encoding == OBJ_ENCODING_RAW) {
|
||||||
asize = sdsAllocSize(ptrFromObj(o))+sizeof(*o);
|
asize = sdsAllocSize(szFromObj(o))+sizeof(*o);
|
||||||
} else if(o->encoding == OBJ_ENCODING_EMBSTR) {
|
} else if(o->encoding == OBJ_ENCODING_EMBSTR) {
|
||||||
asize = sdslen(ptrFromObj(o))+2+sizeof(*o);
|
asize = sdslen(szFromObj(o))+2+sizeof(*o);
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown string encoding");
|
serverPanic("Unknown string encoding");
|
||||||
}
|
}
|
||||||
} else if (o->type == OBJ_LIST) {
|
} else if (o->type == OBJ_LIST) {
|
||||||
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||||
quicklist *ql = ptrFromObj(o);
|
quicklist *ql = (quicklist*)ptrFromObj(o);
|
||||||
quicklistNode *node = ql->head;
|
quicklistNode *node = ql->head;
|
||||||
asize = sizeof(*o)+sizeof(quicklist);
|
asize = sizeof(*o)+sizeof(quicklist);
|
||||||
do {
|
do {
|
||||||
@ -807,41 +807,41 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
} while ((node = node->next) && samples < sample_size);
|
} while ((node = node->next) && samples < sample_size);
|
||||||
asize += (double)elesize/samples*ql->len;
|
asize += (double)elesize/samples*ql->len;
|
||||||
} else if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
} else if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
asize = sizeof(*o)+ziplistBlobLen(ptrFromObj(o));
|
asize = sizeof(*o)+ziplistBlobLen((unsigned char*)ptrFromObj(o));
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown list encoding");
|
serverPanic("Unknown list encoding");
|
||||||
}
|
}
|
||||||
} else if (o->type == OBJ_SET) {
|
} else if (o->type == OBJ_SET) {
|
||||||
if (o->encoding == OBJ_ENCODING_HT) {
|
if (o->encoding == OBJ_ENCODING_HT) {
|
||||||
d = ptrFromObj(o);
|
d = (dict*)ptrFromObj(o);
|
||||||
di = dictGetIterator(d);
|
di = dictGetIterator(d);
|
||||||
asize = sizeof(*o)+sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d));
|
asize = sizeof(*o)+sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d));
|
||||||
while((de = dictNext(di)) != NULL && samples < sample_size) {
|
while((de = dictNext(di)) != NULL && samples < sample_size) {
|
||||||
ele = dictGetKey(de);
|
ele = (sds)dictGetKey(de);
|
||||||
elesize += sizeof(struct dictEntry) + sdsAllocSize(ele);
|
elesize += sizeof(struct dictEntry) + sdsAllocSize(ele);
|
||||||
samples++;
|
samples++;
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
if (samples) asize += (double)elesize/samples*dictSize(d);
|
if (samples) asize += (double)elesize/samples*dictSize(d);
|
||||||
} else if (o->encoding == OBJ_ENCODING_INTSET) {
|
} else if (o->encoding == OBJ_ENCODING_INTSET) {
|
||||||
intset *is = ptrFromObj(o);
|
intset *is = (intset*)ptrFromObj(o);
|
||||||
asize = sizeof(*o)+sizeof(*is)+is->encoding*is->length;
|
asize = sizeof(*o)+sizeof(*is)+is->encoding*is->length;
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown set encoding");
|
serverPanic("Unknown set encoding");
|
||||||
}
|
}
|
||||||
} else if (o->type == OBJ_ZSET) {
|
} else if (o->type == OBJ_ZSET) {
|
||||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
asize = sizeof(*o)+(ziplistBlobLen(ptrFromObj(o)));
|
asize = sizeof(*o)+(ziplistBlobLen((unsigned char*)ptrFromObj(o)));
|
||||||
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||||
d = ((zset*)ptrFromObj(o))->pdict;
|
d = ((zset*)ptrFromObj(o))->pdict;
|
||||||
zskiplist *zsl = ((zset*)ptrFromObj(o))->zsl;
|
zskiplist *zsl = ((zset*)ptrFromObj(o))->zsl;
|
||||||
zskiplistNode *znode = zsl->header->level[0].forward;
|
zskiplistNode *znode = zsl->header->level(0)->forward;
|
||||||
asize = sizeof(*o)+sizeof(zset)+(sizeof(struct dictEntry*)*dictSlots(d));
|
asize = sizeof(*o)+sizeof(zset)+(sizeof(struct dictEntry*)*dictSlots(d));
|
||||||
while(znode != NULL && samples < sample_size) {
|
while(znode != NULL && samples < sample_size) {
|
||||||
elesize += sdsAllocSize(znode->ele);
|
elesize += sdsAllocSize(znode->ele);
|
||||||
elesize += sizeof(struct dictEntry) + zmalloc_size(znode);
|
elesize += sizeof(struct dictEntry) + zmalloc_size(znode);
|
||||||
samples++;
|
samples++;
|
||||||
znode = znode->level[0].forward;
|
znode = znode->level(0)->forward;
|
||||||
}
|
}
|
||||||
if (samples) asize += (double)elesize/samples*dictSize(d);
|
if (samples) asize += (double)elesize/samples*dictSize(d);
|
||||||
} else {
|
} else {
|
||||||
@ -849,14 +849,14 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
}
|
}
|
||||||
} else if (o->type == OBJ_HASH) {
|
} else if (o->type == OBJ_HASH) {
|
||||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
asize = sizeof(*o)+(ziplistBlobLen(ptrFromObj(o)));
|
asize = sizeof(*o)+(ziplistBlobLen((unsigned char*)ptrFromObj(o)));
|
||||||
} else if (o->encoding == OBJ_ENCODING_HT) {
|
} else if (o->encoding == OBJ_ENCODING_HT) {
|
||||||
d = ptrFromObj(o);
|
d = (dict*)ptrFromObj(o);
|
||||||
di = dictGetIterator(d);
|
di = dictGetIterator(d);
|
||||||
asize = sizeof(*o)+sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d));
|
asize = sizeof(*o)+sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d));
|
||||||
while((de = dictNext(di)) != NULL && samples < sample_size) {
|
while((de = dictNext(di)) != NULL && samples < sample_size) {
|
||||||
ele = dictGetKey(de);
|
ele = (sds)dictGetKey(de);
|
||||||
ele2 = dictGetVal(de);
|
ele2 = (sds)dictGetVal(de);
|
||||||
elesize += sdsAllocSize(ele) + sdsAllocSize(ele2);
|
elesize += sdsAllocSize(ele) + sdsAllocSize(ele2);
|
||||||
elesize += sizeof(struct dictEntry);
|
elesize += sizeof(struct dictEntry);
|
||||||
samples++;
|
samples++;
|
||||||
@ -867,7 +867,7 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
serverPanic("Unknown hash encoding");
|
serverPanic("Unknown hash encoding");
|
||||||
}
|
}
|
||||||
} else if (o->type == OBJ_STREAM) {
|
} else if (o->type == OBJ_STREAM) {
|
||||||
stream *s = ptrFromObj(o);
|
stream *s = (stream*)ptrFromObj(o);
|
||||||
asize = sizeof(*o);
|
asize = sizeof(*o);
|
||||||
asize += streamRadixTreeMemoryUsage(s->prax);
|
asize += streamRadixTreeMemoryUsage(s->prax);
|
||||||
|
|
||||||
@ -880,7 +880,7 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
size_t lpsize = 0, samples = 0;
|
size_t lpsize = 0, samples = 0;
|
||||||
while(samples < sample_size && raxNext(&ri)) {
|
while(samples < sample_size && raxNext(&ri)) {
|
||||||
unsigned char *lp = ri.data;
|
unsigned char *lp = (unsigned char*)ri.data;
|
||||||
lpsize += lpBytes(lp);
|
lpsize += lpBytes(lp);
|
||||||
samples++;
|
samples++;
|
||||||
}
|
}
|
||||||
@ -893,7 +893,7 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
* if there are a few elements in the radix tree. */
|
* if there are a few elements in the radix tree. */
|
||||||
raxSeek(&ri,"$",NULL,0);
|
raxSeek(&ri,"$",NULL,0);
|
||||||
raxNext(&ri);
|
raxNext(&ri);
|
||||||
asize += lpBytes(ri.data);
|
asize += lpBytes((unsigned char*)ri.data);
|
||||||
}
|
}
|
||||||
raxStop(&ri);
|
raxStop(&ri);
|
||||||
|
|
||||||
@ -905,7 +905,7 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
raxStart(&ri,s->cgroups);
|
raxStart(&ri,s->cgroups);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
streamCG *cg = ri.data;
|
streamCG *cg = (streamCG*)ri.data;
|
||||||
asize += sizeof(*cg);
|
asize += sizeof(*cg);
|
||||||
asize += streamRadixTreeMemoryUsage(cg->pel);
|
asize += streamRadixTreeMemoryUsage(cg->pel);
|
||||||
asize += sizeof(streamNACK)*raxSize(cg->pel);
|
asize += sizeof(streamNACK)*raxSize(cg->pel);
|
||||||
@ -916,7 +916,7 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
raxStart(&cri,cg->consumers);
|
raxStart(&cri,cg->consumers);
|
||||||
raxSeek(&cri,"^",NULL,0);
|
raxSeek(&cri,"^",NULL,0);
|
||||||
while(raxNext(&cri)) {
|
while(raxNext(&cri)) {
|
||||||
streamConsumer *consumer = cri.data;
|
streamConsumer *consumer = (streamConsumer*)cri.data;
|
||||||
asize += sizeof(*consumer);
|
asize += sizeof(*consumer);
|
||||||
asize += sdslen(consumer->name);
|
asize += sdslen(consumer->name);
|
||||||
asize += streamRadixTreeMemoryUsage(consumer->pel);
|
asize += streamRadixTreeMemoryUsage(consumer->pel);
|
||||||
@ -928,7 +928,7 @@ size_t objectComputeSize(robj *o, size_t sample_size) {
|
|||||||
raxStop(&ri);
|
raxStop(&ri);
|
||||||
}
|
}
|
||||||
} else if (o->type == OBJ_MODULE) {
|
} else if (o->type == OBJ_MODULE) {
|
||||||
moduleValue *mv = ptrFromObj(o);
|
moduleValue *mv = (moduleValue*)ptrFromObj(o);
|
||||||
moduleType *mt = mv->type;
|
moduleType *mt = mv->type;
|
||||||
if (mt->mem_usage != NULL) {
|
if (mt->mem_usage != NULL) {
|
||||||
asize = mt->mem_usage(mv->value);
|
asize = mt->mem_usage(mv->value);
|
||||||
@ -956,7 +956,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) {
|
|||||||
size_t mem_total = 0;
|
size_t mem_total = 0;
|
||||||
size_t mem = 0;
|
size_t mem = 0;
|
||||||
size_t zmalloc_used = zmalloc_used_memory();
|
size_t zmalloc_used = zmalloc_used_memory();
|
||||||
struct redisMemOverhead *mh = zcalloc(sizeof(*mh), MALLOC_LOCAL);
|
struct redisMemOverhead *mh = (redisMemOverhead*)zcalloc(sizeof(*mh), MALLOC_LOCAL);
|
||||||
|
|
||||||
mh->total_allocated = zmalloc_used;
|
mh->total_allocated = zmalloc_used;
|
||||||
mh->startup_allocated = server.initial_memory_usage;
|
mh->startup_allocated = server.initial_memory_usage;
|
||||||
@ -993,7 +993,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) {
|
|||||||
|
|
||||||
listRewind(server.slaves,&li);
|
listRewind(server.slaves,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *c = listNodeValue(ln);
|
client *c = (client*)listNodeValue(ln);
|
||||||
if (c->flags & CLIENT_CLOSE_ASAP)
|
if (c->flags & CLIENT_CLOSE_ASAP)
|
||||||
continue;
|
continue;
|
||||||
mem += getClientOutputBufferMemoryUsage(c);
|
mem += getClientOutputBufferMemoryUsage(c);
|
||||||
@ -1011,7 +1011,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) {
|
|||||||
|
|
||||||
listRewind(server.clients,&li);
|
listRewind(server.clients,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *c = listNodeValue(ln);
|
client *c = (client*)listNodeValue(ln);
|
||||||
if (c->flags & CLIENT_SLAVE && !(c->flags & CLIENT_MONITOR))
|
if (c->flags & CLIENT_SLAVE && !(c->flags & CLIENT_MONITOR))
|
||||||
continue;
|
continue;
|
||||||
mem += getClientOutputBufferMemoryUsage(c);
|
mem += getClientOutputBufferMemoryUsage(c);
|
||||||
@ -1037,7 +1037,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) {
|
|||||||
dictSlots(server.repl_scriptcache_dict) * sizeof(dictEntry*);
|
dictSlots(server.repl_scriptcache_dict) * sizeof(dictEntry*);
|
||||||
if (listLength(server.repl_scriptcache_fifo) > 0) {
|
if (listLength(server.repl_scriptcache_fifo) > 0) {
|
||||||
mem += listLength(server.repl_scriptcache_fifo) * (sizeof(listNode) +
|
mem += listLength(server.repl_scriptcache_fifo) * (sizeof(listNode) +
|
||||||
sdsZmallocSize(listNodeValue(listFirst(server.repl_scriptcache_fifo))));
|
sdsZmallocSize((sds)listNodeValue(listFirst(server.repl_scriptcache_fifo))));
|
||||||
}
|
}
|
||||||
mh->lua_caches = mem;
|
mh->lua_caches = mem;
|
||||||
mem_total+=mem;
|
mem_total+=mem;
|
||||||
@ -1048,7 +1048,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) {
|
|||||||
if (keyscount==0) continue;
|
if (keyscount==0) continue;
|
||||||
|
|
||||||
mh->total_keys += keyscount;
|
mh->total_keys += keyscount;
|
||||||
mh->db = zrealloc(mh->db,sizeof(mh->db[0])*(mh->num_dbs+1), MALLOC_LOCAL);
|
mh->db = (decltype(mh->db))zrealloc(mh->db,sizeof(mh->db[0])*(mh->num_dbs+1), MALLOC_LOCAL);
|
||||||
mh->db[mh->num_dbs].dbid = j;
|
mh->db[mh->num_dbs].dbid = j;
|
||||||
|
|
||||||
mem = dictSize(db->pdict) * sizeof(dictEntry) +
|
mem = dictSize(db->pdict) * sizeof(dictEntry) +
|
||||||
@ -1256,7 +1256,7 @@ robj *objectCommandLookupOrReply(client *c, robj *key, robj *reply) {
|
|||||||
void objectCommand(client *c) {
|
void objectCommand(client *c) {
|
||||||
robj *o;
|
robj *o;
|
||||||
|
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"help")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"ENCODING <key> -- Return the kind of internal representation used in order to store the value associated with a key.",
|
"ENCODING <key> -- Return the kind of internal representation used in order to store the value associated with a key.",
|
||||||
"FREQ <key> -- Return the access frequency index of the key. The returned integer is proportional to the logarithm of the recent access frequency of the key.",
|
"FREQ <key> -- Return the access frequency index of the key. The returned integer is proportional to the logarithm of the recent access frequency of the key.",
|
||||||
@ -1265,15 +1265,15 @@ void objectCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"refcount") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"refcount") && c->argc == 3) {
|
||||||
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
||||||
== NULL) return;
|
== NULL) return;
|
||||||
addReplyLongLong(c,o->refcount);
|
addReplyLongLong(c,o->refcount);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"encoding") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"encoding") && c->argc == 3) {
|
||||||
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
||||||
== NULL) return;
|
== NULL) return;
|
||||||
addReplyBulkCString(c,strEncoding(o->encoding));
|
addReplyBulkCString(c,strEncoding(o->encoding));
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"idletime") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"idletime") && c->argc == 3) {
|
||||||
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
||||||
== NULL) return;
|
== NULL) return;
|
||||||
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
|
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
|
||||||
@ -1281,7 +1281,7 @@ NULL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addReplyLongLong(c,estimateObjectIdleTime(o)/1000);
|
addReplyLongLong(c,estimateObjectIdleTime(o)/1000);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"freq") && c->argc == 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"freq") && c->argc == 3) {
|
||||||
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.null[c->resp]))
|
||||||
== NULL) return;
|
== NULL) return;
|
||||||
if (!(server.maxmemory_policy & MAXMEMORY_FLAG_LFU)) {
|
if (!(server.maxmemory_policy & MAXMEMORY_FLAG_LFU)) {
|
||||||
@ -1303,7 +1303,7 @@ NULL
|
|||||||
*
|
*
|
||||||
* Usage: MEMORY usage <key> */
|
* Usage: MEMORY usage <key> */
|
||||||
void memoryCommand(client *c) {
|
void memoryCommand(client *c) {
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[1]),"help") && c->argc == 2) {
|
if (!strcasecmp(szFromObj(c->argv[1]),"help") && c->argc == 2) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"DOCTOR - Return memory problems reports.",
|
"DOCTOR - Return memory problems reports.",
|
||||||
"MALLOC-STATS -- Return internal statistics report from the memory allocator.",
|
"MALLOC-STATS -- Return internal statistics report from the memory allocator.",
|
||||||
@ -1313,11 +1313,11 @@ void memoryCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"usage") && c->argc >= 3) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"usage") && c->argc >= 3) {
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
long long samples = OBJ_COMPUTE_SIZE_DEF_SAMPLES;
|
long long samples = OBJ_COMPUTE_SIZE_DEF_SAMPLES;
|
||||||
for (int j = 3; j < c->argc; j++) {
|
for (int j = 3; j < c->argc; j++) {
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[j]),"samples") &&
|
if (!strcasecmp(szFromObj(c->argv[j]),"samples") &&
|
||||||
j+1 < c->argc)
|
j+1 < c->argc)
|
||||||
{
|
{
|
||||||
if (getLongLongFromObjectOrReply(c,c->argv[j+1],&samples,NULL)
|
if (getLongLongFromObjectOrReply(c,c->argv[j+1],&samples,NULL)
|
||||||
@ -1337,11 +1337,11 @@ NULL
|
|||||||
addReplyNull(c);
|
addReplyNull(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t usage = objectComputeSize(dictGetVal(de),samples);
|
size_t usage = objectComputeSize((robj*)dictGetVal(de),samples);
|
||||||
usage += sdsAllocSize(dictGetKey(de));
|
usage += sdsAllocSize((sds)dictGetKey(de));
|
||||||
usage += sizeof(dictEntry);
|
usage += sizeof(dictEntry);
|
||||||
addReplyLongLong(c,usage);
|
addReplyLongLong(c,usage);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"stats") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"stats") && c->argc == 2) {
|
||||||
struct redisMemOverhead *mh = getMemoryOverheadData();
|
struct redisMemOverhead *mh = getMemoryOverheadData();
|
||||||
|
|
||||||
addReplyMapLen(c,25+mh->num_dbs);
|
addReplyMapLen(c,25+mh->num_dbs);
|
||||||
@ -1435,7 +1435,7 @@ NULL
|
|||||||
addReplyLongLong(c,mh->total_frag_bytes);
|
addReplyLongLong(c,mh->total_frag_bytes);
|
||||||
|
|
||||||
freeMemoryOverheadData(mh);
|
freeMemoryOverheadData(mh);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"malloc-stats") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"malloc-stats") && c->argc == 2) {
|
||||||
#if defined(USE_JEMALLOC)
|
#if defined(USE_JEMALLOC)
|
||||||
sds info = sdsempty();
|
sds info = sdsempty();
|
||||||
je_malloc_stats_print(inputCatSds, &info, NULL);
|
je_malloc_stats_print(inputCatSds, &info, NULL);
|
||||||
@ -1443,10 +1443,10 @@ NULL
|
|||||||
#else
|
#else
|
||||||
addReplyBulkCString(c,"Stats not supported for the current allocator");
|
addReplyBulkCString(c,"Stats not supported for the current allocator");
|
||||||
#endif
|
#endif
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"doctor") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"doctor") && c->argc == 2) {
|
||||||
sds report = getMemoryDoctorReport();
|
sds report = getMemoryDoctorReport();
|
||||||
addReplyBulkSds(c,report);
|
addReplyBulkSds(c,report);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"purge") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"purge") && c->argc == 2) {
|
||||||
#if defined(USE_JEMALLOC)
|
#if defined(USE_JEMALLOC)
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
unsigned narenas = 0;
|
unsigned narenas = 0;
|
@ -121,14 +121,14 @@ void addReplyPubsubPatUnsubscribed(client *c, robj *pattern) {
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void freePubsubPattern(void *p) {
|
void freePubsubPattern(void *p) {
|
||||||
pubsubPattern *pat = p;
|
pubsubPattern *pat = (pubsubPattern *)p;
|
||||||
|
|
||||||
decrRefCount(pat->pattern);
|
decrRefCount(pat->pattern);
|
||||||
zfree(pat);
|
zfree(pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
int listMatchPubsubPattern(void *a, void *b) {
|
int listMatchPubsubPattern(void *a, void *b) {
|
||||||
pubsubPattern *pa = a, *pb = b;
|
pubsubPattern *pa = (pubsubPattern*)a, *pb = (pubsubPattern*)b;
|
||||||
|
|
||||||
return (pa->pclient == pb->pclient) &&
|
return (pa->pclient == pb->pclient) &&
|
||||||
(equalStringObjects(pa->pattern,pb->pattern));
|
(equalStringObjects(pa->pattern,pb->pattern));
|
||||||
@ -158,7 +158,7 @@ int pubsubSubscribeChannel(client *c, robj *channel) {
|
|||||||
dictAdd(server.pubsub_channels,channel,clients);
|
dictAdd(server.pubsub_channels,channel,clients);
|
||||||
incrRefCount(channel);
|
incrRefCount(channel);
|
||||||
} else {
|
} else {
|
||||||
clients = dictGetVal(de);
|
clients = (list*)dictGetVal(de);
|
||||||
}
|
}
|
||||||
listAddNodeTail(clients,c);
|
listAddNodeTail(clients,c);
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ int pubsubUnsubscribeChannel(client *c, robj *channel, int notify) {
|
|||||||
/* Remove the client from the channel -> clients list hash table */
|
/* Remove the client from the channel -> clients list hash table */
|
||||||
de = dictFind(server.pubsub_channels,channel);
|
de = dictFind(server.pubsub_channels,channel);
|
||||||
serverAssertWithInfo(c,NULL,de != NULL);
|
serverAssertWithInfo(c,NULL,de != NULL);
|
||||||
clients = dictGetVal(de);
|
clients = (list*)dictGetVal(de);
|
||||||
ln = listSearchKey(clients,c);
|
ln = listSearchKey(clients,c);
|
||||||
serverAssertWithInfo(c,NULL,ln != NULL);
|
serverAssertWithInfo(c,NULL,ln != NULL);
|
||||||
listDelNode(clients,ln);
|
listDelNode(clients,ln);
|
||||||
@ -209,7 +209,7 @@ int pubsubSubscribePattern(client *c, robj *pattern) {
|
|||||||
pubsubPattern *pat;
|
pubsubPattern *pat;
|
||||||
listAddNodeTail(c->pubsub_patterns,pattern);
|
listAddNodeTail(c->pubsub_patterns,pattern);
|
||||||
incrRefCount(pattern);
|
incrRefCount(pattern);
|
||||||
pat = zmalloc(sizeof(*pat), MALLOC_LOCAL);
|
pat = (pubsubPattern*)zmalloc(sizeof(*pat), MALLOC_LOCAL);
|
||||||
pat->pattern = getDecodedObject(pattern);
|
pat->pattern = getDecodedObject(pattern);
|
||||||
pat->pclient = c;
|
pat->pclient = c;
|
||||||
listAddNodeTail(server.pubsub_patterns,pat);
|
listAddNodeTail(server.pubsub_patterns,pat);
|
||||||
@ -249,7 +249,7 @@ int pubsubUnsubscribeAllChannels(client *c, int notify) {
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
robj *channel = dictGetKey(de);
|
robj *channel = (robj*)dictGetKey(de);
|
||||||
|
|
||||||
count += pubsubUnsubscribeChannel(c,channel,notify);
|
count += pubsubUnsubscribeChannel(c,channel,notify);
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ int pubsubUnsubscribeAllPatterns(client *c, int notify) {
|
|||||||
|
|
||||||
listRewind(c->pubsub_patterns,&li);
|
listRewind(c->pubsub_patterns,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
robj *pattern = ln->value;
|
robj *pattern = (robj*)ln->value;
|
||||||
|
|
||||||
count += pubsubUnsubscribePattern(c,pattern,notify);
|
count += pubsubUnsubscribePattern(c,pattern,notify);
|
||||||
}
|
}
|
||||||
@ -286,13 +286,13 @@ int pubsubPublishMessage(robj *channel, robj *message) {
|
|||||||
/* Send to clients listening for that channel */
|
/* Send to clients listening for that channel */
|
||||||
de = dictFind(server.pubsub_channels,channel);
|
de = dictFind(server.pubsub_channels,channel);
|
||||||
if (de) {
|
if (de) {
|
||||||
list *list = dictGetVal(de);
|
list *list = reinterpret_cast<::list*>(dictGetVal(de));
|
||||||
listNode *ln;
|
listNode *ln;
|
||||||
listIter li;
|
listIter li;
|
||||||
|
|
||||||
listRewind(list,&li);
|
listRewind(list,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
client *c = ln->value;
|
client *c = reinterpret_cast<client*>(ln->value);
|
||||||
fastlock_lock(&c->lock);
|
fastlock_lock(&c->lock);
|
||||||
addReplyPubsubMessage(c,channel,message);
|
addReplyPubsubMessage(c,channel,message);
|
||||||
fastlock_unlock(&c->lock);
|
fastlock_unlock(&c->lock);
|
||||||
@ -304,12 +304,12 @@ int pubsubPublishMessage(robj *channel, robj *message) {
|
|||||||
listRewind(server.pubsub_patterns,&li);
|
listRewind(server.pubsub_patterns,&li);
|
||||||
channel = getDecodedObject(channel);
|
channel = getDecodedObject(channel);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
pubsubPattern *pat = ln->value;
|
pubsubPattern *pat = (pubsubPattern*)ln->value;
|
||||||
|
|
||||||
if (stringmatchlen((char*)ptrFromObj(pat->pattern),
|
if (stringmatchlen((char*)ptrFromObj(pat->pattern),
|
||||||
sdslen(ptrFromObj(pat->pattern)),
|
sdslen(szFromObj(pat->pattern)),
|
||||||
(char*)ptrFromObj(channel),
|
(char*)ptrFromObj(channel),
|
||||||
sdslen(ptrFromObj(channel)),0))
|
sdslen(szFromObj(channel)),0))
|
||||||
{
|
{
|
||||||
fastlock_lock(&pat->pclient->lock);
|
fastlock_lock(&pat->pclient->lock);
|
||||||
addReplyPubsubPatMessage(pat->pclient,
|
addReplyPubsubPatMessage(pat->pclient,
|
||||||
@ -380,7 +380,7 @@ void publishCommand(client *c) {
|
|||||||
|
|
||||||
/* PUBSUB command for Pub/Sub introspection. */
|
/* PUBSUB command for Pub/Sub introspection. */
|
||||||
void pubsubCommand(client *c) {
|
void pubsubCommand(client *c) {
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"help")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"CHANNELS [<pattern>] -- Return the currently active channels matching a pattern (default: all).",
|
"CHANNELS [<pattern>] -- Return the currently active channels matching a pattern (default: all).",
|
||||||
"NUMPAT -- Return number of subscriptions to patterns.",
|
"NUMPAT -- Return number of subscriptions to patterns.",
|
||||||
@ -388,11 +388,11 @@ void pubsubCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"channels") &&
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"channels") &&
|
||||||
(c->argc == 2 || c->argc == 3))
|
(c->argc == 2 || c->argc == 3))
|
||||||
{
|
{
|
||||||
/* PUBSUB CHANNELS [<pattern>] */
|
/* PUBSUB CHANNELS [<pattern>] */
|
||||||
sds pat = (c->argc == 2) ? NULL : ptrFromObj(c->argv[2]);
|
sds pat = (c->argc == 2) ? NULL : szFromObj(c->argv[2]);
|
||||||
dictIterator *di = dictGetIterator(server.pubsub_channels);
|
dictIterator *di = dictGetIterator(server.pubsub_channels);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
long mblen = 0;
|
long mblen = 0;
|
||||||
@ -400,8 +400,8 @@ NULL
|
|||||||
|
|
||||||
replylen = addReplyDeferredLen(c);
|
replylen = addReplyDeferredLen(c);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
robj *cobj = dictGetKey(de);
|
robj *cobj = (robj*)dictGetKey(de);
|
||||||
sds channel = ptrFromObj(cobj);
|
sds channel = szFromObj(cobj);
|
||||||
|
|
||||||
if (!pat || stringmatchlen(pat, sdslen(pat),
|
if (!pat || stringmatchlen(pat, sdslen(pat),
|
||||||
channel, sdslen(channel),0))
|
channel, sdslen(channel),0))
|
||||||
@ -412,18 +412,18 @@ NULL
|
|||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
setDeferredArrayLen(c,replylen,mblen);
|
setDeferredArrayLen(c,replylen,mblen);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"numsub") && c->argc >= 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"numsub") && c->argc >= 2) {
|
||||||
/* PUBSUB NUMSUB [Channel_1 ... Channel_N] */
|
/* PUBSUB NUMSUB [Channel_1 ... Channel_N] */
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
addReplyArrayLen(c,(c->argc-2)*2);
|
addReplyArrayLen(c,(c->argc-2)*2);
|
||||||
for (j = 2; j < c->argc; j++) {
|
for (j = 2; j < c->argc; j++) {
|
||||||
list *l = dictFetchValue(server.pubsub_channels,c->argv[j]);
|
list *l = (list*)dictFetchValue(server.pubsub_channels,c->argv[j]);
|
||||||
|
|
||||||
addReplyBulk(c,c->argv[j]);
|
addReplyBulk(c,c->argv[j]);
|
||||||
addReplyLongLong(c,l ? listLength(l) : 0);
|
addReplyLongLong(c,l ? listLength(l) : 0);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"numpat") && c->argc == 2) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"numpat") && c->argc == 2) {
|
||||||
/* PUBSUB NUMPAT */
|
/* PUBSUB NUMPAT */
|
||||||
addReplyLongLong(c,listLength(server.pubsub_patterns));
|
addReplyLongLong(c,listLength(server.pubsub_patterns));
|
||||||
} else {
|
} else {
|
@ -49,7 +49,7 @@ extern int rdbCheckMode;
|
|||||||
void rdbCheckError(const char *fmt, ...);
|
void rdbCheckError(const char *fmt, ...);
|
||||||
void rdbCheckSetError(const char *fmt, ...);
|
void rdbCheckSetError(const char *fmt, ...);
|
||||||
|
|
||||||
void rdbCheckThenExit(int linenum, char *reason, ...) {
|
void rdbCheckThenExit(int linenum, const char *reason, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
int len;
|
int len;
|
||||||
@ -62,7 +62,7 @@ void rdbCheckThenExit(int linenum, char *reason, ...) {
|
|||||||
|
|
||||||
if (!rdbCheckMode) {
|
if (!rdbCheckMode) {
|
||||||
serverLog(LL_WARNING, "%s", msg);
|
serverLog(LL_WARNING, "%s", msg);
|
||||||
char *argv[2] = {"",server.rdb_filename};
|
const char * argv[2] = {"",server.rdb_filename};
|
||||||
redis_check_rdb_main(2,argv,NULL);
|
redis_check_rdb_main(2,argv,NULL);
|
||||||
} else {
|
} else {
|
||||||
rdbCheckError("%s",msg);
|
rdbCheckError("%s",msg);
|
||||||
@ -285,7 +285,7 @@ void *rdbLoadIntegerObject(rio *rdb, int enctype, int flags, size_t *lenptr) {
|
|||||||
char buf[LONG_STR_SIZE], *p;
|
char buf[LONG_STR_SIZE], *p;
|
||||||
int len = ll2string(buf,sizeof(buf),val);
|
int len = ll2string(buf,sizeof(buf),val);
|
||||||
if (lenptr) *lenptr = len;
|
if (lenptr) *lenptr = len;
|
||||||
p = plain ? zmalloc(len, MALLOC_SHARED) : sdsnewlen(SDS_NOINIT,len);
|
p = (char*)(plain ? zmalloc(len, MALLOC_SHARED) : sdsnewlen(SDS_NOINIT,len));
|
||||||
memcpy(p,buf,len);
|
memcpy(p,buf,len);
|
||||||
return p;
|
return p;
|
||||||
} else if (encode) {
|
} else if (encode) {
|
||||||
@ -339,7 +339,7 @@ writeerr:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
|
ssize_t rdbSaveLzfStringObject(rio *rdb, const unsigned char *s, size_t len) {
|
||||||
size_t comprlen, outlen;
|
size_t comprlen, outlen;
|
||||||
void *out;
|
void *out;
|
||||||
|
|
||||||
@ -369,11 +369,11 @@ void *rdbLoadLzfStringObject(rio *rdb, int flags, size_t *lenptr) {
|
|||||||
|
|
||||||
if ((clen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
if ((clen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
||||||
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
||||||
if ((c = zmalloc(clen, MALLOC_SHARED)) == NULL) goto err;
|
if ((c = (unsigned char*)zmalloc(clen, MALLOC_SHARED)) == NULL) goto err;
|
||||||
|
|
||||||
/* Allocate our target according to the uncompressed size. */
|
/* Allocate our target according to the uncompressed size. */
|
||||||
if (plain) {
|
if (plain) {
|
||||||
val = zmalloc(len, MALLOC_SHARED);
|
val = (char*)zmalloc(len, MALLOC_SHARED);
|
||||||
} else {
|
} else {
|
||||||
val = sdsnewlen(SDS_NOINIT,len);
|
val = sdsnewlen(SDS_NOINIT,len);
|
||||||
}
|
}
|
||||||
@ -403,7 +403,7 @@ err:
|
|||||||
|
|
||||||
/* Save a string object as [len][data] on disk. If the object is a string
|
/* Save a string object as [len][data] on disk. If the object is a string
|
||||||
* representation of an integer value we try to save it in a special form */
|
* representation of an integer value we try to save it in a special form */
|
||||||
ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
|
ssize_t rdbSaveRawString(rio *rdb, const unsigned char *s, size_t len) {
|
||||||
int enclen;
|
int enclen;
|
||||||
ssize_t n, nwritten = 0;
|
ssize_t n, nwritten = 0;
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
|
|||||||
/* Try LZF compression - under 20 bytes it's unable to compress even
|
/* Try LZF compression - under 20 bytes it's unable to compress even
|
||||||
* aaaaaaaaaaaaaaaaaa so skip it */
|
* aaaaaaaaaaaaaaaaaa so skip it */
|
||||||
if (server.rdb_compression && len > 20) {
|
if (server.rdb_compression && len > 20) {
|
||||||
n = rdbSaveLzfStringObject(rdb,s,len);
|
n = rdbSaveLzfStringObject(rdb,(const unsigned char*)s,len);
|
||||||
if (n == -1) return -1;
|
if (n == -1) return -1;
|
||||||
if (n > 0) return n;
|
if (n > 0) return n;
|
||||||
/* Return value of 0 means data can't be compressed, save the old way */
|
/* Return value of 0 means data can't be compressed, save the old way */
|
||||||
@ -429,7 +429,7 @@ ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
|
|||||||
if ((n = rdbSaveLen(rdb,len)) == -1) return -1;
|
if ((n = rdbSaveLen(rdb,len)) == -1) return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
if (rdbWriteRaw(rdb,s,len) == -1) return -1;
|
if (rdbWriteRaw(rdb,(unsigned char*)s,len) == -1) return -1;
|
||||||
nwritten += len;
|
nwritten += len;
|
||||||
}
|
}
|
||||||
return nwritten;
|
return nwritten;
|
||||||
@ -462,7 +462,7 @@ ssize_t rdbSaveStringObject(rio *rdb, robj *obj) {
|
|||||||
return rdbSaveLongLongAsStringObject(rdb,(long)ptrFromObj(obj));
|
return rdbSaveLongLongAsStringObject(rdb,(long)ptrFromObj(obj));
|
||||||
} else {
|
} else {
|
||||||
serverAssertWithInfo(NULL,obj,sdsEncodedObject(obj));
|
serverAssertWithInfo(NULL,obj,sdsEncodedObject(obj));
|
||||||
return rdbSaveRawString(rdb,ptrFromObj(obj),sdslen(ptrFromObj(obj)));
|
return rdbSaveRawString(rdb,(unsigned char*)szFromObj(obj),sdslen(szFromObj(obj)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr) {
|
|||||||
if (plain)
|
if (plain)
|
||||||
zfree(buf);
|
zfree(buf);
|
||||||
else
|
else
|
||||||
sdsfree(buf);
|
sdsfree((char*)buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
@ -524,11 +524,11 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
robj *rdbLoadStringObject(rio *rdb) {
|
robj *rdbLoadStringObject(rio *rdb) {
|
||||||
return rdbGenericLoadStringObject(rdb,RDB_LOAD_NONE,NULL);
|
return (robj*)rdbGenericLoadStringObject(rdb,RDB_LOAD_NONE,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
robj *rdbLoadEncodedStringObject(rio *rdb) {
|
robj *rdbLoadEncodedStringObject(rio *rdb) {
|
||||||
return rdbGenericLoadStringObject(rdb,RDB_LOAD_ENC,NULL);
|
return (robj*)rdbGenericLoadStringObject(rdb,RDB_LOAD_ENC,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save a double value. Doubles are saved as strings prefixed by an unsigned
|
/* Save a double value. Doubles are saved as strings prefixed by an unsigned
|
||||||
@ -697,7 +697,7 @@ ssize_t rdbSaveStreamPEL(rio *rdb, rax *pel, int nacks) {
|
|||||||
nwritten += n;
|
nwritten += n;
|
||||||
|
|
||||||
if (nacks) {
|
if (nacks) {
|
||||||
streamNACK *nack = ri.data;
|
streamNACK *nack = (streamNACK*)ri.data;
|
||||||
if ((n = rdbSaveMillisecondTime(rdb,nack->delivery_time)) == -1)
|
if ((n = rdbSaveMillisecondTime(rdb,nack->delivery_time)) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
@ -727,7 +727,7 @@ size_t rdbSaveStreamConsumers(rio *rdb, streamCG *cg) {
|
|||||||
raxStart(&ri,cg->consumers);
|
raxStart(&ri,cg->consumers);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
streamConsumer *consumer = ri.data;
|
streamConsumer *consumer = (streamConsumer*)ri.data;
|
||||||
|
|
||||||
/* Consumer name. */
|
/* Consumer name. */
|
||||||
if ((n = rdbSaveRawString(rdb,ri.key,ri.key_len)) == -1) return -1;
|
if ((n = rdbSaveRawString(rdb,ri.key,ri.key_len)) == -1) return -1;
|
||||||
@ -762,7 +762,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
} else if (o->type == OBJ_LIST) {
|
} else if (o->type == OBJ_LIST) {
|
||||||
/* Save a list value */
|
/* Save a list value */
|
||||||
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
if (o->encoding == OBJ_ENCODING_QUICKLIST) {
|
||||||
quicklist *ql = ptrFromObj(o);
|
quicklist *ql = (quicklist*)ptrFromObj(o);
|
||||||
quicklistNode *node = ql->head;
|
quicklistNode *node = ql->head;
|
||||||
|
|
||||||
if ((n = rdbSaveLen(rdb,ql->len)) == -1) return -1;
|
if ((n = rdbSaveLen(rdb,ql->len)) == -1) return -1;
|
||||||
@ -786,7 +786,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
} else if (o->type == OBJ_SET) {
|
} else if (o->type == OBJ_SET) {
|
||||||
/* Save a set value */
|
/* Save a set value */
|
||||||
if (o->encoding == OBJ_ENCODING_HT) {
|
if (o->encoding == OBJ_ENCODING_HT) {
|
||||||
dict *set = ptrFromObj(o);
|
dict *set = (dict*)ptrFromObj(o);
|
||||||
dictIterator *di = dictGetIterator(set);
|
dictIterator *di = dictGetIterator(set);
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
@ -797,7 +797,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
nwritten += n;
|
nwritten += n;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds ele = dictGetKey(de);
|
sds ele = (sds)dictGetKey(de);
|
||||||
if ((n = rdbSaveRawString(rdb,(unsigned char*)ele,sdslen(ele)))
|
if ((n = rdbSaveRawString(rdb,(unsigned char*)ele,sdslen(ele)))
|
||||||
== -1)
|
== -1)
|
||||||
{
|
{
|
||||||
@ -810,7 +810,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
} else if (o->encoding == OBJ_ENCODING_INTSET) {
|
} else if (o->encoding == OBJ_ENCODING_INTSET) {
|
||||||
size_t l = intsetBlobLen((intset*)ptrFromObj(o));
|
size_t l = intsetBlobLen((intset*)ptrFromObj(o));
|
||||||
|
|
||||||
if ((n = rdbSaveRawString(rdb,ptrFromObj(o),l)) == -1) return -1;
|
if ((n = rdbSaveRawString(rdb,(unsigned char*)szFromObj(o),l)) == -1) return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown set encoding");
|
serverPanic("Unknown set encoding");
|
||||||
@ -820,10 +820,10 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
size_t l = ziplistBlobLen((unsigned char*)ptrFromObj(o));
|
size_t l = ziplistBlobLen((unsigned char*)ptrFromObj(o));
|
||||||
|
|
||||||
if ((n = rdbSaveRawString(rdb,ptrFromObj(o),l)) == -1) return -1;
|
if ((n = rdbSaveRawString(rdb,(unsigned char*)ptrFromObj(o),l)) == -1) return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else if (o->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||||
zset *zs = ptrFromObj(o);
|
zset *zs = (zset*)ptrFromObj(o);
|
||||||
zskiplist *zsl = zs->zsl;
|
zskiplist *zsl = zs->zsl;
|
||||||
|
|
||||||
if ((n = rdbSaveLen(rdb,zsl->length)) == -1) return -1;
|
if ((n = rdbSaveLen(rdb,zsl->length)) == -1) return -1;
|
||||||
@ -856,11 +856,11 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (o->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
size_t l = ziplistBlobLen((unsigned char*)ptrFromObj(o));
|
size_t l = ziplistBlobLen((unsigned char*)ptrFromObj(o));
|
||||||
|
|
||||||
if ((n = rdbSaveRawString(rdb,ptrFromObj(o),l)) == -1) return -1;
|
if ((n = rdbSaveRawString(rdb,(unsigned char*)ptrFromObj(o),l)) == -1) return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
|
|
||||||
} else if (o->encoding == OBJ_ENCODING_HT) {
|
} else if (o->encoding == OBJ_ENCODING_HT) {
|
||||||
dictIterator *di = dictGetIterator(ptrFromObj(o));
|
dictIterator *di = dictGetIterator((dict*)ptrFromObj(o));
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
|
|
||||||
if ((n = rdbSaveLen(rdb,dictSize((dict*)ptrFromObj(o)))) == -1) {
|
if ((n = rdbSaveLen(rdb,dictSize((dict*)ptrFromObj(o)))) == -1) {
|
||||||
@ -870,8 +870,8 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
nwritten += n;
|
nwritten += n;
|
||||||
|
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds field = dictGetKey(de);
|
sds field = (sds)dictGetKey(de);
|
||||||
sds value = dictGetVal(de);
|
sds value = (sds)dictGetVal(de);
|
||||||
|
|
||||||
if ((n = rdbSaveRawString(rdb,(unsigned char*)field,
|
if ((n = rdbSaveRawString(rdb,(unsigned char*)field,
|
||||||
sdslen(field))) == -1)
|
sdslen(field))) == -1)
|
||||||
@ -894,7 +894,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
}
|
}
|
||||||
} else if (o->type == OBJ_STREAM) {
|
} else if (o->type == OBJ_STREAM) {
|
||||||
/* Store how many listpacks we have inside the radix tree. */
|
/* Store how many listpacks we have inside the radix tree. */
|
||||||
stream *s = ptrFromObj(o);
|
stream *s = (stream*)ptrFromObj(o);
|
||||||
rax *rax = s->prax;
|
rax *rax = s->prax;
|
||||||
if ((n = rdbSaveLen(rdb,raxSize(rax))) == -1) return -1;
|
if ((n = rdbSaveLen(rdb,raxSize(rax))) == -1) return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
@ -906,7 +906,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
raxStart(&ri,rax);
|
raxStart(&ri,rax);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while (raxNext(&ri)) {
|
while (raxNext(&ri)) {
|
||||||
unsigned char *lp = ri.data;
|
unsigned char *lp = (unsigned char*)ri.data;
|
||||||
size_t lp_bytes = lpBytes(lp);
|
size_t lp_bytes = lpBytes(lp);
|
||||||
if ((n = rdbSaveRawString(rdb,ri.key,ri.key_len)) == -1) return -1;
|
if ((n = rdbSaveRawString(rdb,ri.key,ri.key_len)) == -1) return -1;
|
||||||
nwritten += n;
|
nwritten += n;
|
||||||
@ -939,7 +939,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
raxStart(&ri,s->cgroups);
|
raxStart(&ri,s->cgroups);
|
||||||
raxSeek(&ri,"^",NULL,0);
|
raxSeek(&ri,"^",NULL,0);
|
||||||
while(raxNext(&ri)) {
|
while(raxNext(&ri)) {
|
||||||
streamCG *cg = ri.data;
|
streamCG *cg = (streamCG*)ri.data;
|
||||||
|
|
||||||
/* Save the group name. */
|
/* Save the group name. */
|
||||||
if ((n = rdbSaveRawString(rdb,ri.key,ri.key_len)) == -1)
|
if ((n = rdbSaveRawString(rdb,ri.key,ri.key_len)) == -1)
|
||||||
@ -965,7 +965,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
|
|||||||
} else if (o->type == OBJ_MODULE) {
|
} else if (o->type == OBJ_MODULE) {
|
||||||
/* Save a module-specific value. */
|
/* Save a module-specific value. */
|
||||||
RedisModuleIO io;
|
RedisModuleIO io;
|
||||||
moduleValue *mv = ptrFromObj(o);
|
moduleValue *mv = (moduleValue*)ptrFromObj(o);
|
||||||
moduleType *mt = mv->type;
|
moduleType *mt = mv->type;
|
||||||
moduleInitIOContext(io,mt,rdb,key);
|
moduleInitIOContext(io,mt,rdb,key);
|
||||||
|
|
||||||
@ -1044,25 +1044,25 @@ int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save an AUX field. */
|
/* Save an AUX field. */
|
||||||
ssize_t rdbSaveAuxField(rio *rdb, void *key, size_t keylen, void *val, size_t vallen) {
|
ssize_t rdbSaveAuxField(rio *rdb, const void *key, size_t keylen, const void *val, size_t vallen) {
|
||||||
ssize_t ret, len = 0;
|
ssize_t ret, len = 0;
|
||||||
if ((ret = rdbSaveType(rdb,RDB_OPCODE_AUX)) == -1) return -1;
|
if ((ret = rdbSaveType(rdb,RDB_OPCODE_AUX)) == -1) return -1;
|
||||||
len += ret;
|
len += ret;
|
||||||
if ((ret = rdbSaveRawString(rdb,key,keylen)) == -1) return -1;
|
if ((ret = rdbSaveRawString(rdb,(const unsigned char*)key,keylen)) == -1) return -1;
|
||||||
len += ret;
|
len += ret;
|
||||||
if ((ret = rdbSaveRawString(rdb,val,vallen)) == -1) return -1;
|
if ((ret = rdbSaveRawString(rdb,(const unsigned char*)val,vallen)) == -1) return -1;
|
||||||
len += ret;
|
len += ret;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrapper for rdbSaveAuxField() used when key/val length can be obtained
|
/* Wrapper for rdbSaveAuxField() used when key/val length can be obtained
|
||||||
* with strlen(). */
|
* with strlen(). */
|
||||||
ssize_t rdbSaveAuxFieldStrStr(rio *rdb, char *key, char *val) {
|
ssize_t rdbSaveAuxFieldStrStr(rio *rdb, const char *key, const char *val) {
|
||||||
return rdbSaveAuxField(rdb,key,strlen(key),val,strlen(val));
|
return rdbSaveAuxField(rdb,key,strlen(key),val,strlen(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrapper for strlen(key) + integer type (up to long long range). */
|
/* Wrapper for strlen(key) + integer type (up to long long range). */
|
||||||
ssize_t rdbSaveAuxFieldStrInt(rio *rdb, char *key, long long val) {
|
ssize_t rdbSaveAuxFieldStrInt(rio *rdb, const char *key, long long val) {
|
||||||
char buf[LONG_STR_SIZE];
|
char buf[LONG_STR_SIZE];
|
||||||
int vlen = ll2string(buf,sizeof(buf),val);
|
int vlen = ll2string(buf,sizeof(buf),val);
|
||||||
return rdbSaveAuxField(rdb,key,strlen(key),buf,vlen);
|
return rdbSaveAuxField(rdb,key,strlen(key),buf,vlen);
|
||||||
@ -1137,8 +1137,8 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
|
|||||||
|
|
||||||
/* Iterate this DB writing every entry */
|
/* Iterate this DB writing every entry */
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sds keystr = dictGetKey(de);
|
sds keystr = (sds)dictGetKey(de);
|
||||||
robj key, *o = dictGetVal(de);
|
robj key, *o = (robj*)dictGetVal(de);
|
||||||
long long expire;
|
long long expire;
|
||||||
|
|
||||||
initStaticStringObject(key,keystr);
|
initStaticStringObject(key,keystr);
|
||||||
@ -1166,8 +1166,8 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
|
|||||||
if (rsi && dictSize(server.lua_scripts)) {
|
if (rsi && dictSize(server.lua_scripts)) {
|
||||||
di = dictGetIterator(server.lua_scripts);
|
di = dictGetIterator(server.lua_scripts);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
robj *body = dictGetVal(de);
|
robj *body = (robj*)dictGetVal(de);
|
||||||
if (rdbSaveAuxField(rdb,"lua",3,ptrFromObj(body),sdslen(ptrFromObj(body))) == -1)
|
if (rdbSaveAuxField(rdb,"lua",3,szFromObj(body),sdslen(szFromObj(body))) == -1)
|
||||||
goto werr;
|
goto werr;
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
@ -1376,7 +1376,7 @@ robj *rdbLoadCheckModuleValue(rio *rdb, char *modulename) {
|
|||||||
"Error reading integer from module %s value", modulename);
|
"Error reading integer from module %s value", modulename);
|
||||||
}
|
}
|
||||||
} else if (opcode == RDB_MODULE_OPCODE_STRING) {
|
} else if (opcode == RDB_MODULE_OPCODE_STRING) {
|
||||||
robj *o = rdbGenericLoadStringObject(rdb,RDB_LOAD_NONE,NULL);
|
robj *o = (robj*)rdbGenericLoadStringObject(rdb,RDB_LOAD_NONE,NULL);
|
||||||
if (o == NULL) {
|
if (o == NULL) {
|
||||||
rdbExitReportCorruptRDB(
|
rdbExitReportCorruptRDB(
|
||||||
"Error reading string from module %s value", modulename);
|
"Error reading string from module %s value", modulename);
|
||||||
@ -1415,15 +1415,15 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
||||||
|
|
||||||
o = createQuicklistObject();
|
o = createQuicklistObject();
|
||||||
quicklistSetOptions(ptrFromObj(o), server.list_max_ziplist_size,
|
quicklistSetOptions((quicklist*)ptrFromObj(o), server.list_max_ziplist_size,
|
||||||
server.list_compress_depth);
|
server.list_compress_depth);
|
||||||
|
|
||||||
/* Load every single element of the list */
|
/* Load every single element of the list */
|
||||||
while(len--) {
|
while(len--) {
|
||||||
if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
|
if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
|
||||||
dec = getDecodedObject(ele);
|
dec = getDecodedObject(ele);
|
||||||
size_t len = sdslen(ptrFromObj(dec));
|
size_t len = sdslen(szFromObj(dec));
|
||||||
quicklistPushTail(ptrFromObj(o), ptrFromObj(dec), len);
|
quicklistPushTail((quicklist*)ptrFromObj(o), ptrFromObj(dec), len);
|
||||||
decrRefCount(dec);
|
decrRefCount(dec);
|
||||||
decrRefCount(ele);
|
decrRefCount(ele);
|
||||||
}
|
}
|
||||||
@ -1437,7 +1437,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
/* It's faster to expand the dict to the right size asap in order
|
/* It's faster to expand the dict to the right size asap in order
|
||||||
* to avoid rehashing */
|
* to avoid rehashing */
|
||||||
if (len > DICT_HT_INITIAL_SIZE)
|
if (len > DICT_HT_INITIAL_SIZE)
|
||||||
dictExpand(ptrFromObj(o),len);
|
dictExpand((dict*)ptrFromObj(o),len);
|
||||||
} else {
|
} else {
|
||||||
o = createIntsetObject();
|
o = createIntsetObject();
|
||||||
}
|
}
|
||||||
@ -1447,16 +1447,16 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
long long llval;
|
long long llval;
|
||||||
sds sdsele;
|
sds sdsele;
|
||||||
|
|
||||||
if ((sdsele = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
if ((sdsele = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
||||||
== NULL) return NULL;
|
== NULL) return NULL;
|
||||||
|
|
||||||
if (o->encoding == OBJ_ENCODING_INTSET) {
|
if (o->encoding == OBJ_ENCODING_INTSET) {
|
||||||
/* Fetch integer value from element. */
|
/* Fetch integer value from element. */
|
||||||
if (isSdsRepresentableAsLongLong(sdsele,&llval) == C_OK) {
|
if (isSdsRepresentableAsLongLong(sdsele,&llval) == C_OK) {
|
||||||
o->m_ptr = intsetAdd(ptrFromObj(o),llval,NULL);
|
o->m_ptr = intsetAdd((intset*)ptrFromObj(o),llval,NULL);
|
||||||
} else {
|
} else {
|
||||||
setTypeConvert(o,OBJ_ENCODING_HT);
|
setTypeConvert(o,OBJ_ENCODING_HT);
|
||||||
dictExpand(ptrFromObj(o),len);
|
dictExpand((dict*)ptrFromObj(o),len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1476,7 +1476,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
|
|
||||||
if ((zsetlen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
if ((zsetlen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
||||||
o = createZsetObject();
|
o = createZsetObject();
|
||||||
zs = ptrFromObj(o);
|
zs = (zset*)ptrFromObj(o);
|
||||||
|
|
||||||
if (zsetlen > DICT_HT_INITIAL_SIZE)
|
if (zsetlen > DICT_HT_INITIAL_SIZE)
|
||||||
dictExpand(zs->pdict,zsetlen);
|
dictExpand(zs->pdict,zsetlen);
|
||||||
@ -1487,7 +1487,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
double score;
|
double score;
|
||||||
zskiplistNode *znode;
|
zskiplistNode *znode;
|
||||||
|
|
||||||
if ((sdsele = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
if ((sdsele = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
||||||
== NULL) return NULL;
|
== NULL) return NULL;
|
||||||
|
|
||||||
if (rdbtype == RDB_TYPE_ZSET_2) {
|
if (rdbtype == RDB_TYPE_ZSET_2) {
|
||||||
@ -1525,15 +1525,15 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
while (o->encoding == OBJ_ENCODING_ZIPLIST && len > 0) {
|
while (o->encoding == OBJ_ENCODING_ZIPLIST && len > 0) {
|
||||||
len--;
|
len--;
|
||||||
/* Load raw strings */
|
/* Load raw strings */
|
||||||
if ((field = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
if ((field = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
||||||
== NULL) return NULL;
|
== NULL) return NULL;
|
||||||
if ((value = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
if ((value = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
||||||
== NULL) return NULL;
|
== NULL) return NULL;
|
||||||
|
|
||||||
/* Add pair to ziplist */
|
/* Add pair to ziplist */
|
||||||
o->m_ptr = ziplistPush(ptrFromObj(o), (unsigned char*)field,
|
o->m_ptr = ziplistPush((unsigned char*)ptrFromObj(o), (unsigned char*)field,
|
||||||
sdslen(field), ZIPLIST_TAIL);
|
sdslen(field), ZIPLIST_TAIL);
|
||||||
o->m_ptr = ziplistPush(ptrFromObj(o), (unsigned char*)value,
|
o->m_ptr = ziplistPush((unsigned char*)ptrFromObj(o), (unsigned char*)value,
|
||||||
sdslen(value), ZIPLIST_TAIL);
|
sdslen(value), ZIPLIST_TAIL);
|
||||||
|
|
||||||
/* Convert to hash table if size threshold is exceeded */
|
/* Convert to hash table if size threshold is exceeded */
|
||||||
@ -1550,15 +1550,15 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (o->encoding == OBJ_ENCODING_HT && len > DICT_HT_INITIAL_SIZE)
|
if (o->encoding == OBJ_ENCODING_HT && len > DICT_HT_INITIAL_SIZE)
|
||||||
dictExpand(ptrFromObj(o),len);
|
dictExpand((dict*)ptrFromObj(o),len);
|
||||||
|
|
||||||
/* Load remaining fields and values into the hash table */
|
/* Load remaining fields and values into the hash table */
|
||||||
while (o->encoding == OBJ_ENCODING_HT && len > 0) {
|
while (o->encoding == OBJ_ENCODING_HT && len > 0) {
|
||||||
len--;
|
len--;
|
||||||
/* Load encoded strings */
|
/* Load encoded strings */
|
||||||
if ((field = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
if ((field = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
||||||
== NULL) return NULL;
|
== NULL) return NULL;
|
||||||
if ((value = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
if ((value = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
|
||||||
== NULL) return NULL;
|
== NULL) return NULL;
|
||||||
|
|
||||||
/* Add pair to hash table */
|
/* Add pair to hash table */
|
||||||
@ -1573,14 +1573,14 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
} else if (rdbtype == RDB_TYPE_LIST_QUICKLIST) {
|
} else if (rdbtype == RDB_TYPE_LIST_QUICKLIST) {
|
||||||
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
||||||
o = createQuicklistObject();
|
o = createQuicklistObject();
|
||||||
quicklistSetOptions(ptrFromObj(o), server.list_max_ziplist_size,
|
quicklistSetOptions((quicklist*)ptrFromObj(o), server.list_max_ziplist_size,
|
||||||
server.list_compress_depth);
|
server.list_compress_depth);
|
||||||
|
|
||||||
while (len--) {
|
while (len--) {
|
||||||
unsigned char *zl =
|
unsigned char *zl = (unsigned char*)
|
||||||
rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN,NULL);
|
rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN,NULL);
|
||||||
if (zl == NULL) return NULL;
|
if (zl == NULL) return NULL;
|
||||||
quicklistAppendZiplist(ptrFromObj(o), zl);
|
quicklistAppendZiplist((quicklist*)ptrFromObj(o), zl);
|
||||||
}
|
}
|
||||||
} else if (rdbtype == RDB_TYPE_HASH_ZIPMAP ||
|
} else if (rdbtype == RDB_TYPE_HASH_ZIPMAP ||
|
||||||
rdbtype == RDB_TYPE_LIST_ZIPLIST ||
|
rdbtype == RDB_TYPE_LIST_ZIPLIST ||
|
||||||
@ -1588,7 +1588,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
rdbtype == RDB_TYPE_ZSET_ZIPLIST ||
|
rdbtype == RDB_TYPE_ZSET_ZIPLIST ||
|
||||||
rdbtype == RDB_TYPE_HASH_ZIPLIST)
|
rdbtype == RDB_TYPE_HASH_ZIPLIST)
|
||||||
{
|
{
|
||||||
unsigned char *encoded =
|
unsigned char *encoded = (unsigned char*)
|
||||||
rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN,NULL);
|
rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN,NULL);
|
||||||
if (encoded == NULL) return NULL;
|
if (encoded == NULL) return NULL;
|
||||||
o = createObject(OBJ_STRING,encoded); /* Obj type fixed below. */
|
o = createObject(OBJ_STRING,encoded); /* Obj type fixed below. */
|
||||||
@ -1605,7 +1605,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
* when loading dumps created by Redis 2.4 gets deprecated. */
|
* when loading dumps created by Redis 2.4 gets deprecated. */
|
||||||
{
|
{
|
||||||
unsigned char *zl = ziplistNew();
|
unsigned char *zl = ziplistNew();
|
||||||
unsigned char *zi = zipmapRewind(ptrFromObj(o));
|
unsigned char *zi = zipmapRewind((unsigned char*)ptrFromObj(o));
|
||||||
unsigned char *fstr, *vstr;
|
unsigned char *fstr, *vstr;
|
||||||
unsigned int flen, vlen;
|
unsigned int flen, vlen;
|
||||||
unsigned int maxlen = 0;
|
unsigned int maxlen = 0;
|
||||||
@ -1637,7 +1637,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
case RDB_TYPE_SET_INTSET:
|
case RDB_TYPE_SET_INTSET:
|
||||||
o->type = OBJ_SET;
|
o->type = OBJ_SET;
|
||||||
o->encoding = OBJ_ENCODING_INTSET;
|
o->encoding = OBJ_ENCODING_INTSET;
|
||||||
if (intsetLen(ptrFromObj(o)) > server.set_max_intset_entries)
|
if (intsetLen((intset*)ptrFromObj(o)) > server.set_max_intset_entries)
|
||||||
setTypeConvert(o,OBJ_ENCODING_HT);
|
setTypeConvert(o,OBJ_ENCODING_HT);
|
||||||
break;
|
break;
|
||||||
case RDB_TYPE_ZSET_ZIPLIST:
|
case RDB_TYPE_ZSET_ZIPLIST:
|
||||||
@ -1658,14 +1658,14 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
}
|
}
|
||||||
} else if (rdbtype == RDB_TYPE_STREAM_LISTPACKS) {
|
} else if (rdbtype == RDB_TYPE_STREAM_LISTPACKS) {
|
||||||
o = createStreamObject();
|
o = createStreamObject();
|
||||||
stream *s = ptrFromObj(o);
|
stream *s = (stream*)ptrFromObj(o);
|
||||||
uint64_t listpacks = rdbLoadLen(rdb,NULL);
|
uint64_t listpacks = rdbLoadLen(rdb,NULL);
|
||||||
|
|
||||||
while(listpacks--) {
|
while(listpacks--) {
|
||||||
/* Get the master ID, the one we'll use as key of the radix tree
|
/* Get the master ID, the one we'll use as key of the radix tree
|
||||||
* node: the entries inside the listpack itself are delta-encoded
|
* node: the entries inside the listpack itself are delta-encoded
|
||||||
* relatively to this ID. */
|
* relatively to this ID. */
|
||||||
sds nodekey = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL);
|
sds nodekey = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL);
|
||||||
if (nodekey == NULL) {
|
if (nodekey == NULL) {
|
||||||
rdbExitReportCorruptRDB("Stream master ID loading failed: invalid encoding or I/O error.");
|
rdbExitReportCorruptRDB("Stream master ID loading failed: invalid encoding or I/O error.");
|
||||||
}
|
}
|
||||||
@ -1675,7 +1675,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load the listpack. */
|
/* Load the listpack. */
|
||||||
unsigned char *lp =
|
unsigned char *lp = (unsigned char*)
|
||||||
rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN,NULL);
|
rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN,NULL);
|
||||||
if (lp == NULL) return NULL;
|
if (lp == NULL) return NULL;
|
||||||
unsigned char *first = lpFirst(lp);
|
unsigned char *first = lpFirst(lp);
|
||||||
@ -1706,7 +1706,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
* consumer group ASAP and populate its structure as
|
* consumer group ASAP and populate its structure as
|
||||||
* we read more data. */
|
* we read more data. */
|
||||||
streamID cg_id;
|
streamID cg_id;
|
||||||
sds cgname = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL);
|
sds cgname = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL);
|
||||||
if (cgname == NULL) {
|
if (cgname == NULL) {
|
||||||
rdbExitReportCorruptRDB(
|
rdbExitReportCorruptRDB(
|
||||||
"Error reading the consumer group name from Stream");
|
"Error reading the consumer group name from Stream");
|
||||||
@ -1740,7 +1740,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
* consumers and their local PELs. */
|
* consumers and their local PELs. */
|
||||||
size_t consumers_num = rdbLoadLen(rdb,NULL);
|
size_t consumers_num = rdbLoadLen(rdb,NULL);
|
||||||
while(consumers_num--) {
|
while(consumers_num--) {
|
||||||
sds cname = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL);
|
sds cname = (sds)rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL);
|
||||||
if (cname == NULL) {
|
if (cname == NULL) {
|
||||||
rdbExitReportCorruptRDB(
|
rdbExitReportCorruptRDB(
|
||||||
"Error reading the consumer name from Stream group");
|
"Error reading the consumer name from Stream group");
|
||||||
@ -1756,7 +1756,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|||||||
while(pel_size--) {
|
while(pel_size--) {
|
||||||
unsigned char rawid[sizeof(streamID)];
|
unsigned char rawid[sizeof(streamID)];
|
||||||
rdbLoadRaw(rdb,rawid,sizeof(rawid));
|
rdbLoadRaw(rdb,rawid,sizeof(rawid));
|
||||||
streamNACK *nack = raxFind(cgroup->pel,rawid,sizeof(rawid));
|
streamNACK *nack = (streamNACK*)raxFind(cgroup->pel,rawid,sizeof(rawid));
|
||||||
if (nack == raxNotFound)
|
if (nack == raxNotFound)
|
||||||
rdbExitReportCorruptRDB("Consumer entry not found in "
|
rdbExitReportCorruptRDB("Consumer entry not found in "
|
||||||
"group global PEL");
|
"group global PEL");
|
||||||
@ -1880,6 +1880,9 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
|||||||
int type, rdbver;
|
int type, rdbver;
|
||||||
redisDb *db = server.db+0;
|
redisDb *db = server.db+0;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
/* Key-specific attributes, set by opcodes before the key type. */
|
||||||
|
long long lru_idle = -1, lfu_freq = -1, expiretime = -1, now = mstime();
|
||||||
|
long long lru_clock = LRU_CLOCK();
|
||||||
|
|
||||||
rdb->update_cksum = rdbLoadProgressCallback;
|
rdb->update_cksum = rdbLoadProgressCallback;
|
||||||
rdb->max_processing_chunk = server.loading_process_events_interval_bytes;
|
rdb->max_processing_chunk = server.loading_process_events_interval_bytes;
|
||||||
@ -1897,9 +1900,8 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
|||||||
return C_ERR;
|
return C_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Key-specific attributes, set by opcodes before the key type. */
|
now = mstime();
|
||||||
long long lru_idle = -1, lfu_freq = -1, expiretime = -1, now = mstime();
|
lru_clock = LRU_CLOCK();
|
||||||
long long lru_clock = LRU_CLOCK();
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
robj *key, *val;
|
robj *key, *val;
|
||||||
@ -1975,38 +1977,38 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
|||||||
serverLog(LL_NOTICE,"RDB '%s': %s",
|
serverLog(LL_NOTICE,"RDB '%s': %s",
|
||||||
(char*)ptrFromObj(auxkey),
|
(char*)ptrFromObj(auxkey),
|
||||||
(char*)ptrFromObj(auxval));
|
(char*)ptrFromObj(auxval));
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"repl-stream-db")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"repl-stream-db")) {
|
||||||
if (rsi) rsi->repl_stream_db = atoi(ptrFromObj(auxval));
|
if (rsi) rsi->repl_stream_db = atoi(szFromObj(auxval));
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"repl-id")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"repl-id")) {
|
||||||
if (rsi && sdslen(ptrFromObj(auxval)) == CONFIG_RUN_ID_SIZE) {
|
if (rsi && sdslen(szFromObj(auxval)) == CONFIG_RUN_ID_SIZE) {
|
||||||
memcpy(rsi->repl_id,ptrFromObj(auxval),CONFIG_RUN_ID_SIZE+1);
|
memcpy(rsi->repl_id,ptrFromObj(auxval),CONFIG_RUN_ID_SIZE+1);
|
||||||
rsi->repl_id_is_set = 1;
|
rsi->repl_id_is_set = 1;
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"repl-offset")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"repl-offset")) {
|
||||||
if (rsi) rsi->repl_offset = strtoll(ptrFromObj(auxval),NULL,10);
|
if (rsi) rsi->repl_offset = strtoll(szFromObj(auxval),NULL,10);
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"lua")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"lua")) {
|
||||||
/* Load the script back in memory. */
|
/* Load the script back in memory. */
|
||||||
if (luaCreateFunction(NULL,server.lua,auxval) == NULL) {
|
if (luaCreateFunction(NULL,server.lua,auxval) == NULL) {
|
||||||
rdbExitReportCorruptRDB(
|
rdbExitReportCorruptRDB(
|
||||||
"Can't load Lua script from RDB file! "
|
"Can't load Lua script from RDB file! "
|
||||||
"BODY: %s", ptrFromObj(auxval));
|
"BODY: %s", ptrFromObj(auxval));
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"redis-ver")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"redis-ver")) {
|
||||||
serverLog(LL_NOTICE,"Loading RDB produced by version %s",
|
serverLog(LL_NOTICE,"Loading RDB produced by version %s",
|
||||||
(const char*)ptrFromObj(auxval));
|
(const char*)ptrFromObj(auxval));
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"ctime")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"ctime")) {
|
||||||
time_t age = time(NULL)-strtol(ptrFromObj(auxval),NULL,10);
|
time_t age = time(NULL)-strtol(szFromObj(auxval),NULL,10);
|
||||||
if (age < 0) age = 0;
|
if (age < 0) age = 0;
|
||||||
serverLog(LL_NOTICE,"RDB age %ld seconds",
|
serverLog(LL_NOTICE,"RDB age %ld seconds",
|
||||||
(unsigned long) age);
|
(unsigned long) age);
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"used-mem")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"used-mem")) {
|
||||||
long long usedmem = strtoll(ptrFromObj(auxval),NULL,10);
|
long long usedmem = strtoll(szFromObj(auxval),NULL,10);
|
||||||
serverLog(LL_NOTICE,"RDB memory usage when created %.2f Mb",
|
serverLog(LL_NOTICE,"RDB memory usage when created %.2f Mb",
|
||||||
(double) usedmem / (1024*1024));
|
(double) usedmem / (1024*1024));
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"aof-preamble")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"aof-preamble")) {
|
||||||
long long haspreamble = strtoll(ptrFromObj(auxval),NULL,10);
|
long long haspreamble = strtoll(szFromObj(auxval),NULL,10);
|
||||||
if (haspreamble) serverLog(LL_NOTICE,"RDB has an AOF tail");
|
if (haspreamble) serverLog(LL_NOTICE,"RDB has an AOF tail");
|
||||||
} else if (!strcasecmp(ptrFromObj(auxkey),"redis-bits")) {
|
} else if (!strcasecmp(szFromObj(auxkey),"redis-bits")) {
|
||||||
/* Just ignored. */
|
/* Just ignored. */
|
||||||
} else {
|
} else {
|
||||||
/* We ignore fields we don't understand, as by AUX field
|
/* We ignore fields we don't understand, as by AUX field
|
||||||
@ -2208,7 +2210,7 @@ void backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {
|
|||||||
* If the process returned an error, consider the list of slaves that
|
* If the process returned an error, consider the list of slaves that
|
||||||
* can continue to be empty, so that it's just a special case of the
|
* can continue to be empty, so that it's just a special case of the
|
||||||
* normal code path. */
|
* normal code path. */
|
||||||
ok_slaves = zmalloc(sizeof(uint64_t), MALLOC_LOCAL); /* Make space for the count. */
|
ok_slaves = (uint64_t*)zmalloc(sizeof(uint64_t), MALLOC_LOCAL); /* Make space for the count. */
|
||||||
ok_slaves[0] = 0;
|
ok_slaves[0] = 0;
|
||||||
if (!bysignal && exitcode == 0) {
|
if (!bysignal && exitcode == 0) {
|
||||||
int readlen = sizeof(uint64_t);
|
int readlen = sizeof(uint64_t);
|
||||||
@ -2220,7 +2222,7 @@ void backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {
|
|||||||
|
|
||||||
/* Make space for enough elements as specified by the first
|
/* Make space for enough elements as specified by the first
|
||||||
* uint64_t element in the array. */
|
* uint64_t element in the array. */
|
||||||
ok_slaves = zrealloc(ok_slaves,sizeof(uint64_t)+readlen, MALLOC_LOCAL);
|
ok_slaves = (uint64_t*)zrealloc(ok_slaves,sizeof(uint64_t)+readlen, MALLOC_LOCAL);
|
||||||
if (readlen &&
|
if (readlen &&
|
||||||
read(server.rdb_pipe_read_result_from_child, ok_slaves+1,
|
read(server.rdb_pipe_read_result_from_child, ok_slaves+1,
|
||||||
readlen) != readlen)
|
readlen) != readlen)
|
||||||
@ -2240,7 +2242,7 @@ void backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {
|
|||||||
|
|
||||||
listRewind(server.slaves,&li);
|
listRewind(server.slaves,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *slave = ln->value;
|
client *slave = (client*)ln->value;
|
||||||
|
|
||||||
if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {
|
if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {
|
||||||
uint64_t j;
|
uint64_t j;
|
||||||
@ -2326,16 +2328,16 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) {
|
|||||||
|
|
||||||
/* Collect the file descriptors of the slaves we want to transfer
|
/* Collect the file descriptors of the slaves we want to transfer
|
||||||
* the RDB to, which are i WAIT_BGSAVE_START state. */
|
* the RDB to, which are i WAIT_BGSAVE_START state. */
|
||||||
fds = zmalloc(sizeof(int)*listLength(server.slaves), MALLOC_LOCAL);
|
fds = (int*)zmalloc(sizeof(int)*listLength(server.slaves), MALLOC_LOCAL);
|
||||||
/* We also allocate an array of corresponding client IDs. This will
|
/* We also allocate an array of corresponding client IDs. This will
|
||||||
* be useful for the child process in order to build the report
|
* be useful for the child process in order to build the report
|
||||||
* (sent via unix pipe) that will be sent to the parent. */
|
* (sent via unix pipe) that will be sent to the parent. */
|
||||||
clientids = zmalloc(sizeof(uint64_t)*listLength(server.slaves), MALLOC_LOCAL);
|
clientids = (uint64_t*)zmalloc(sizeof(uint64_t)*listLength(server.slaves), MALLOC_LOCAL);
|
||||||
numfds = 0;
|
numfds = 0;
|
||||||
|
|
||||||
listRewind(server.slaves,&li);
|
listRewind(server.slaves,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *slave = ln->value;
|
client *slave = (client*)ln->value;
|
||||||
|
|
||||||
if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {
|
if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {
|
||||||
clientids[numfds] = slave->id;
|
clientids[numfds] = slave->id;
|
||||||
@ -2395,7 +2397,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) {
|
|||||||
* set to 0 if the replication process terminated with a success
|
* set to 0 if the replication process terminated with a success
|
||||||
* or the error code if an error occurred. */
|
* or the error code if an error occurred. */
|
||||||
void *msg = zmalloc(sizeof(uint64_t)*(1+2*numfds), MALLOC_LOCAL);
|
void *msg = zmalloc(sizeof(uint64_t)*(1+2*numfds), MALLOC_LOCAL);
|
||||||
uint64_t *len = msg;
|
uint64_t *len = (uint64_t*)msg;
|
||||||
uint64_t *ids = len+1;
|
uint64_t *ids = len+1;
|
||||||
int j, msglen;
|
int j, msglen;
|
||||||
|
|
||||||
@ -2432,7 +2434,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) {
|
|||||||
* replicationSetupSlaveForFullResync() turned it into BGSAVE_END */
|
* replicationSetupSlaveForFullResync() turned it into BGSAVE_END */
|
||||||
listRewind(server.slaves,&li);
|
listRewind(server.slaves,&li);
|
||||||
while((ln = listNext(&li))) {
|
while((ln = listNext(&li))) {
|
||||||
client *slave = ln->value;
|
client *slave = (client*)ln->value;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < numfds; j++) {
|
for (j = 0; j < numfds; j++) {
|
||||||
@ -2485,7 +2487,7 @@ void bgsaveCommand(client *c) {
|
|||||||
/* The SCHEDULE option changes the behavior of BGSAVE when an AOF rewrite
|
/* The SCHEDULE option changes the behavior of BGSAVE when an AOF rewrite
|
||||||
* is in progress. Instead of returning an error a BGSAVE gets scheduled. */
|
* is in progress. Instead of returning an error a BGSAVE gets scheduled. */
|
||||||
if (c->argc > 1) {
|
if (c->argc > 1) {
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"schedule")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"schedule")) {
|
||||||
schedule = 1;
|
schedule = 1;
|
||||||
} else {
|
} else {
|
||||||
addReply(c,shared.syntaxerr);
|
addReply(c,shared.syntaxerr);
|
||||||
@ -2550,7 +2552,7 @@ rdbSaveInfo *rdbPopulateSaveInfo(rdbSaveInfo *rsi) {
|
|||||||
// BUGBUG, warn user about this incomplete implementation
|
// BUGBUG, warn user about this incomplete implementation
|
||||||
serverLog(LL_WARNING, "Warning: Only backing up first master's information in RDB");
|
serverLog(LL_WARNING, "Warning: Only backing up first master's information in RDB");
|
||||||
}
|
}
|
||||||
struct redisMaster *miFirst = listLength(server.masters) ? listNodeValue(listFirst(server.masters)) : NULL;
|
struct redisMaster *miFirst = (redisMaster*)(listLength(server.masters) ? listNodeValue(listFirst(server.masters)) : NULL);
|
||||||
|
|
||||||
/* If the instance is a slave we need a connected master
|
/* If the instance is a slave we need a connected master
|
||||||
* in order to fetch the currently selected DB. */
|
* in order to fetch the currently selected DB. */
|
@ -151,7 +151,7 @@ void backgroundSaveDoneHandler(int exitcode, int bysignal);
|
|||||||
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime);
|
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime);
|
||||||
robj *rdbLoadStringObject(rio *rdb);
|
robj *rdbLoadStringObject(rio *rdb);
|
||||||
ssize_t rdbSaveStringObject(rio *rdb, robj *obj);
|
ssize_t rdbSaveStringObject(rio *rdb, robj *obj);
|
||||||
ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len);
|
ssize_t rdbSaveRawString(rio *rdb, const unsigned char *s, size_t len);
|
||||||
void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr);
|
void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr);
|
||||||
int rdbSaveBinaryDoubleValue(rio *rdb, double val);
|
int rdbSaveBinaryDoubleValue(rio *rdb, double val);
|
||||||
int rdbLoadBinaryDoubleValue(rio *rdb, double *val);
|
int rdbLoadBinaryDoubleValue(rio *rdb, double *val);
|
||||||
|
@ -41,10 +41,11 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
extern "C" {
|
||||||
#include <sds.h> /* Use hiredis sds. */
|
#include <sds.h> /* Use hiredis sds. */
|
||||||
#include "ae.h"
|
|
||||||
#include "hiredis.h"
|
#include "hiredis.h"
|
||||||
|
}
|
||||||
|
#include "ae.h"
|
||||||
#include "adlist.h"
|
#include "adlist.h"
|
||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
#include "zmalloc.h"
|
#include "zmalloc.h"
|
||||||
@ -231,7 +232,7 @@ static int dictSdsKeyCompare(void *privdata, const void *key1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* _serverAssert is needed by dict */
|
/* _serverAssert is needed by dict */
|
||||||
void _serverAssert(const char *estr, const char *file, int line) {
|
extern "C" void _serverAssert(const char *estr, const char *file, int line) {
|
||||||
fprintf(stderr, "=== ASSERTION FAILED ===");
|
fprintf(stderr, "=== ASSERTION FAILED ===");
|
||||||
fprintf(stderr, "==> %s:%d '%s' is not true",file,line,estr);
|
fprintf(stderr, "==> %s:%d '%s' is not true",file,line,estr);
|
||||||
*((char*)-1) = 'x';
|
*((char*)-1) = 'x';
|
||||||
@ -240,7 +241,9 @@ void _serverAssert(const char *estr, const char *file, int line) {
|
|||||||
static redisConfig *getRedisConfig(const char *ip, int port,
|
static redisConfig *getRedisConfig(const char *ip, int port,
|
||||||
const char *hostsocket)
|
const char *hostsocket)
|
||||||
{
|
{
|
||||||
redisConfig *cfg = zcalloc(sizeof(*cfg), MALLOC_LOCAL);
|
redisConfig *cfg = (redisConfig*)zcalloc(sizeof(*cfg), MALLOC_LOCAL);
|
||||||
|
int i = 0;
|
||||||
|
void *r = NULL;
|
||||||
if (!cfg) return NULL;
|
if (!cfg) return NULL;
|
||||||
redisContext *c = NULL;
|
redisContext *c = NULL;
|
||||||
redisReply *reply = NULL, *sub_reply = NULL;
|
redisReply *reply = NULL, *sub_reply = NULL;
|
||||||
@ -250,15 +253,14 @@ static redisConfig *getRedisConfig(const char *ip, int port,
|
|||||||
c = redisConnectUnix(hostsocket);
|
c = redisConnectUnix(hostsocket);
|
||||||
if (c == NULL || c->err) {
|
if (c == NULL || c->err) {
|
||||||
fprintf(stderr,"Could not connect to Redis at ");
|
fprintf(stderr,"Could not connect to Redis at ");
|
||||||
char *err = (c != NULL ? c->errstr : "");
|
const char *err = (c != NULL ? c->errstr : "");
|
||||||
if (hostsocket == NULL) fprintf(stderr,"%s:%d: %s\n",ip,port,err);
|
if (hostsocket == NULL) fprintf(stderr,"%s:%d: %s\n",ip,port,err);
|
||||||
else fprintf(stderr,"%s: %s\n",hostsocket,err);
|
else fprintf(stderr,"%s: %s\n",hostsocket,err);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
redisAppendCommand(c, "CONFIG GET %s", "save");
|
redisAppendCommand(c, "CONFIG GET %s", "save");
|
||||||
redisAppendCommand(c, "CONFIG GET %s", "appendonly");
|
redisAppendCommand(c, "CONFIG GET %s", "appendonly");
|
||||||
int i = 0;
|
|
||||||
void *r = NULL;
|
|
||||||
for (; i < 2; i++) {
|
for (; i < 2; i++) {
|
||||||
int res = redisGetReply(c, &r);
|
int res = redisGetReply(c, &r);
|
||||||
if (reply) freeReplyObject(reply);
|
if (reply) freeReplyObject(reply);
|
||||||
@ -270,7 +272,7 @@ static redisConfig *getRedisConfig(const char *ip, int port,
|
|||||||
}
|
}
|
||||||
if (reply->type != REDIS_REPLY_ARRAY || reply->elements < 2) goto fail;
|
if (reply->type != REDIS_REPLY_ARRAY || reply->elements < 2) goto fail;
|
||||||
sub_reply = reply->element[1];
|
sub_reply = reply->element[1];
|
||||||
char *value = sub_reply->str;
|
const char *value = sub_reply->str;
|
||||||
if (!value) value = "";
|
if (!value) value = "";
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: cfg->save = sdsnew(value); break;
|
case 0: cfg->save = sdsnew(value); break;
|
||||||
@ -325,7 +327,7 @@ static void freeAllClients(void) {
|
|||||||
|
|
||||||
while(ln) {
|
while(ln) {
|
||||||
next = ln->next;
|
next = ln->next;
|
||||||
freeClient(ln->value);
|
freeClient((client)ln->value);
|
||||||
ln = next;
|
ln = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +407,7 @@ static void clientDone(client c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||||
client c = privdata;
|
client c = (client)privdata;
|
||||||
void *reply = NULL;
|
void *reply = NULL;
|
||||||
UNUSED(el);
|
UNUSED(el);
|
||||||
UNUSED(fd);
|
UNUSED(fd);
|
||||||
@ -430,7 +432,7 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
|||||||
fprintf(stderr,"Unexpected error reply, exiting...\n");
|
fprintf(stderr,"Unexpected error reply, exiting...\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
redisReply *r = reply;
|
redisReply *r = (redisReply*)reply;
|
||||||
int is_err = (r->type == REDIS_REPLY_ERROR);
|
int is_err = (r->type == REDIS_REPLY_ERROR);
|
||||||
|
|
||||||
if (is_err && config.showerrors) {
|
if (is_err && config.showerrors) {
|
||||||
@ -505,7 +507,7 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||||
client c = privdata;
|
client c = (client)privdata;
|
||||||
UNUSED(el);
|
UNUSED(el);
|
||||||
UNUSED(fd);
|
UNUSED(fd);
|
||||||
UNUSED(mask);
|
UNUSED(mask);
|
||||||
@ -565,10 +567,10 @@ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
|
|||||||
* for arguments randomization.
|
* for arguments randomization.
|
||||||
*
|
*
|
||||||
* Even when cloning another client, prefix commands are applied if needed.*/
|
* Even when cloning another client, prefix commands are applied if needed.*/
|
||||||
static client createClient(char *cmd, size_t len, client from, int thread_id) {
|
static client createClient(const char *cmd, size_t len, client from, int thread_id) {
|
||||||
int j;
|
int j;
|
||||||
int is_cluster_client = (config.cluster_mode && thread_id >= 0);
|
int is_cluster_client = (config.cluster_mode && thread_id >= 0);
|
||||||
client c = zmalloc(sizeof(struct _client), MALLOC_LOCAL);
|
client c = (client)zmalloc(sizeof(struct _client), MALLOC_LOCAL);
|
||||||
|
|
||||||
const char *ip = NULL;
|
const char *ip = NULL;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
@ -653,7 +655,7 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
|
|||||||
if (from) {
|
if (from) {
|
||||||
c->randlen = from->randlen;
|
c->randlen = from->randlen;
|
||||||
c->randfree = 0;
|
c->randfree = 0;
|
||||||
c->randptr = zmalloc(sizeof(char*)*c->randlen, MALLOC_LOCAL);
|
c->randptr = (char**)zmalloc(sizeof(char*)*c->randlen, MALLOC_LOCAL);
|
||||||
/* copy the offsets. */
|
/* copy the offsets. */
|
||||||
for (j = 0; j < (int)c->randlen; j++) {
|
for (j = 0; j < (int)c->randlen; j++) {
|
||||||
c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf);
|
c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf);
|
||||||
@ -665,10 +667,10 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
|
|||||||
|
|
||||||
c->randlen = 0;
|
c->randlen = 0;
|
||||||
c->randfree = RANDPTR_INITIAL_SIZE;
|
c->randfree = RANDPTR_INITIAL_SIZE;
|
||||||
c->randptr = zmalloc(sizeof(char*)*c->randfree, MALLOC_LOCAL);
|
c->randptr = (char**)zmalloc(sizeof(char*)*c->randfree, MALLOC_LOCAL);
|
||||||
while ((p = strstr(p,"__rand_int__")) != NULL) {
|
while ((p = strstr(p,"__rand_int__")) != NULL) {
|
||||||
if (c->randfree == 0) {
|
if (c->randfree == 0) {
|
||||||
c->randptr = zrealloc(c->randptr,sizeof(char*)*c->randlen*2, MALLOC_LOCAL);
|
c->randptr = (char**)zrealloc(c->randptr,sizeof(char*)*c->randlen*2, MALLOC_LOCAL);
|
||||||
c->randfree += c->randlen;
|
c->randfree += c->randlen;
|
||||||
}
|
}
|
||||||
c->randptr[c->randlen++] = p;
|
c->randptr[c->randlen++] = p;
|
||||||
@ -682,7 +684,7 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
|
|||||||
if (from) {
|
if (from) {
|
||||||
c->staglen = from->staglen;
|
c->staglen = from->staglen;
|
||||||
c->stagfree = 0;
|
c->stagfree = 0;
|
||||||
c->stagptr = zmalloc(sizeof(char*)*c->staglen, MALLOC_LOCAL);
|
c->stagptr = (char**)zmalloc(sizeof(char*)*c->staglen, MALLOC_LOCAL);
|
||||||
/* copy the offsets. */
|
/* copy the offsets. */
|
||||||
for (j = 0; j < (int)c->staglen; j++) {
|
for (j = 0; j < (int)c->staglen; j++) {
|
||||||
c->stagptr[j] = c->obuf + (from->stagptr[j]-from->obuf);
|
c->stagptr[j] = c->obuf + (from->stagptr[j]-from->obuf);
|
||||||
@ -694,10 +696,10 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
|
|||||||
|
|
||||||
c->staglen = 0;
|
c->staglen = 0;
|
||||||
c->stagfree = RANDPTR_INITIAL_SIZE;
|
c->stagfree = RANDPTR_INITIAL_SIZE;
|
||||||
c->stagptr = zmalloc(sizeof(char*)*c->stagfree, MALLOC_LOCAL);
|
c->stagptr = (char**)zmalloc(sizeof(char*)*c->stagfree, MALLOC_LOCAL);
|
||||||
while ((p = strstr(p,"{tag}")) != NULL) {
|
while ((p = strstr(p,"{tag}")) != NULL) {
|
||||||
if (c->stagfree == 0) {
|
if (c->stagfree == 0) {
|
||||||
c->stagptr = zrealloc(c->stagptr,
|
c->stagptr = (char**)zrealloc(c->stagptr,
|
||||||
sizeof(char*) * c->staglen*2, MALLOC_LOCAL);
|
sizeof(char*) * c->staglen*2, MALLOC_LOCAL);
|
||||||
c->stagfree += c->staglen;
|
c->stagfree += c->staglen;
|
||||||
}
|
}
|
||||||
@ -821,7 +823,7 @@ static void showLatencyReport(void) {
|
|||||||
static void initBenchmarkThreads() {
|
static void initBenchmarkThreads() {
|
||||||
int i;
|
int i;
|
||||||
if (config.threads) freeBenchmarkThreads();
|
if (config.threads) freeBenchmarkThreads();
|
||||||
config.threads = zmalloc(config.num_threads * sizeof(benchmarkThread*), MALLOC_LOCAL);
|
config.threads = (benchmarkThread**)zmalloc(config.num_threads * sizeof(benchmarkThread*), MALLOC_LOCAL);
|
||||||
for (i = 0; i < config.num_threads; i++) {
|
for (i = 0; i < config.num_threads; i++) {
|
||||||
benchmarkThread *thread = createBenchmarkThread(i);
|
benchmarkThread *thread = createBenchmarkThread(i);
|
||||||
config.threads[i] = thread;
|
config.threads[i] = thread;
|
||||||
@ -841,7 +843,7 @@ static void startBenchmarkThreads() {
|
|||||||
pthread_join(config.threads[i]->thread, NULL);
|
pthread_join(config.threads[i]->thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void benchmark(char *title, char *cmd, int len) {
|
static void benchmark(const char *title, const char *cmd, int len) {
|
||||||
client c;
|
client c;
|
||||||
|
|
||||||
config.title = title;
|
config.title = title;
|
||||||
@ -867,7 +869,7 @@ static void benchmark(char *title, char *cmd, int len) {
|
|||||||
/* Thread functions. */
|
/* Thread functions. */
|
||||||
|
|
||||||
static benchmarkThread *createBenchmarkThread(int index) {
|
static benchmarkThread *createBenchmarkThread(int index) {
|
||||||
benchmarkThread *thread = zmalloc(sizeof(*thread), MALLOC_LOCAL);
|
benchmarkThread *thread = (benchmarkThread*)zmalloc(sizeof(*thread), MALLOC_LOCAL);
|
||||||
if (thread == NULL) return NULL;
|
if (thread == NULL) return NULL;
|
||||||
thread->index = index;
|
thread->index = index;
|
||||||
thread->el = aeCreateEventLoop(1024*10);
|
thread->el = aeCreateEventLoop(1024*10);
|
||||||
@ -899,7 +901,7 @@ static void *execBenchmarkThread(void *ptr) {
|
|||||||
/* Cluster helper functions. */
|
/* Cluster helper functions. */
|
||||||
|
|
||||||
static clusterNode *createClusterNode(char *ip, int port) {
|
static clusterNode *createClusterNode(char *ip, int port) {
|
||||||
clusterNode *node = zmalloc(sizeof(*node), MALLOC_LOCAL);
|
clusterNode *node = (clusterNode*)zmalloc(sizeof(*node), MALLOC_LOCAL);
|
||||||
if (!node) return NULL;
|
if (!node) return NULL;
|
||||||
node->ip = ip;
|
node->ip = ip;
|
||||||
node->port = port;
|
node->port = port;
|
||||||
@ -907,7 +909,7 @@ static clusterNode *createClusterNode(char *ip, int port) {
|
|||||||
node->flags = 0;
|
node->flags = 0;
|
||||||
node->replicate = NULL;
|
node->replicate = NULL;
|
||||||
node->replicas_count = 0;
|
node->replicas_count = 0;
|
||||||
node->slots = zmalloc(CLUSTER_SLOTS * sizeof(int), MALLOC_LOCAL);
|
node->slots = (int*)zmalloc(CLUSTER_SLOTS * sizeof(int), MALLOC_LOCAL);
|
||||||
node->slots_count = 0;
|
node->slots_count = 0;
|
||||||
node->current_slot_index = 0;
|
node->current_slot_index = 0;
|
||||||
node->updated_slots = NULL;
|
node->updated_slots = NULL;
|
||||||
@ -953,7 +955,7 @@ static void freeClusterNodes() {
|
|||||||
|
|
||||||
static clusterNode **addClusterNode(clusterNode *node) {
|
static clusterNode **addClusterNode(clusterNode *node) {
|
||||||
int count = config.cluster_node_count + 1;
|
int count = config.cluster_node_count + 1;
|
||||||
config.cluster_nodes = zrealloc(config.cluster_nodes,
|
config.cluster_nodes = (clusterNode**)zrealloc(config.cluster_nodes,
|
||||||
count * sizeof(*node), MALLOC_LOCAL);
|
count * sizeof(*node), MALLOC_LOCAL);
|
||||||
if (!config.cluster_nodes) return NULL;
|
if (!config.cluster_nodes) return NULL;
|
||||||
config.cluster_nodes[config.cluster_node_count++] = node;
|
config.cluster_nodes[config.cluster_node_count++] = node;
|
||||||
@ -964,6 +966,7 @@ static int fetchClusterConfiguration() {
|
|||||||
int success = 1;
|
int success = 1;
|
||||||
redisContext *ctx = NULL;
|
redisContext *ctx = NULL;
|
||||||
redisReply *reply = NULL;
|
redisReply *reply = NULL;
|
||||||
|
char *lines = reply->str, *p, *line;
|
||||||
if (config.hostsocket == NULL)
|
if (config.hostsocket == NULL)
|
||||||
ctx = redisConnect(config.hostip,config.hostport);
|
ctx = redisConnect(config.hostip,config.hostport);
|
||||||
else
|
else
|
||||||
@ -979,7 +982,7 @@ static int fetchClusterConfiguration() {
|
|||||||
clusterNode *firstNode = createClusterNode((char *) config.hostip,
|
clusterNode *firstNode = createClusterNode((char *) config.hostip,
|
||||||
config.hostport);
|
config.hostport);
|
||||||
if (!firstNode) {success = 0; goto cleanup;}
|
if (!firstNode) {success = 0; goto cleanup;}
|
||||||
reply = redisCommand(ctx, "CLUSTER NODES");
|
reply = (redisReply*)redisCommand(ctx, "CLUSTER NODES");
|
||||||
success = (reply != NULL);
|
success = (reply != NULL);
|
||||||
if (!success) goto cleanup;
|
if (!success) goto cleanup;
|
||||||
success = (reply->type != REDIS_REPLY_ERROR);
|
success = (reply->type != REDIS_REPLY_ERROR);
|
||||||
@ -993,7 +996,7 @@ static int fetchClusterConfiguration() {
|
|||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
char *lines = reply->str, *p, *line;
|
lines = reply->str;
|
||||||
while ((p = strstr(lines, "\n")) != NULL) {
|
while ((p = strstr(lines, "\n")) != NULL) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
line = lines;
|
line = lines;
|
||||||
@ -1077,7 +1080,7 @@ static int fetchClusterConfiguration() {
|
|||||||
sds dst = sdsnew(p);
|
sds dst = sdsnew(p);
|
||||||
node->migrating_count += 2;
|
node->migrating_count += 2;
|
||||||
node->migrating =
|
node->migrating =
|
||||||
zrealloc(node->migrating,
|
(char**)zrealloc(node->migrating,
|
||||||
(node->migrating_count * sizeof(sds)), MALLOC_LOCAL);
|
(node->migrating_count * sizeof(sds)), MALLOC_LOCAL);
|
||||||
node->migrating[node->migrating_count - 2] =
|
node->migrating[node->migrating_count - 2] =
|
||||||
slot;
|
slot;
|
||||||
@ -1091,7 +1094,7 @@ static int fetchClusterConfiguration() {
|
|||||||
sds slot = sdsnew(slotsdef);
|
sds slot = sdsnew(slotsdef);
|
||||||
sds src = sdsnew(p);
|
sds src = sdsnew(p);
|
||||||
node->importing_count += 2;
|
node->importing_count += 2;
|
||||||
node->importing = zrealloc(node->importing,
|
node->importing = (char**)zrealloc(node->importing,
|
||||||
(node->importing_count * sizeof(sds)), MALLOC_LOCAL);
|
(node->importing_count * sizeof(sds)), MALLOC_LOCAL);
|
||||||
node->importing[node->importing_count - 2] =
|
node->importing[node->importing_count - 2] =
|
||||||
slot;
|
slot;
|
||||||
@ -1183,7 +1186,7 @@ static int fetchClusterSlotsConfiguration(client c) {
|
|||||||
node->updated_slots_count = 0;
|
node->updated_slots_count = 0;
|
||||||
dictReplace(masters, node->name, node) ;
|
dictReplace(masters, node->name, node) ;
|
||||||
}
|
}
|
||||||
reply = redisCommand(ctx, "CLUSTER SLOTS");
|
reply = (redisReply*)redisCommand(ctx, "CLUSTER SLOTS");
|
||||||
if (reply == NULL || reply->type == REDIS_REPLY_ERROR) {
|
if (reply == NULL || reply->type == REDIS_REPLY_ERROR) {
|
||||||
success = 0;
|
success = 0;
|
||||||
if (reply)
|
if (reply)
|
||||||
@ -1211,9 +1214,9 @@ static int fetchClusterSlotsConfiguration(client c) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
sdsfree(name);
|
sdsfree(name);
|
||||||
clusterNode *node = dictGetVal(entry);
|
clusterNode *node = (clusterNode*)dictGetVal(entry);
|
||||||
if (node->updated_slots == NULL)
|
if (node->updated_slots == NULL)
|
||||||
node->updated_slots = zcalloc(CLUSTER_SLOTS * sizeof(int), MALLOC_LOCAL);
|
node->updated_slots = (int*)zcalloc(CLUSTER_SLOTS * sizeof(int), MALLOC_LOCAL);
|
||||||
for (slot = from; slot <= to; slot++)
|
for (slot = from; slot <= to; slot++)
|
||||||
node->updated_slots[node->updated_slots_count++] = slot;
|
node->updated_slots[node->updated_slots_count++] = slot;
|
||||||
}
|
}
|
||||||
@ -1436,7 +1439,7 @@ int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData
|
|||||||
|
|
||||||
/* Return true if the named test was selected using the -t command line
|
/* Return true if the named test was selected using the -t command line
|
||||||
* switch, or if all the tests are selected (no -t passed by user). */
|
* switch, or if all the tests are selected (no -t passed by user). */
|
||||||
int test_is_selected(char *name) {
|
int test_is_selected(const char *name) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int l = strlen(name);
|
int l = strlen(name);
|
||||||
|
|
||||||
@ -1499,7 +1502,7 @@ int main(int argc, const char **argv) {
|
|||||||
argc -= i;
|
argc -= i;
|
||||||
argv += i;
|
argv += i;
|
||||||
|
|
||||||
config.latency = zmalloc(sizeof(long long)*config.requests, MALLOC_LOCAL);
|
config.latency = (long long*)zmalloc(sizeof(long long)*config.requests, MALLOC_LOCAL);
|
||||||
|
|
||||||
if (config.cluster_mode) {
|
if (config.cluster_mode) {
|
||||||
/* Fetch cluster configuration. */
|
/* Fetch cluster configuration. */
|
||||||
@ -1596,7 +1599,7 @@ int main(int argc, const char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Run default benchmark suite. */
|
/* Run default benchmark suite. */
|
||||||
data = zmalloc(config.datasize+1, MALLOC_LOCAL);
|
data = (char*)zmalloc(config.datasize+1, MALLOC_LOCAL);
|
||||||
do {
|
do {
|
||||||
memset(data,'x',config.datasize);
|
memset(data,'x',config.datasize);
|
||||||
data[config.datasize] = '\0';
|
data[config.datasize] = '\0';
|
@ -190,7 +190,7 @@ int redis_check_aof_main(int argc, char **argv) {
|
|||||||
if (has_preamble) {
|
if (has_preamble) {
|
||||||
printf("The AOF appears to start with an RDB preamble.\n"
|
printf("The AOF appears to start with an RDB preamble.\n"
|
||||||
"Checking the RDB preamble to start:\n");
|
"Checking the RDB preamble to start:\n");
|
||||||
if (redis_check_rdb_main(argc,argv,fp) == C_ERR) {
|
if (redis_check_rdb_main(argc,(const char**)argv,fp) == C_ERR) {
|
||||||
printf("RDB preamble of AOF file is not sane, aborting.\n");
|
printf("RDB preamble of AOF file is not sane, aborting.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
@ -37,7 +37,7 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len);
|
|||||||
int rdbCheckMode = 0;
|
int rdbCheckMode = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
rio *rio;
|
::rio *rio;
|
||||||
robj *key; /* Current key we are reading. */
|
robj *key; /* Current key we are reading. */
|
||||||
int key_type; /* Current key type if != -1. */
|
int key_type; /* Current key type if != -1. */
|
||||||
unsigned long keys; /* Number of keys processed. */
|
unsigned long keys; /* Number of keys processed. */
|
||||||
@ -59,7 +59,7 @@ struct {
|
|||||||
#define RDB_CHECK_DOING_READ_LEN 6
|
#define RDB_CHECK_DOING_READ_LEN 6
|
||||||
#define RDB_CHECK_DOING_READ_AUX 7
|
#define RDB_CHECK_DOING_READ_AUX 7
|
||||||
|
|
||||||
char *rdb_check_doing_string[] = {
|
const char *rdb_check_doing_string[] = {
|
||||||
"start",
|
"start",
|
||||||
"read-type",
|
"read-type",
|
||||||
"read-expire",
|
"read-expire",
|
||||||
@ -70,7 +70,7 @@ char *rdb_check_doing_string[] = {
|
|||||||
"read-aux"
|
"read-aux"
|
||||||
};
|
};
|
||||||
|
|
||||||
char *rdb_type_string[] = {
|
const char *rdb_type_string[] = {
|
||||||
"string",
|
"string",
|
||||||
"list-linked",
|
"list-linked",
|
||||||
"set-hashtable",
|
"set-hashtable",
|
||||||
@ -176,7 +176,7 @@ void rdbCheckSetupSignals(void) {
|
|||||||
* 1 is returned.
|
* 1 is returned.
|
||||||
* The file is specified as a filename in 'rdbfilename' if 'fp' is not NULL,
|
* The file is specified as a filename in 'rdbfilename' if 'fp' is not NULL,
|
||||||
* otherwise the already open file 'fp' is checked. */
|
* otherwise the already open file 'fp' is checked. */
|
||||||
int redis_check_rdb(char *rdbfilename, FILE *fp) {
|
int redis_check_rdb(const char *rdbfilename, FILE *fp) {
|
||||||
uint64_t dbid;
|
uint64_t dbid;
|
||||||
int type, rdbver;
|
int type, rdbver;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -339,7 +339,7 @@ err:
|
|||||||
* status code according to success (RDB is sane) or error (RDB is corrupted).
|
* status code according to success (RDB is sane) or error (RDB is corrupted).
|
||||||
* Otherwise if called with a non NULL fp, the function returns C_OK or
|
* Otherwise if called with a non NULL fp, the function returns C_OK or
|
||||||
* C_ERR depending on the success or failure. */
|
* C_ERR depending on the success or failure. */
|
||||||
int redis_check_rdb_main(int argc, char **argv, FILE *fp) {
|
int redis_check_rdb_main(int argc, const char **argv, FILE *fp) {
|
||||||
if (argc != 2 && fp == NULL) {
|
if (argc != 2 && fp == NULL) {
|
||||||
fprintf(stderr, "Usage: %s <rdb-file-name>\n", argv[0]);
|
fprintf(stderr, "Usage: %s <rdb-file-name>\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
933
src/redis-cli-cpphelper.cpp
Normal file
933
src/redis-cli-cpphelper.cpp
Normal file
@ -0,0 +1,933 @@
|
|||||||
|
#include "fmacros.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <hiredis.h>
|
||||||
|
#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */
|
||||||
|
}
|
||||||
|
#include "dict.h"
|
||||||
|
#include "adlist.h"
|
||||||
|
#include "zmalloc.h"
|
||||||
|
#include "storage.h"
|
||||||
|
|
||||||
|
#include "redis-cli.h"
|
||||||
|
|
||||||
|
static dict *clusterManagerGetLinkStatus(void);
|
||||||
|
|
||||||
|
/* The Cluster Manager global structure */
|
||||||
|
struct clusterManager cluster_manager;
|
||||||
|
|
||||||
|
extern "C" uint64_t dictSdsHash(const void *key) {
|
||||||
|
return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int dictSdsKeyCompare(void *privdata, const void *key1,
|
||||||
|
const void *key2)
|
||||||
|
{
|
||||||
|
int l1,l2;
|
||||||
|
DICT_NOTUSED(privdata);
|
||||||
|
|
||||||
|
l1 = sdslen((sds)key1);
|
||||||
|
l2 = sdslen((sds)key2);
|
||||||
|
if (l1 != l2) return 0;
|
||||||
|
return memcmp(key1, key2, l1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void dictSdsDestructor(void *privdata, void *val)
|
||||||
|
{
|
||||||
|
DICT_NOTUSED(privdata);
|
||||||
|
sdsfree((sds)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void dictListDestructor(void *privdata, void *val)
|
||||||
|
{
|
||||||
|
DICT_NOTUSED(privdata);
|
||||||
|
listRelease((list*)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used by clusterManagerFixSlotsCoverage */
|
||||||
|
dict *clusterManagerUncoveredSlots = NULL;
|
||||||
|
|
||||||
|
/* Info about a cluster internal link. */
|
||||||
|
|
||||||
|
typedef struct clusterManagerLink {
|
||||||
|
sds node_name;
|
||||||
|
sds node_addr;
|
||||||
|
int connected;
|
||||||
|
int handshaking;
|
||||||
|
} clusterManagerLink;
|
||||||
|
|
||||||
|
static dictType clusterManagerDictType = {
|
||||||
|
dictSdsHash, /* hash function */
|
||||||
|
NULL, /* key dup */
|
||||||
|
NULL, /* val dup */
|
||||||
|
dictSdsKeyCompare, /* key compare */
|
||||||
|
NULL, /* key destructor */
|
||||||
|
dictSdsDestructor /* val destructor */
|
||||||
|
};
|
||||||
|
|
||||||
|
static dictType clusterManagerLinkDictType = {
|
||||||
|
dictSdsHash, /* hash function */
|
||||||
|
NULL, /* key dup */
|
||||||
|
NULL, /* val dup */
|
||||||
|
dictSdsKeyCompare, /* key compare */
|
||||||
|
dictSdsDestructor, /* key destructor */
|
||||||
|
dictListDestructor /* val destructor */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void freeClusterManager(void) {
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
if (cluster_manager.nodes != NULL) {
|
||||||
|
listRewind(cluster_manager.nodes,&li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
freeClusterManagerNode(n);
|
||||||
|
}
|
||||||
|
listRelease(cluster_manager.nodes);
|
||||||
|
cluster_manager.nodes = NULL;
|
||||||
|
}
|
||||||
|
if (cluster_manager.errors != NULL) {
|
||||||
|
listRewind(cluster_manager.errors,&li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
sds err = (sds)ln->value;
|
||||||
|
sdsfree(err);
|
||||||
|
}
|
||||||
|
listRelease(cluster_manager.errors);
|
||||||
|
cluster_manager.errors = NULL;
|
||||||
|
}
|
||||||
|
if (clusterManagerUncoveredSlots != NULL)
|
||||||
|
dictRelease(clusterManagerUncoveredSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the anti-affinity score, which is a measure of the amount of
|
||||||
|
* violations of anti-affinity in the current cluster layout, that is, how
|
||||||
|
* badly the masters and slaves are distributed in the different IP
|
||||||
|
* addresses so that slaves of the same master are not in the master
|
||||||
|
* host and are also in different hosts.
|
||||||
|
*
|
||||||
|
* The score is calculated as follows:
|
||||||
|
*
|
||||||
|
* SAME_AS_MASTER = 10000 * each slave in the same IP of its master.
|
||||||
|
* SAME_AS_SLAVE = 1 * each slave having the same IP as another slave
|
||||||
|
of the same master.
|
||||||
|
* FINAL_SCORE = SAME_AS_MASTER + SAME_AS_SLAVE
|
||||||
|
*
|
||||||
|
* So a greater score means a worse anti-affinity level, while zero
|
||||||
|
* means perfect anti-affinity.
|
||||||
|
*
|
||||||
|
* The anti affinity optimizator will try to get a score as low as
|
||||||
|
* possible. Since we do not want to sacrifice the fact that slaves should
|
||||||
|
* not be in the same host as the master, we assign 10000 times the score
|
||||||
|
* to this violation, so that we'll optimize for the second factor only
|
||||||
|
* if it does not impact the first one.
|
||||||
|
*
|
||||||
|
* The ipnodes argument is an array of clusterManagerNodeArray, one for
|
||||||
|
* each IP, while ip_count is the total number of IPs in the configuration.
|
||||||
|
*
|
||||||
|
* The function returns the above score, and the list of
|
||||||
|
* offending slaves can be stored into the 'offending' argument,
|
||||||
|
* so that the optimizer can try changing the configuration of the
|
||||||
|
* slaves violating the anti-affinity goals. */
|
||||||
|
int clusterManagerGetAntiAffinityScore(clusterManagerNodeArray *ipnodes,
|
||||||
|
int ip_count, clusterManagerNode ***offending, int *offending_len)
|
||||||
|
{
|
||||||
|
int score = 0, i, j;
|
||||||
|
int node_len = cluster_manager.nodes->len;
|
||||||
|
clusterManagerNode **offending_p = NULL;
|
||||||
|
if (offending != NULL) {
|
||||||
|
*offending = (clusterManagerNode**)zcalloc(node_len * sizeof(clusterManagerNode*), MALLOC_LOCAL);
|
||||||
|
offending_p = *offending;
|
||||||
|
}
|
||||||
|
/* For each set of nodes in the same host, split by
|
||||||
|
* related nodes (masters and slaves which are involved in
|
||||||
|
* replication of each other) */
|
||||||
|
for (i = 0; i < ip_count; i++) {
|
||||||
|
clusterManagerNodeArray *node_array = &(ipnodes[i]);
|
||||||
|
dict *related = dictCreate(&clusterManagerDictType, NULL);
|
||||||
|
char *ip = NULL;
|
||||||
|
for (j = 0; j < node_array->len; j++) {
|
||||||
|
clusterManagerNode *node = node_array->nodes[j];
|
||||||
|
if (node == NULL) continue;
|
||||||
|
if (!ip) ip = node->ip;
|
||||||
|
sds types;
|
||||||
|
/* We always use the Master ID as key. */
|
||||||
|
sds key = (!node->replicate ? node->name : node->replicate);
|
||||||
|
assert(key != NULL);
|
||||||
|
dictEntry *entry = dictFind(related, key);
|
||||||
|
if (entry) types = sdsdup((sds) dictGetVal(entry));
|
||||||
|
else types = sdsempty();
|
||||||
|
/* Master type 'm' is always set as the first character of the
|
||||||
|
* types string. */
|
||||||
|
if (!node->replicate) types = sdscatprintf(types, "m%s", types);
|
||||||
|
else types = sdscat(types, "s");
|
||||||
|
dictReplace(related, key, types);
|
||||||
|
}
|
||||||
|
/* Now it's trivial to check, for each related group having the
|
||||||
|
* same host, what is their local score. */
|
||||||
|
dictIterator *iter = dictGetIterator(related);
|
||||||
|
dictEntry *entry;
|
||||||
|
while ((entry = dictNext(iter)) != NULL) {
|
||||||
|
sds types = (sds) dictGetVal(entry);
|
||||||
|
sds name = (sds) dictGetKey(entry);
|
||||||
|
int typeslen = sdslen(types);
|
||||||
|
if (typeslen < 2) continue;
|
||||||
|
if (types[0] == 'm') score += (10000 * (typeslen - 1));
|
||||||
|
else score += (1 * typeslen);
|
||||||
|
if (offending == NULL) continue;
|
||||||
|
/* Populate the list of offending nodes. */
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
if (n->replicate == NULL) continue;
|
||||||
|
if (!strcmp(n->replicate, name) && !strcmp(n->ip, ip)) {
|
||||||
|
*(offending_p++) = n;
|
||||||
|
if (offending_len != NULL) (*offending_len)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (offending_len != NULL) *offending_len = offending_p - *offending;
|
||||||
|
dictReleaseIterator(iter);
|
||||||
|
dictRelease(related);
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Wait until the cluster configuration is consistent. */
|
||||||
|
extern "C" void clusterManagerWaitForClusterJoin(void) {
|
||||||
|
printf("Waiting for the cluster to join\n");
|
||||||
|
int counter = 0,
|
||||||
|
check_after = CLUSTER_JOIN_CHECK_AFTER +
|
||||||
|
(int)(listLength(cluster_manager.nodes) * 0.15f);
|
||||||
|
while(!clusterManagerIsConfigConsistent()) {
|
||||||
|
printf(".");
|
||||||
|
fflush(stdout);
|
||||||
|
sleep(1);
|
||||||
|
if (++counter > check_after) {
|
||||||
|
dict *status = clusterManagerGetLinkStatus();
|
||||||
|
dictIterator *iter = NULL;
|
||||||
|
if (status != NULL && dictSize(status) > 0) {
|
||||||
|
printf("\n");
|
||||||
|
clusterManagerLogErr("Warning: %d node(s) may "
|
||||||
|
"be unreachable\n", dictSize(status));
|
||||||
|
iter = dictGetIterator(status);
|
||||||
|
dictEntry *entry;
|
||||||
|
while ((entry = dictNext(iter)) != NULL) {
|
||||||
|
sds nodeaddr = (sds) dictGetKey(entry);
|
||||||
|
char *node_ip = NULL;
|
||||||
|
int node_port = 0, node_bus_port = 0;
|
||||||
|
list *from = (list *) dictGetVal(entry);
|
||||||
|
if (parseClusterNodeAddress(nodeaddr, &node_ip,
|
||||||
|
&node_port, &node_bus_port) && node_bus_port) {
|
||||||
|
clusterManagerLogErr(" - The port %d of node %s may "
|
||||||
|
"be unreachable from:\n",
|
||||||
|
node_bus_port, node_ip);
|
||||||
|
} else {
|
||||||
|
clusterManagerLogErr(" - Node %s may be unreachable "
|
||||||
|
"from:\n", nodeaddr);
|
||||||
|
}
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(from, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
sds from_addr = (sds)ln->value;
|
||||||
|
clusterManagerLogErr(" %s\n", from_addr);
|
||||||
|
sdsfree(from_addr);
|
||||||
|
}
|
||||||
|
clusterManagerLogErr("Cluster bus ports must be reachable "
|
||||||
|
"by every node.\nRemember that "
|
||||||
|
"cluster bus ports are different "
|
||||||
|
"from standard instance ports.\n");
|
||||||
|
listEmpty(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iter != NULL) dictReleaseIterator(iter);
|
||||||
|
if (status != NULL) dictRelease(status);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
list *clusterManagerGetDisconnectedLinks(clusterManagerNode *node) {
|
||||||
|
list *links = NULL;
|
||||||
|
char *lines = NULL, *p, *line;
|
||||||
|
redisReply *reply = (redisReply*)CLUSTER_MANAGER_COMMAND(node, "CLUSTER NODES");
|
||||||
|
if (!clusterManagerCheckRedisReply(node, reply, NULL)) goto cleanup;
|
||||||
|
links = listCreate();
|
||||||
|
lines = reply->str;
|
||||||
|
while ((p = strstr(lines, "\n")) != NULL) {
|
||||||
|
int i = 0;
|
||||||
|
*p = '\0';
|
||||||
|
line = lines;
|
||||||
|
lines = p + 1;
|
||||||
|
char *nodename = NULL, *addr = NULL, *flags = NULL, *link_status = NULL;
|
||||||
|
while ((p = strchr(line, ' ')) != NULL) {
|
||||||
|
*p = '\0';
|
||||||
|
char *token = line;
|
||||||
|
line = p + 1;
|
||||||
|
if (i == 0) nodename = token;
|
||||||
|
else if (i == 1) addr = token;
|
||||||
|
else if (i == 2) flags = token;
|
||||||
|
else if (i == 7) link_status = token;
|
||||||
|
else if (i == 8) break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i == 7) link_status = line;
|
||||||
|
if (nodename == NULL || addr == NULL || flags == NULL ||
|
||||||
|
link_status == NULL) continue;
|
||||||
|
if (strstr(flags, "myself") != NULL) continue;
|
||||||
|
int disconnected = ((strstr(flags, "disconnected") != NULL) ||
|
||||||
|
(strstr(link_status, "disconnected")));
|
||||||
|
int handshaking = (strstr(flags, "handshake") != NULL);
|
||||||
|
if (disconnected || handshaking) {
|
||||||
|
clusterManagerLink *link = (clusterManagerLink*)zmalloc(sizeof(*link), MALLOC_LOCAL);
|
||||||
|
link->node_name = sdsnew(nodename);
|
||||||
|
link->node_addr = sdsnew(addr);
|
||||||
|
link->connected = 0;
|
||||||
|
link->handshaking = handshaking;
|
||||||
|
listAddNodeTail(links, link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
if (reply != NULL) freeReplyObject(reply);
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for disconnected cluster links. It returns a dict whose keys
|
||||||
|
* are the unreachable node addresses and the values are lists of
|
||||||
|
* node addresses that cannot reach the unreachable node. */
|
||||||
|
dict *clusterManagerGetLinkStatus(void) {
|
||||||
|
if (cluster_manager.nodes == NULL) return NULL;
|
||||||
|
dict *status = dictCreate(&clusterManagerLinkDictType, NULL);
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *node = (clusterManagerNode*)ln->value;
|
||||||
|
list *links = clusterManagerGetDisconnectedLinks(node);
|
||||||
|
if (links) {
|
||||||
|
listIter lli;
|
||||||
|
listNode *lln;
|
||||||
|
listRewind(links, &lli);
|
||||||
|
while ((lln = listNext(&lli)) != NULL) {
|
||||||
|
clusterManagerLink *link = (clusterManagerLink*)lln->value;
|
||||||
|
list *from = NULL;
|
||||||
|
dictEntry *entry = dictFind(status, link->node_addr);
|
||||||
|
if (entry) from = (list*)dictGetVal(entry);
|
||||||
|
else {
|
||||||
|
from = listCreate();
|
||||||
|
dictAdd(status, sdsdup(link->node_addr), from);
|
||||||
|
}
|
||||||
|
sds myaddr = sdsempty();
|
||||||
|
myaddr = sdscatfmt(myaddr, "%s:%u", node->ip, node->port);
|
||||||
|
listAddNodeTail(from, myaddr);
|
||||||
|
sdsfree(link->node_name);
|
||||||
|
sdsfree(link->node_addr);
|
||||||
|
zfree(link);
|
||||||
|
}
|
||||||
|
listRelease(links);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function returns a random master node, return NULL if none */
|
||||||
|
|
||||||
|
static clusterManagerNode *clusterManagerNodeMasterRandom() {
|
||||||
|
int master_count = 0;
|
||||||
|
int idx;
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE) continue;
|
||||||
|
master_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
idx = rand() % master_count;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE) continue;
|
||||||
|
if (!idx--) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Can not be reached */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clusterManagerFixSlotsCoverage(char *all_slots) {
|
||||||
|
int i, fixed = 0;
|
||||||
|
dictIterator *iter = nullptr;
|
||||||
|
dictEntry *entry = nullptr;
|
||||||
|
list *none = NULL, *single = NULL, *multi = NULL;
|
||||||
|
clusterManagerLogInfo(">>> Fixing slots coverage...\n");
|
||||||
|
printf("List of not covered slots: \n");
|
||||||
|
int uncovered_count = 0;
|
||||||
|
sds log = sdsempty();
|
||||||
|
for (i = 0; i < CLUSTER_MANAGER_SLOTS; i++) {
|
||||||
|
int covered = all_slots[i];
|
||||||
|
if (!covered) {
|
||||||
|
sds key = sdsfromlonglong((long long) i);
|
||||||
|
if (uncovered_count++ > 0) printf(",");
|
||||||
|
printf("%s", (char *) key);
|
||||||
|
list *slot_nodes = listCreate();
|
||||||
|
sds slot_nodes_str = sdsempty();
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE || n->replicate)
|
||||||
|
continue;
|
||||||
|
redisReply *reply = (redisReply*)CLUSTER_MANAGER_COMMAND(n,
|
||||||
|
"CLUSTER GETKEYSINSLOT %d %d", i, 1);
|
||||||
|
if (!clusterManagerCheckRedisReply(n, reply, NULL)) {
|
||||||
|
fixed = -1;
|
||||||
|
if (reply) freeReplyObject(reply);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
assert(reply->type == REDIS_REPLY_ARRAY);
|
||||||
|
if (reply->elements > 0) {
|
||||||
|
listAddNodeTail(slot_nodes, n);
|
||||||
|
if (listLength(slot_nodes) > 1)
|
||||||
|
slot_nodes_str = sdscat(slot_nodes_str, ", ");
|
||||||
|
slot_nodes_str = sdscatfmt(slot_nodes_str,
|
||||||
|
"%s:%u", n->ip, n->port);
|
||||||
|
}
|
||||||
|
freeReplyObject(reply);
|
||||||
|
}
|
||||||
|
log = sdscatfmt(log, "\nSlot %S has keys in %u nodes: %S",
|
||||||
|
key, listLength(slot_nodes), slot_nodes_str);
|
||||||
|
sdsfree(slot_nodes_str);
|
||||||
|
dictAdd(clusterManagerUncoveredSlots, key, slot_nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n%s\n", log);
|
||||||
|
/* For every slot, take action depending on the actual condition:
|
||||||
|
* 1) No node has keys for this slot.
|
||||||
|
* 2) A single node has keys for this slot.
|
||||||
|
* 3) Multiple nodes have keys for this slot. */
|
||||||
|
none = listCreate();
|
||||||
|
single = listCreate();
|
||||||
|
multi = listCreate();
|
||||||
|
iter = dictGetIterator(clusterManagerUncoveredSlots);
|
||||||
|
while ((entry = dictNext(iter)) != NULL) {
|
||||||
|
sds slot = (sds) dictGetKey(entry);
|
||||||
|
list *nodes = (list *) dictGetVal(entry);
|
||||||
|
switch (listLength(nodes)){
|
||||||
|
case 0: listAddNodeTail(none, slot); break;
|
||||||
|
case 1: listAddNodeTail(single, slot); break;
|
||||||
|
default: listAddNodeTail(multi, slot); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dictReleaseIterator(iter);
|
||||||
|
|
||||||
|
/* Handle case "1": keys in no node. */
|
||||||
|
if (listLength(none) > 0) {
|
||||||
|
printf("The following uncovered slots have no keys "
|
||||||
|
"across the cluster:\n");
|
||||||
|
clusterManagerPrintSlotsList(none);
|
||||||
|
if (confirmWithYes("Fix these slots by covering with a random node?")){
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(none, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
sds slot = (sds)ln->value;
|
||||||
|
int s = atoi(slot);
|
||||||
|
clusterManagerNode *n = clusterManagerNodeMasterRandom();
|
||||||
|
clusterManagerLogInfo(">>> Covering slot %s with %s:%d\n",
|
||||||
|
slot, n->ip, n->port);
|
||||||
|
if (!clusterManagerSetSlotOwner(n, s, 0)) {
|
||||||
|
fixed = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* Since CLUSTER ADDSLOTS succeeded, we also update the slot
|
||||||
|
* info into the node struct, in order to keep it synced */
|
||||||
|
n->slots[s] = 1;
|
||||||
|
fixed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle case "2": keys only in one node. */
|
||||||
|
if (listLength(single) > 0) {
|
||||||
|
printf("The following uncovered slots have keys in just one node:\n");
|
||||||
|
clusterManagerPrintSlotsList(single);
|
||||||
|
if (confirmWithYes("Fix these slots by covering with those nodes?")){
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(single, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
sds slot = (sds)ln->value;
|
||||||
|
int s = atoi(slot);
|
||||||
|
dictEntry *entry = dictFind(clusterManagerUncoveredSlots, slot);
|
||||||
|
assert(entry != NULL);
|
||||||
|
list *nodes = (list *) dictGetVal(entry);
|
||||||
|
listNode *fn = listFirst(nodes);
|
||||||
|
assert(fn != NULL);
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)fn->value;
|
||||||
|
clusterManagerLogInfo(">>> Covering slot %s with %s:%d\n",
|
||||||
|
slot, n->ip, n->port);
|
||||||
|
if (!clusterManagerSetSlotOwner(n, s, 0)) {
|
||||||
|
fixed = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* Since CLUSTER ADDSLOTS succeeded, we also update the slot
|
||||||
|
* info into the node struct, in order to keep it synced */
|
||||||
|
n->slots[atoi(slot)] = 1;
|
||||||
|
fixed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle case "3": keys in multiple nodes. */
|
||||||
|
if (listLength(multi) > 0) {
|
||||||
|
printf("The following uncovered slots have keys in multiple nodes:\n");
|
||||||
|
clusterManagerPrintSlotsList(multi);
|
||||||
|
if (confirmWithYes("Fix these slots by moving keys "
|
||||||
|
"into a single node?")) {
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(multi, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
sds slot = (sds)ln->value;
|
||||||
|
dictEntry *entry = dictFind(clusterManagerUncoveredSlots, slot);
|
||||||
|
assert(entry != NULL);
|
||||||
|
list *nodes = (list *) dictGetVal(entry);
|
||||||
|
int s = atoi(slot);
|
||||||
|
clusterManagerNode *target =
|
||||||
|
clusterManagerGetNodeWithMostKeysInSlot(nodes, s, NULL);
|
||||||
|
if (target == NULL) {
|
||||||
|
fixed = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
clusterManagerLogInfo(">>> Covering slot %s moving keys "
|
||||||
|
"to %s:%d\n", slot,
|
||||||
|
target->ip, target->port);
|
||||||
|
if (!clusterManagerSetSlotOwner(target, s, 1)) {
|
||||||
|
fixed = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* Since CLUSTER ADDSLOTS succeeded, we also update the slot
|
||||||
|
* info into the node struct, in order to keep it synced */
|
||||||
|
target->slots[atoi(slot)] = 1;
|
||||||
|
listIter nli;
|
||||||
|
listNode *nln;
|
||||||
|
listRewind(nodes, &nli);
|
||||||
|
while ((nln = listNext(&nli)) != NULL) {
|
||||||
|
clusterManagerNode *src = (clusterManagerNode*)nln->value;
|
||||||
|
if (src == target) continue;
|
||||||
|
/* Assign the slot to target node in the source node. */
|
||||||
|
if (!clusterManagerSetSlot(src, target, s, "NODE", NULL))
|
||||||
|
fixed = -1;
|
||||||
|
if (fixed < 0) goto cleanup;
|
||||||
|
/* Set the source node in 'importing' state
|
||||||
|
* (even if we will actually migrate keys away)
|
||||||
|
* in order to avoid receiving redirections
|
||||||
|
* for MIGRATE. */
|
||||||
|
if (!clusterManagerSetSlot(src, target, s,
|
||||||
|
"IMPORTING", NULL)) fixed = -1;
|
||||||
|
if (fixed < 0) goto cleanup;
|
||||||
|
int opts = CLUSTER_MANAGER_OPT_VERBOSE |
|
||||||
|
CLUSTER_MANAGER_OPT_COLD;
|
||||||
|
if (!clusterManagerMoveSlot(src, target, s, opts, NULL)) {
|
||||||
|
fixed = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!clusterManagerClearSlotStatus(src, s))
|
||||||
|
fixed = -1;
|
||||||
|
if (fixed < 0) goto cleanup;
|
||||||
|
}
|
||||||
|
fixed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
sdsfree(log);
|
||||||
|
if (none) listRelease(none);
|
||||||
|
if (single) listRelease(single);
|
||||||
|
if (multi) listRelease(multi);
|
||||||
|
return fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int clusterManagerCheckCluster(int quiet) {
|
||||||
|
listNode *ln = listFirst(cluster_manager.nodes);
|
||||||
|
if (!ln) return 0;
|
||||||
|
clusterManagerNode *node = (clusterManagerNode*)ln->value;
|
||||||
|
clusterManagerLogInfo(">>> Performing Cluster Check (using node %s:%d)\n",
|
||||||
|
node->ip, node->port);
|
||||||
|
int result = 1, consistent = 0;
|
||||||
|
int do_fix = config.cluster_manager_command.flags &
|
||||||
|
CLUSTER_MANAGER_CMD_FLAG_FIX;
|
||||||
|
if (!quiet) clusterManagerShowNodes();
|
||||||
|
consistent = clusterManagerIsConfigConsistent();
|
||||||
|
if (!consistent) {
|
||||||
|
sds err = sdsnew("[ERR] Nodes don't agree about configuration!");
|
||||||
|
clusterManagerOnError(err);
|
||||||
|
result = 0;
|
||||||
|
} else {
|
||||||
|
clusterManagerLogOk("[OK] All nodes agree about slots "
|
||||||
|
"configuration.\n");
|
||||||
|
}
|
||||||
|
/* Check open slots */
|
||||||
|
clusterManagerLogInfo(">>> Check for open slots...\n");
|
||||||
|
listIter li;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
int i;
|
||||||
|
dict *open_slots = NULL;
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
if (n->migrating != NULL) {
|
||||||
|
if (open_slots == NULL)
|
||||||
|
open_slots = dictCreate(&clusterManagerDictType, NULL);
|
||||||
|
sds errstr = sdsempty();
|
||||||
|
errstr = sdscatprintf(errstr,
|
||||||
|
"[WARNING] Node %s:%d has slots in "
|
||||||
|
"migrating state ",
|
||||||
|
n->ip,
|
||||||
|
n->port);
|
||||||
|
for (i = 0; i < n->migrating_count; i += 2) {
|
||||||
|
sds slot = n->migrating[i];
|
||||||
|
dictReplace(open_slots, slot, sdsdup(n->migrating[i + 1]));
|
||||||
|
const char *fmt = (i > 0 ? ",%S" : "%S");
|
||||||
|
errstr = sdscatfmt(errstr, fmt, slot);
|
||||||
|
}
|
||||||
|
errstr = sdscat(errstr, ".");
|
||||||
|
clusterManagerOnError(errstr);
|
||||||
|
}
|
||||||
|
if (n->importing != NULL) {
|
||||||
|
if (open_slots == NULL)
|
||||||
|
open_slots = dictCreate(&clusterManagerDictType, NULL);
|
||||||
|
sds errstr = sdsempty();
|
||||||
|
errstr = sdscatprintf(errstr,
|
||||||
|
"[WARNING] Node %s:%d has slots in "
|
||||||
|
"importing state ",
|
||||||
|
n->ip,
|
||||||
|
n->port);
|
||||||
|
for (i = 0; i < n->importing_count; i += 2) {
|
||||||
|
sds slot = n->importing[i];
|
||||||
|
dictReplace(open_slots, slot, sdsdup(n->importing[i + 1]));
|
||||||
|
const char *fmt = (i > 0 ? ",%S" : "%S");
|
||||||
|
errstr = sdscatfmt(errstr, fmt, slot);
|
||||||
|
}
|
||||||
|
errstr = sdscat(errstr, ".");
|
||||||
|
clusterManagerOnError(errstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (open_slots != NULL) {
|
||||||
|
result = 0;
|
||||||
|
dictIterator *iter = dictGetIterator(open_slots);
|
||||||
|
dictEntry *entry;
|
||||||
|
sds errstr = sdsnew("[WARNING] The following slots are open: ");
|
||||||
|
i = 0;
|
||||||
|
while ((entry = dictNext(iter)) != NULL) {
|
||||||
|
sds slot = (sds) dictGetKey(entry);
|
||||||
|
const char *fmt = (i++ > 0 ? ",%S" : "%S");
|
||||||
|
errstr = sdscatfmt(errstr, fmt, slot);
|
||||||
|
}
|
||||||
|
clusterManagerLogErr("%s.\n", (char *) errstr);
|
||||||
|
sdsfree(errstr);
|
||||||
|
if (do_fix) {
|
||||||
|
/* Fix open slots. */
|
||||||
|
dictReleaseIterator(iter);
|
||||||
|
iter = dictGetIterator(open_slots);
|
||||||
|
while ((entry = dictNext(iter)) != NULL) {
|
||||||
|
sds slot = (sds) dictGetKey(entry);
|
||||||
|
result = clusterManagerFixOpenSlot(atoi(slot));
|
||||||
|
if (!result) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dictReleaseIterator(iter);
|
||||||
|
dictRelease(open_slots);
|
||||||
|
}
|
||||||
|
clusterManagerLogInfo(">>> Check slots coverage...\n");
|
||||||
|
char slots[CLUSTER_MANAGER_SLOTS];
|
||||||
|
memset(slots, 0, CLUSTER_MANAGER_SLOTS);
|
||||||
|
int coverage = clusterManagerGetCoveredSlots(slots);
|
||||||
|
if (coverage == CLUSTER_MANAGER_SLOTS) {
|
||||||
|
clusterManagerLogOk("[OK] All %d slots covered.\n",
|
||||||
|
CLUSTER_MANAGER_SLOTS);
|
||||||
|
} else {
|
||||||
|
sds err = sdsempty();
|
||||||
|
err = sdscatprintf(err, "[ERR] Not all %d slots are "
|
||||||
|
"covered by nodes.\n",
|
||||||
|
CLUSTER_MANAGER_SLOTS);
|
||||||
|
clusterManagerOnError(err);
|
||||||
|
result = 0;
|
||||||
|
if (do_fix/* && result*/) {
|
||||||
|
dictType dtype = clusterManagerDictType;
|
||||||
|
dtype.keyDestructor = dictSdsDestructor;
|
||||||
|
dtype.valDestructor = dictListDestructor;
|
||||||
|
clusterManagerUncoveredSlots = dictCreate(&dtype, NULL);
|
||||||
|
int fixed = clusterManagerFixSlotsCoverage(slots);
|
||||||
|
if (fixed > 0) result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int search_multiple_owners = config.cluster_manager_command.flags &
|
||||||
|
CLUSTER_MANAGER_CMD_FLAG_CHECK_OWNERS;
|
||||||
|
if (search_multiple_owners) {
|
||||||
|
/* Check whether there are multiple owners, even when slots are
|
||||||
|
* fully covered and there are no open slots. */
|
||||||
|
clusterManagerLogInfo(">>> Check for multiple slot owners...\n");
|
||||||
|
int slot = 0, slots_with_multiple_owners = 0;
|
||||||
|
for (; slot < CLUSTER_MANAGER_SLOTS; slot++) {
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(cluster_manager.nodes, &li);
|
||||||
|
list *owners = listCreate();
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE) continue;
|
||||||
|
if (n->slots[slot]) listAddNodeTail(owners, n);
|
||||||
|
else {
|
||||||
|
/* Nodes having keys for the slot will be considered
|
||||||
|
* owners too. */
|
||||||
|
int count = clusterManagerCountKeysInSlot(n, slot);
|
||||||
|
if (count > 0) listAddNodeTail(owners, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (listLength(owners) > 1) {
|
||||||
|
result = 0;
|
||||||
|
clusterManagerLogErr("[WARNING] Slot %d has %d owners:\n",
|
||||||
|
slot, listLength(owners));
|
||||||
|
listRewind(owners, &li);
|
||||||
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
|
clusterManagerNode *n = (clusterManagerNode*)ln->value;
|
||||||
|
clusterManagerLogErr(" %s:%d\n", n->ip, n->port);
|
||||||
|
}
|
||||||
|
slots_with_multiple_owners++;
|
||||||
|
if (do_fix) {
|
||||||
|
result = clusterManagerFixMultipleSlotOwners(slot, owners);
|
||||||
|
if (!result) {
|
||||||
|
clusterManagerLogErr("Failed to fix multiple owners "
|
||||||
|
"for slot %d\n", slot);
|
||||||
|
listRelease(owners);
|
||||||
|
break;
|
||||||
|
} else slots_with_multiple_owners--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listRelease(owners);
|
||||||
|
}
|
||||||
|
if (slots_with_multiple_owners == 0)
|
||||||
|
clusterManagerLogOk("[OK] No multiple owners found.\n");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static typeinfo* typeinfo_add(dict *types, const char* name, typeinfo* type_template) {
|
||||||
|
typeinfo *info = (typeinfo*)zmalloc(sizeof(typeinfo), MALLOC_LOCAL);
|
||||||
|
*info = *type_template;
|
||||||
|
info->name = sdsnew(name);
|
||||||
|
dictAdd(types, info->name, info);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dictType typeinfoDictType = {
|
||||||
|
dictSdsHash, /* hash function */
|
||||||
|
NULL, /* key dup */
|
||||||
|
NULL, /* val dup */
|
||||||
|
dictSdsKeyCompare, /* key compare */
|
||||||
|
NULL, /* key destructor (owned by the value)*/
|
||||||
|
type_free /* val destructor */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void getKeyTypes(dict *types_dict, redisReply *keys, typeinfo **types) {
|
||||||
|
redisReply *reply;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Pipeline TYPE commands */
|
||||||
|
for(i=0;i<keys->elements;i++) {
|
||||||
|
redisAppendCommand(context, "TYPE %s", keys->element[i]->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve types */
|
||||||
|
for(i=0;i<keys->elements;i++) {
|
||||||
|
if(redisGetReply(context, (void**)&reply)!=REDIS_OK) {
|
||||||
|
fprintf(stderr, "Error getting type for key '%s' (%d: %s)\n",
|
||||||
|
keys->element[i]->str, context->err, context->errstr);
|
||||||
|
exit(1);
|
||||||
|
} else if(reply->type != REDIS_REPLY_STATUS) {
|
||||||
|
if(reply->type == REDIS_REPLY_ERROR) {
|
||||||
|
fprintf(stderr, "TYPE returned an error: %s\n", reply->str);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Invalid reply type (%d) for TYPE on key '%s'!\n",
|
||||||
|
reply->type, keys->element[i]->str);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sds typereply = sdsnew(reply->str);
|
||||||
|
dictEntry *de = dictFind(types_dict, typereply);
|
||||||
|
sdsfree(typereply);
|
||||||
|
typeinfo *type = NULL;
|
||||||
|
if (de)
|
||||||
|
type = (typeinfo*)dictGetVal(de);
|
||||||
|
else if (strcmp(reply->str, "none")) /* create new types for modules, (but not for deleted keys) */
|
||||||
|
type = typeinfo_add(types_dict, reply->str, &type_other);
|
||||||
|
types[i] = type;
|
||||||
|
freeReplyObject(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void findBigKeys(int memkeys, unsigned memkeys_samples) {
|
||||||
|
unsigned long long sampled = 0, total_keys, totlen=0, *sizes=NULL, it=0;
|
||||||
|
redisReply *reply, *keys;
|
||||||
|
unsigned int arrsize=0, i;
|
||||||
|
dictIterator *di;
|
||||||
|
dictEntry *de;
|
||||||
|
typeinfo **types = NULL;
|
||||||
|
double pct;
|
||||||
|
|
||||||
|
dict *types_dict = dictCreate(&typeinfoDictType, NULL);
|
||||||
|
typeinfo_add(types_dict, "string", &type_string);
|
||||||
|
typeinfo_add(types_dict, "list", &type_list);
|
||||||
|
typeinfo_add(types_dict, "set", &type_set);
|
||||||
|
typeinfo_add(types_dict, "hash", &type_hash);
|
||||||
|
typeinfo_add(types_dict, "zset", &type_zset);
|
||||||
|
typeinfo_add(types_dict, "stream", &type_stream);
|
||||||
|
|
||||||
|
/* Total keys pre scanning */
|
||||||
|
total_keys = getDbSize();
|
||||||
|
|
||||||
|
/* Status message */
|
||||||
|
printf("\n# Scanning the entire keyspace to find biggest keys as well as\n");
|
||||||
|
printf("# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec\n");
|
||||||
|
printf("# per 100 SCAN commands (not usually needed).\n\n");
|
||||||
|
|
||||||
|
/* SCAN loop */
|
||||||
|
do {
|
||||||
|
/* Calculate approximate percentage completion */
|
||||||
|
pct = 100 * (double)sampled/total_keys;
|
||||||
|
|
||||||
|
/* Grab some keys and point to the keys array */
|
||||||
|
reply = sendScan(&it);
|
||||||
|
keys = reply->element[1];
|
||||||
|
|
||||||
|
/* Reallocate our type and size array if we need to */
|
||||||
|
if(keys->elements > arrsize) {
|
||||||
|
types = (typeinfo**)zrealloc(types, sizeof(int)*keys->elements, MALLOC_LOCAL);
|
||||||
|
sizes = (unsigned long long*)zrealloc(sizes, sizeof(unsigned long long)*keys->elements, MALLOC_LOCAL);
|
||||||
|
|
||||||
|
if(!types || !sizes) {
|
||||||
|
fprintf(stderr, "Failed to allocate storage for keys!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
arrsize = keys->elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve types and then sizes */
|
||||||
|
getKeyTypes(types_dict, keys, types);
|
||||||
|
getKeySizes(keys, types, sizes, memkeys, memkeys_samples);
|
||||||
|
|
||||||
|
/* Now update our stats */
|
||||||
|
for(i=0;i<keys->elements;i++) {
|
||||||
|
typeinfo *type = types[i];
|
||||||
|
/* Skip keys that disappeared between SCAN and TYPE */
|
||||||
|
if(!type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
type->totalsize += sizes[i];
|
||||||
|
type->count++;
|
||||||
|
totlen += keys->element[i]->len;
|
||||||
|
sampled++;
|
||||||
|
|
||||||
|
if(type->biggest<sizes[i]) {
|
||||||
|
printf(
|
||||||
|
"[%05.2f%%] Biggest %-6s found so far '%s' with %llu %s\n",
|
||||||
|
pct, type->name, keys->element[i]->str, sizes[i],
|
||||||
|
!memkeys? type->sizeunit: "bytes");
|
||||||
|
|
||||||
|
/* Keep track of biggest key name for this type */
|
||||||
|
if (type->biggest_key)
|
||||||
|
sdsfree(type->biggest_key);
|
||||||
|
type->biggest_key = sdsnew(keys->element[i]->str);
|
||||||
|
if(!type->biggest_key) {
|
||||||
|
fprintf(stderr, "Failed to allocate memory for key!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep track of the biggest size for this type */
|
||||||
|
type->biggest = sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update overall progress */
|
||||||
|
if(sampled % 1000000 == 0) {
|
||||||
|
printf("[%05.2f%%] Sampled %llu keys so far\n", pct, sampled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sleep if we've been directed to do so */
|
||||||
|
if(sampled && (sampled %100) == 0 && config.interval) {
|
||||||
|
usleep(config.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeReplyObject(reply);
|
||||||
|
} while(it != 0);
|
||||||
|
|
||||||
|
if(types) zfree(types);
|
||||||
|
if(sizes) zfree(sizes);
|
||||||
|
|
||||||
|
/* We're done */
|
||||||
|
printf("\n-------- summary -------\n\n");
|
||||||
|
|
||||||
|
printf("Sampled %llu keys in the keyspace!\n", sampled);
|
||||||
|
printf("Total key length in bytes is %llu (avg len %.2f)\n\n",
|
||||||
|
totlen, totlen ? (double)totlen/sampled : 0);
|
||||||
|
|
||||||
|
/* Output the biggest keys we found, for types we did find */
|
||||||
|
di = dictGetIterator(types_dict);
|
||||||
|
while ((de = dictNext(di))) {
|
||||||
|
typeinfo *type = (typeinfo*)dictGetVal(de);
|
||||||
|
if(type->biggest_key) {
|
||||||
|
printf("Biggest %6s found '%s' has %llu %s\n", type->name, type->biggest_key,
|
||||||
|
type->biggest, !memkeys? type->sizeunit: "bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dictReleaseIterator(di);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
di = dictGetIterator(types_dict);
|
||||||
|
while ((de = dictNext(di))) {
|
||||||
|
typeinfo *type = (typeinfo*)dictGetVal(de);
|
||||||
|
printf("%llu %ss with %llu %s (%05.2f%% of keys, avg size %.2f)\n",
|
||||||
|
type->count, type->name, type->totalsize, !memkeys? type->sizeunit: "bytes",
|
||||||
|
sampled ? 100 * (double)type->count/sampled : 0,
|
||||||
|
type->count ? (double)type->totalsize/type->count : 0);
|
||||||
|
}
|
||||||
|
dictReleaseIterator(di);
|
||||||
|
|
||||||
|
dictRelease(types_dict);
|
||||||
|
|
||||||
|
/* Success! */
|
||||||
|
exit(0);
|
||||||
|
}
|
1198
src/redis-cli.c
1198
src/redis-cli.c
File diff suppressed because it is too large
Load Diff
279
src/redis-cli.h
Normal file
279
src/redis-cli.h
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UNUSED(V) ((void) V)
|
||||||
|
|
||||||
|
#define OUTPUT_STANDARD 0
|
||||||
|
#define OUTPUT_RAW 1
|
||||||
|
#define OUTPUT_CSV 2
|
||||||
|
#define REDIS_CLI_KEEPALIVE_INTERVAL 15 /* seconds */
|
||||||
|
#define REDIS_CLI_DEFAULT_PIPE_TIMEOUT 30 /* seconds */
|
||||||
|
#define REDIS_CLI_HISTFILE_ENV "REDISCLI_HISTFILE"
|
||||||
|
#define REDIS_CLI_HISTFILE_DEFAULT ".rediscli_history"
|
||||||
|
#define REDIS_CLI_RCFILE_ENV "REDISCLI_RCFILE"
|
||||||
|
#define REDIS_CLI_RCFILE_DEFAULT ".redisclirc"
|
||||||
|
#define REDIS_CLI_AUTH_ENV "REDISCLI_AUTH"
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_SLOTS 16384
|
||||||
|
#define CLUSTER_MANAGER_MIGRATE_TIMEOUT 60000
|
||||||
|
#define CLUSTER_MANAGER_MIGRATE_PIPELINE 10
|
||||||
|
#define CLUSTER_MANAGER_REBALANCE_THRESHOLD 2
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_INVALID_HOST_ARG \
|
||||||
|
"[ERR] Invalid arguments: you need to pass either a valid " \
|
||||||
|
"address (ie. 120.0.0.1:7000) or space separated IP " \
|
||||||
|
"and port (ie. 120.0.0.1 7000)\n"
|
||||||
|
#define CLUSTER_MANAGER_MODE() (config.cluster_manager_command.name != NULL)
|
||||||
|
#define CLUSTER_MANAGER_MASTERS_COUNT(nodes, replicas) (nodes/(replicas + 1))
|
||||||
|
#define CLUSTER_MANAGER_COMMAND(n,...) \
|
||||||
|
(redisCommand(n->context, __VA_ARGS__))
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_NODE_ARRAY_FREE(array) zfree(array->alloc)
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_PRINT_REPLY_ERROR(n, err) \
|
||||||
|
clusterManagerLogErr("Node %s:%d replied with error:\n%s\n", \
|
||||||
|
n->ip, n->port, err);
|
||||||
|
|
||||||
|
#define clusterManagerLogInfo(...) \
|
||||||
|
clusterManagerLog(CLUSTER_MANAGER_LOG_LVL_INFO,__VA_ARGS__)
|
||||||
|
|
||||||
|
#define clusterManagerLogErr(...) \
|
||||||
|
clusterManagerLog(CLUSTER_MANAGER_LOG_LVL_ERR,__VA_ARGS__)
|
||||||
|
|
||||||
|
#define clusterManagerLogWarn(...) \
|
||||||
|
clusterManagerLog(CLUSTER_MANAGER_LOG_LVL_WARN,__VA_ARGS__)
|
||||||
|
|
||||||
|
#define clusterManagerLogOk(...) \
|
||||||
|
clusterManagerLog(CLUSTER_MANAGER_LOG_LVL_SUCCESS,__VA_ARGS__)
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_FLAG_MYSELF 1 << 0
|
||||||
|
#define CLUSTER_MANAGER_FLAG_SLAVE 1 << 1
|
||||||
|
#define CLUSTER_MANAGER_FLAG_FRIEND 1 << 2
|
||||||
|
#define CLUSTER_MANAGER_FLAG_NOADDR 1 << 3
|
||||||
|
#define CLUSTER_MANAGER_FLAG_DISCONNECT 1 << 4
|
||||||
|
#define CLUSTER_MANAGER_FLAG_FAIL 1 << 5
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_FIX 1 << 0
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_SLAVE 1 << 1
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_YES 1 << 2
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_AUTOWEIGHTS 1 << 3
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_EMPTYMASTER 1 << 4
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_SIMULATE 1 << 5
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_REPLACE 1 << 6
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_COPY 1 << 7
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_COLOR 1 << 8
|
||||||
|
#define CLUSTER_MANAGER_CMD_FLAG_CHECK_OWNERS 1 << 9
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_OPT_GETFRIENDS 1 << 0
|
||||||
|
#define CLUSTER_MANAGER_OPT_COLD 1 << 1
|
||||||
|
#define CLUSTER_MANAGER_OPT_UPDATE 1 << 2
|
||||||
|
#define CLUSTER_MANAGER_OPT_QUIET 1 << 6
|
||||||
|
#define CLUSTER_MANAGER_OPT_VERBOSE 1 << 7
|
||||||
|
|
||||||
|
#define CLUSTER_MANAGER_LOG_LVL_INFO 1
|
||||||
|
#define CLUSTER_MANAGER_LOG_LVL_WARN 2
|
||||||
|
#define CLUSTER_MANAGER_LOG_LVL_ERR 3
|
||||||
|
#define CLUSTER_MANAGER_LOG_LVL_SUCCESS 4
|
||||||
|
|
||||||
|
#define CLUSTER_JOIN_CHECK_AFTER 20
|
||||||
|
|
||||||
|
#define LOG_COLOR_BOLD "29;1m"
|
||||||
|
#define LOG_COLOR_RED "31;1m"
|
||||||
|
#define LOG_COLOR_GREEN "32;1m"
|
||||||
|
#define LOG_COLOR_YELLOW "33;1m"
|
||||||
|
#define LOG_COLOR_RESET "0m"
|
||||||
|
|
||||||
|
/* cliConnect() flags. */
|
||||||
|
#define CC_FORCE (1<<0) /* Re-connect if already connected. */
|
||||||
|
#define CC_QUIET (1<<1) /* Don't log connecting errors. */
|
||||||
|
|
||||||
|
struct clusterManagerLink;
|
||||||
|
typedef struct clusterManagerLink clusterManagerLink;
|
||||||
|
|
||||||
|
/* Dict Helpers */
|
||||||
|
|
||||||
|
uint64_t dictSdsHash(const void *key);
|
||||||
|
int dictSdsKeyCompare(void *privdata, const void *key1,
|
||||||
|
const void *key2);
|
||||||
|
void dictSdsDestructor(void *privdata, void *val);
|
||||||
|
void dictListDestructor(void *privdata, void *val);
|
||||||
|
|
||||||
|
/* Cluster Manager Command Info */
|
||||||
|
typedef struct clusterManagerCommand {
|
||||||
|
char *name;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
int flags;
|
||||||
|
int replicas;
|
||||||
|
char *from;
|
||||||
|
char *to;
|
||||||
|
char **weight;
|
||||||
|
int weight_argc;
|
||||||
|
char *master_id;
|
||||||
|
int slots;
|
||||||
|
int timeout;
|
||||||
|
int pipeline;
|
||||||
|
float threshold;
|
||||||
|
char *backup_dir;
|
||||||
|
} clusterManagerCommand;
|
||||||
|
|
||||||
|
void createClusterManagerCommand(char *cmdname, int argc, char **argv);
|
||||||
|
|
||||||
|
extern redisContext *context;
|
||||||
|
extern struct config {
|
||||||
|
char *hostip;
|
||||||
|
int hostport;
|
||||||
|
char *hostsocket;
|
||||||
|
long repeat;
|
||||||
|
long interval;
|
||||||
|
int dbnum;
|
||||||
|
int interactive;
|
||||||
|
int shutdown;
|
||||||
|
int monitor_mode;
|
||||||
|
int pubsub_mode;
|
||||||
|
int latency_mode;
|
||||||
|
int latency_dist_mode;
|
||||||
|
int latency_history;
|
||||||
|
int lru_test_mode;
|
||||||
|
long long lru_test_sample_size;
|
||||||
|
int cluster_mode;
|
||||||
|
int cluster_reissue_command;
|
||||||
|
int slave_mode;
|
||||||
|
int pipe_mode;
|
||||||
|
int pipe_timeout;
|
||||||
|
int getrdb_mode;
|
||||||
|
int stat_mode;
|
||||||
|
int scan_mode;
|
||||||
|
int intrinsic_latency_mode;
|
||||||
|
int intrinsic_latency_duration;
|
||||||
|
char *pattern;
|
||||||
|
char *rdb_filename;
|
||||||
|
int bigkeys;
|
||||||
|
int memkeys;
|
||||||
|
unsigned memkeys_samples;
|
||||||
|
int hotkeys;
|
||||||
|
int stdinarg; /* get last arg from stdin. (-x option) */
|
||||||
|
char *auth;
|
||||||
|
int output; /* output mode, see OUTPUT_* defines */
|
||||||
|
sds mb_delim;
|
||||||
|
char prompt[128];
|
||||||
|
char *eval;
|
||||||
|
int eval_ldb;
|
||||||
|
int eval_ldb_sync; /* Ask for synchronous mode of the Lua debugger. */
|
||||||
|
int eval_ldb_end; /* Lua debugging session ended. */
|
||||||
|
int enable_ldb_on_eval; /* Handle manual SCRIPT DEBUG + EVAL commands. */
|
||||||
|
int last_cmd_type;
|
||||||
|
int verbose;
|
||||||
|
clusterManagerCommand cluster_manager_command;
|
||||||
|
int no_auth_warning;
|
||||||
|
} config;
|
||||||
|
|
||||||
|
/* The Cluster Manager global structure */
|
||||||
|
extern struct clusterManager {
|
||||||
|
list *nodes; /* List of nodes in the configuration. */
|
||||||
|
list *errors;
|
||||||
|
} cluster_manager;
|
||||||
|
|
||||||
|
typedef struct clusterManagerNode {
|
||||||
|
redisContext *context;
|
||||||
|
sds name;
|
||||||
|
char *ip;
|
||||||
|
int port;
|
||||||
|
uint64_t current_epoch;
|
||||||
|
time_t ping_sent;
|
||||||
|
time_t ping_recv;
|
||||||
|
int flags;
|
||||||
|
list *flags_str; /* Flags string representations */
|
||||||
|
sds replicate; /* Master ID if node is a slave */
|
||||||
|
int dirty; /* Node has changes that can be flushed */
|
||||||
|
uint8_t slots[CLUSTER_MANAGER_SLOTS];
|
||||||
|
int slots_count;
|
||||||
|
int replicas_count;
|
||||||
|
list *friends;
|
||||||
|
sds *migrating; /* An array of sds where even strings are slots and odd
|
||||||
|
* strings are the destination node IDs. */
|
||||||
|
sds *importing; /* An array of sds where even strings are slots and odd
|
||||||
|
* strings are the source node IDs. */
|
||||||
|
int migrating_count; /* Length of the migrating array (migrating slots*2) */
|
||||||
|
int importing_count; /* Length of the importing array (importing slots*2) */
|
||||||
|
float weight; /* Weight used by rebalance */
|
||||||
|
int balance; /* Used by rebalance */
|
||||||
|
} clusterManagerNode;
|
||||||
|
|
||||||
|
/* Data structure used to represent a sequence of cluster nodes. */
|
||||||
|
typedef struct clusterManagerNodeArray {
|
||||||
|
clusterManagerNode **nodes; /* Actual nodes array */
|
||||||
|
clusterManagerNode **alloc; /* Pointer to the allocated memory */
|
||||||
|
int len; /* Actual length of the array */
|
||||||
|
int count; /* Non-NULL nodes count */
|
||||||
|
} clusterManagerNodeArray;
|
||||||
|
|
||||||
|
/* Used for the reshard table. */
|
||||||
|
typedef struct clusterManagerReshardTableItem {
|
||||||
|
clusterManagerNode *source;
|
||||||
|
int slot;
|
||||||
|
} clusterManagerReshardTableItem;
|
||||||
|
|
||||||
|
typedef struct typeinfo {
|
||||||
|
char *name;
|
||||||
|
char *sizecmd;
|
||||||
|
char *sizeunit;
|
||||||
|
unsigned long long biggest;
|
||||||
|
unsigned long long count;
|
||||||
|
unsigned long long totalsize;
|
||||||
|
sds biggest_key;
|
||||||
|
} typeinfo;
|
||||||
|
|
||||||
|
extern typeinfo type_string;
|
||||||
|
extern typeinfo type_list;
|
||||||
|
extern typeinfo type_set;
|
||||||
|
extern typeinfo type_hash;
|
||||||
|
extern typeinfo type_zset;
|
||||||
|
extern typeinfo type_stream;
|
||||||
|
extern typeinfo type_other;
|
||||||
|
|
||||||
|
void findBigKeys(int memkeys, unsigned memkeys_samples);
|
||||||
|
int clusterManagerGetAntiAffinityScore(clusterManagerNodeArray *ipnodes,
|
||||||
|
int ip_count, clusterManagerNode ***offending, int *offending_len);
|
||||||
|
int clusterManagerFixMultipleSlotOwners(int slot, list *owners);
|
||||||
|
void getKeySizes(redisReply *keys, struct typeinfo **types,
|
||||||
|
unsigned long long *sizes, int memkeys,
|
||||||
|
unsigned memkeys_samples);
|
||||||
|
int clusterManagerFixOpenSlot(int slot);
|
||||||
|
void clusterManagerPrintSlotsList(list *slots);
|
||||||
|
int clusterManagerGetCoveredSlots(char *all_slots);
|
||||||
|
void clusterManagerOnError(sds err);
|
||||||
|
int clusterManagerIsConfigConsistent(void);
|
||||||
|
void freeClusterManagerNode(clusterManagerNode *node);
|
||||||
|
void clusterManagerLog(int level, const char* fmt, ...);
|
||||||
|
int parseClusterNodeAddress(char *addr, char **ip_ptr, int *port_ptr,
|
||||||
|
int *bus_port_ptr);
|
||||||
|
int clusterManagerCheckRedisReply(clusterManagerNode *n,
|
||||||
|
redisReply *r, char **err);
|
||||||
|
int confirmWithYes(const char *msg);
|
||||||
|
int clusterManagerSetSlotOwner(clusterManagerNode *owner,
|
||||||
|
int slot,
|
||||||
|
int do_clear);
|
||||||
|
clusterManagerNode * clusterManagerGetNodeWithMostKeysInSlot(list *nodes,
|
||||||
|
int slot,
|
||||||
|
char **err);
|
||||||
|
int clusterManagerSetSlot(clusterManagerNode *node1,
|
||||||
|
clusterManagerNode *node2,
|
||||||
|
int slot, const char *status, char **err);
|
||||||
|
int clusterManagerMoveSlot(clusterManagerNode *source,
|
||||||
|
clusterManagerNode *target,
|
||||||
|
int slot, int opts, char**err);
|
||||||
|
int clusterManagerClearSlotStatus(clusterManagerNode *node, int slot);
|
||||||
|
void clusterManagerShowNodes(void);
|
||||||
|
signed int clusterManagerCountKeysInSlot(clusterManagerNode *node,
|
||||||
|
int slot);
|
||||||
|
void type_free(void* priv_data, void* val);
|
||||||
|
int getDbSize(void);
|
||||||
|
redisReply *sendScan(unsigned long long *it);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -186,9 +186,9 @@ void freeReplicationBacklog(void) {
|
|||||||
* This function also increments the global replication offset stored at
|
* This function also increments the global replication offset stored at
|
||||||
* server.master_repl_offset, because there is no case where we want to feed
|
* server.master_repl_offset, because there is no case where we want to feed
|
||||||
* the backlog without incrementing the offset. */
|
* the backlog without incrementing the offset. */
|
||||||
void feedReplicationBacklog(void *ptr, size_t len) {
|
void feedReplicationBacklog(const void *ptr, size_t len) {
|
||||||
serverAssert(GlobalLocksAcquired());
|
serverAssert(GlobalLocksAcquired());
|
||||||
unsigned char *p = (unsigned char*)ptr;
|
const unsigned char *p = (const unsigned char*)ptr;
|
||||||
|
|
||||||
server.master_repl_offset += len;
|
server.master_repl_offset += len;
|
||||||
|
|
||||||
|
@ -266,8 +266,8 @@ void rioInitWithFdset(rio *r, int *fds, int numfds) {
|
|||||||
int j;
|
int j;
|
||||||
|
|
||||||
*r = rioFdsetIO;
|
*r = rioFdsetIO;
|
||||||
r->io.fdset.fds = zmalloc(sizeof(int)*numfds, MALLOC_LOCAL);
|
r->io.fdset.fds = (int*)zmalloc(sizeof(int)*numfds, MALLOC_LOCAL);
|
||||||
r->io.fdset.state = zmalloc(sizeof(int)*numfds, MALLOC_LOCAL);
|
r->io.fdset.state = (int*)zmalloc(sizeof(int)*numfds, MALLOC_LOCAL);
|
||||||
memcpy(r->io.fdset.fds,fds,sizeof(int)*numfds);
|
memcpy(r->io.fdset.fds,fds,sizeof(int)*numfds);
|
||||||
for (j = 0; j < numfds; j++) r->io.fdset.state[j] = 0;
|
for (j = 0; j < numfds; j++) r->io.fdset.state[j] = 0;
|
||||||
r->io.fdset.numfds = numfds;
|
r->io.fdset.numfds = numfds;
|
||||||
@ -287,7 +287,7 @@ void rioFreeFdset(rio *r) {
|
|||||||
/* This function can be installed both in memory and file streams when checksum
|
/* This function can be installed both in memory and file streams when checksum
|
||||||
* computation is needed. */
|
* computation is needed. */
|
||||||
void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len) {
|
void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len) {
|
||||||
r->cksum = crc64(r->cksum,buf,len);
|
r->cksum = crc64(r->cksum,(const unsigned char*)buf,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the file-based rio object to auto-fsync every 'bytes' file written.
|
/* Set the file-based rio object to auto-fsync every 'bytes' file written.
|
@ -36,6 +36,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "sds.h"
|
#include "sds.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
struct _rio {
|
struct _rio {
|
||||||
/* Backend functions.
|
/* Backend functions.
|
||||||
* Since this functions do not tolerate short writes or reads the return
|
* Since this functions do not tolerate short writes or reads the return
|
||||||
@ -141,4 +145,8 @@ int rioWriteBulkObject(rio *r, struct redisObject *obj);
|
|||||||
void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len);
|
void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len);
|
||||||
void rioSetAutoSync(rio *r, off_t bytes);
|
void rioSetAutoSync(rio *r, off_t bytes);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1089,7 +1089,7 @@ sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {
|
|||||||
|
|
||||||
/* Join an array of C strings using the specified separator (also a C string).
|
/* Join an array of C strings using the specified separator (also a C string).
|
||||||
* Returns the result as an sds string. */
|
* Returns the result as an sds string. */
|
||||||
sds sdsjoin(char **argv, int argc, char *sep) {
|
sds sdsjoin(char **argv, int argc, const char *sep) {
|
||||||
sds join = sdsempty();
|
sds join = sdsempty();
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@ struct __attribute__ ((__packed__)) sdshdr8 {
|
|||||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
char buf[];
|
char buf[];
|
||||||
|
#else
|
||||||
|
char *buf() {
|
||||||
|
return reinterpret_cast<char*>(this+1);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
struct __attribute__ ((__packed__)) sdshdr16 {
|
struct __attribute__ ((__packed__)) sdshdr16 {
|
||||||
@ -270,7 +274,7 @@ sds sdsfromlonglong(long long value);
|
|||||||
sds sdscatrepr(sds s, const char *p, size_t len);
|
sds sdscatrepr(sds s, const char *p, size_t len);
|
||||||
sds *sdssplitargs(const char *line, int *argc);
|
sds *sdssplitargs(const char *line, int *argc);
|
||||||
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
|
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
|
||||||
sds sdsjoin(char **argv, int argc, char *sep);
|
sds sdsjoin(char **argv, int argc, const char *sep);
|
||||||
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
|
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
|
||||||
|
|
||||||
/* Low level functions exposed to the user API */
|
/* Low level functions exposed to the user API */
|
||||||
|
@ -375,7 +375,7 @@ sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master);
|
|||||||
void sentinelScheduleScriptExecution(char *path, ...);
|
void sentinelScheduleScriptExecution(char *path, ...);
|
||||||
void sentinelStartFailover(sentinelRedisInstance *master);
|
void sentinelStartFailover(sentinelRedisInstance *master);
|
||||||
void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata);
|
void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata);
|
||||||
int sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port);
|
int sentinelSendSlaveOf(sentinelRedisInstance *ri, const char *host, int port);
|
||||||
char *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char *req_runid, uint64_t *leader_epoch);
|
char *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char *req_runid, uint64_t *leader_epoch);
|
||||||
void sentinelFlushConfig(void);
|
void sentinelFlushConfig(void);
|
||||||
void sentinelGenerateInitialMonitorEvents(void);
|
void sentinelGenerateInitialMonitorEvents(void);
|
||||||
@ -394,7 +394,7 @@ void releaseSentinelRedisInstance(sentinelRedisInstance *ri);
|
|||||||
|
|
||||||
void dictInstancesValDestructor (void *privdata, void *obj) {
|
void dictInstancesValDestructor (void *privdata, void *obj) {
|
||||||
UNUSED(privdata);
|
UNUSED(privdata);
|
||||||
releaseSentinelRedisInstance(obj);
|
releaseSentinelRedisInstance((sentinelRedisInstance*)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Instance name (sds) -> instance (sentinelRedisInstance pointer)
|
/* Instance name (sds) -> instance (sentinelRedisInstance pointer)
|
||||||
@ -554,7 +554,7 @@ sentinelAddr *createSentinelAddr(char *hostname, int port) {
|
|||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sa = zmalloc(sizeof(*sa), MALLOC_LOCAL);
|
sa = (sentinelAddr*)zmalloc(sizeof(*sa), MALLOC_LOCAL);
|
||||||
sa->ip = sdsnew(ip);
|
sa->ip = sdsnew(ip);
|
||||||
sa->port = port;
|
sa->port = port;
|
||||||
return sa;
|
return sa;
|
||||||
@ -564,7 +564,7 @@ sentinelAddr *createSentinelAddr(char *hostname, int port) {
|
|||||||
sentinelAddr *dupSentinelAddr(sentinelAddr *src) {
|
sentinelAddr *dupSentinelAddr(sentinelAddr *src) {
|
||||||
sentinelAddr *sa;
|
sentinelAddr *sa;
|
||||||
|
|
||||||
sa = zmalloc(sizeof(*sa), MALLOC_LOCAL);
|
sa = (sentinelAddr*)zmalloc(sizeof(*sa), MALLOC_LOCAL);
|
||||||
sa->ip = sdsnew(src->ip);
|
sa->ip = sdsnew(src->ip);
|
||||||
sa->port = src->port;
|
sa->port = src->port;
|
||||||
return sa;
|
return sa;
|
||||||
@ -607,7 +607,7 @@ int sentinelAddrIsEqual(sentinelAddr *a, sentinelAddr *b) {
|
|||||||
*
|
*
|
||||||
* Any other specifier after "%@" is processed by printf itself.
|
* Any other specifier after "%@" is processed by printf itself.
|
||||||
*/
|
*/
|
||||||
void sentinelEvent(int level, char *type, sentinelRedisInstance *ri,
|
void sentinelEvent(int level, const char *type, sentinelRedisInstance *ri,
|
||||||
const char *fmt, ...) {
|
const char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char msg[LOG_MAX_LEN];
|
char msg[LOG_MAX_LEN];
|
||||||
@ -674,7 +674,7 @@ void sentinelGenerateInitialMonitorEvents(void) {
|
|||||||
|
|
||||||
di = dictGetIterator(sentinel.masters);
|
di = dictGetIterator(sentinel.masters);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
sentinelEvent(LL_WARNING,"+monitor",ri,"%@ quorum %d",ri->quorum);
|
sentinelEvent(LL_WARNING,"+monitor",ri,"%@ quorum %d",ri->quorum);
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
@ -708,10 +708,10 @@ void sentinelScheduleScriptExecution(char *path, ...) {
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
argv[0] = sdsnew(path);
|
argv[0] = sdsnew(path);
|
||||||
|
|
||||||
sj = zmalloc(sizeof(*sj), MALLOC_LOCAL);
|
sj = (sentinelScriptJob*)zmalloc(sizeof(*sj), MALLOC_LOCAL);
|
||||||
sj->flags = SENTINEL_SCRIPT_NONE;
|
sj->flags = SENTINEL_SCRIPT_NONE;
|
||||||
sj->retry_num = 0;
|
sj->retry_num = 0;
|
||||||
sj->argv = zmalloc(sizeof(char*)*(argc+1), MALLOC_LOCAL);
|
sj->argv = (char**)zmalloc(sizeof(char*)*(argc+1), MALLOC_LOCAL);
|
||||||
sj->start_time = 0;
|
sj->start_time = 0;
|
||||||
sj->pid = 0;
|
sj->pid = 0;
|
||||||
memcpy(sj->argv,argv,sizeof(char*)*(argc+1));
|
memcpy(sj->argv,argv,sizeof(char*)*(argc+1));
|
||||||
@ -725,7 +725,7 @@ void sentinelScheduleScriptExecution(char *path, ...) {
|
|||||||
|
|
||||||
listRewind(sentinel.scripts_queue,&li);
|
listRewind(sentinel.scripts_queue,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
sj = ln->value;
|
sj = (sentinelScriptJob*)ln->value;
|
||||||
|
|
||||||
if (sj->flags & SENTINEL_SCRIPT_RUNNING) continue;
|
if (sj->flags & SENTINEL_SCRIPT_RUNNING) continue;
|
||||||
/* The first node is the oldest as we add on tail. */
|
/* The first node is the oldest as we add on tail. */
|
||||||
@ -746,7 +746,7 @@ listNode *sentinelGetScriptListNodeByPid(pid_t pid) {
|
|||||||
|
|
||||||
listRewind(sentinel.scripts_queue,&li);
|
listRewind(sentinel.scripts_queue,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
sentinelScriptJob *sj = ln->value;
|
sentinelScriptJob *sj = (sentinelScriptJob*)ln->value;
|
||||||
|
|
||||||
if ((sj->flags & SENTINEL_SCRIPT_RUNNING) && sj->pid == pid)
|
if ((sj->flags & SENTINEL_SCRIPT_RUNNING) && sj->pid == pid)
|
||||||
return ln;
|
return ln;
|
||||||
@ -767,7 +767,7 @@ void sentinelRunPendingScripts(void) {
|
|||||||
while (sentinel.running_scripts < SENTINEL_SCRIPT_MAX_RUNNING &&
|
while (sentinel.running_scripts < SENTINEL_SCRIPT_MAX_RUNNING &&
|
||||||
(ln = listNext(&li)) != NULL)
|
(ln = listNext(&li)) != NULL)
|
||||||
{
|
{
|
||||||
sentinelScriptJob *sj = ln->value;
|
sentinelScriptJob *sj = (sentinelScriptJob*)ln->value;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
/* Skip if already running. */
|
/* Skip if already running. */
|
||||||
@ -839,7 +839,7 @@ void sentinelCollectTerminatedScripts(void) {
|
|||||||
serverLog(LL_WARNING,"wait3() returned a pid (%ld) we can't find in our scripts execution queue!", (long)pid);
|
serverLog(LL_WARNING,"wait3() returned a pid (%ld) we can't find in our scripts execution queue!", (long)pid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sj = ln->value;
|
sj = (sentinelScriptJob*)ln->value;
|
||||||
|
|
||||||
/* If the script was terminated by a signal or returns an
|
/* If the script was terminated by a signal or returns an
|
||||||
* exit code of "1" (that means: please retry), we reschedule it
|
* exit code of "1" (that means: please retry), we reschedule it
|
||||||
@ -874,7 +874,7 @@ void sentinelKillTimedoutScripts(void) {
|
|||||||
|
|
||||||
listRewind(sentinel.scripts_queue,&li);
|
listRewind(sentinel.scripts_queue,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
sentinelScriptJob *sj = ln->value;
|
sentinelScriptJob *sj = (sentinelScriptJob*)ln->value;
|
||||||
|
|
||||||
if (sj->flags & SENTINEL_SCRIPT_RUNNING &&
|
if (sj->flags & SENTINEL_SCRIPT_RUNNING &&
|
||||||
(now - sj->start_time) > SENTINEL_SCRIPT_MAX_RUNTIME)
|
(now - sj->start_time) > SENTINEL_SCRIPT_MAX_RUNTIME)
|
||||||
@ -894,7 +894,7 @@ void sentinelPendingScriptsCommand(client *c) {
|
|||||||
addReplyArrayLen(c,listLength(sentinel.scripts_queue));
|
addReplyArrayLen(c,listLength(sentinel.scripts_queue));
|
||||||
listRewind(sentinel.scripts_queue,&li);
|
listRewind(sentinel.scripts_queue,&li);
|
||||||
while ((ln = listNext(&li)) != NULL) {
|
while ((ln = listNext(&li)) != NULL) {
|
||||||
sentinelScriptJob *sj = ln->value;
|
sentinelScriptJob *sj = (sentinelScriptJob*)ln->value;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
addReplyMapLen(c,5);
|
addReplyMapLen(c,5);
|
||||||
@ -939,7 +939,7 @@ void sentinelPendingScriptsCommand(client *c) {
|
|||||||
*
|
*
|
||||||
* from/to fields are respectively master -> promoted slave addresses for
|
* from/to fields are respectively master -> promoted slave addresses for
|
||||||
* "start" and "end". */
|
* "start" and "end". */
|
||||||
void sentinelCallClientReconfScript(sentinelRedisInstance *master, int role, char *state, sentinelAddr *from, sentinelAddr *to) {
|
void sentinelCallClientReconfScript(sentinelRedisInstance *master, int role, const char *state, sentinelAddr *from, sentinelAddr *to) {
|
||||||
char fromport[32], toport[32];
|
char fromport[32], toport[32];
|
||||||
|
|
||||||
if (master->client_reconfig_script == NULL) return;
|
if (master->client_reconfig_script == NULL) return;
|
||||||
@ -955,7 +955,7 @@ void sentinelCallClientReconfScript(sentinelRedisInstance *master, int role, cha
|
|||||||
|
|
||||||
/* Create a not yet connected link object. */
|
/* Create a not yet connected link object. */
|
||||||
instanceLink *createInstanceLink(void) {
|
instanceLink *createInstanceLink(void) {
|
||||||
instanceLink *link = zmalloc(sizeof(*link), MALLOC_LOCAL);
|
instanceLink *link = (instanceLink*)zmalloc(sizeof(*link), MALLOC_LOCAL);
|
||||||
|
|
||||||
link->refcount = 1;
|
link->refcount = 1;
|
||||||
link->disconnected = 1;
|
link->disconnected = 1;
|
||||||
@ -1053,7 +1053,7 @@ int sentinelTryConnectionSharing(sentinelRedisInstance *ri) {
|
|||||||
|
|
||||||
di = dictGetIterator(sentinel.masters);
|
di = dictGetIterator(sentinel.masters);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *master = dictGetVal(de), *match;
|
sentinelRedisInstance *master = (sentinelRedisInstance*)dictGetVal(de), *match;
|
||||||
/* We want to share with the same physical Sentinel referenced
|
/* We want to share with the same physical Sentinel referenced
|
||||||
* in other masters, so skip our master. */
|
* in other masters, so skip our master. */
|
||||||
if (master == ri->master) continue;
|
if (master == ri->master) continue;
|
||||||
@ -1087,7 +1087,7 @@ int sentinelUpdateSentinelAddressInAllMasters(sentinelRedisInstance *ri) {
|
|||||||
|
|
||||||
di = dictGetIterator(sentinel.masters);
|
di = dictGetIterator(sentinel.masters);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *master = dictGetVal(de), *match;
|
sentinelRedisInstance *master = (sentinelRedisInstance*)dictGetVal(de), *match;
|
||||||
match = getSentinelRedisInstanceByAddrAndRunID(master->sentinels,
|
match = getSentinelRedisInstanceByAddrAndRunID(master->sentinels,
|
||||||
NULL,0,ri->runid);
|
NULL,0,ri->runid);
|
||||||
/* If there is no match, this master does not know about this
|
/* If there is no match, this master does not know about this
|
||||||
@ -1122,7 +1122,7 @@ int sentinelUpdateSentinelAddressInAllMasters(sentinelRedisInstance *ri) {
|
|||||||
* Note: we don't free the hiredis context as hiredis will do it for us
|
* Note: we don't free the hiredis context as hiredis will do it for us
|
||||||
* for async connections. */
|
* for async connections. */
|
||||||
void instanceLinkConnectionError(const redisAsyncContext *c) {
|
void instanceLinkConnectionError(const redisAsyncContext *c) {
|
||||||
instanceLink *link = c->data;
|
instanceLink *link = (instanceLink*)c->data;
|
||||||
int pubsub;
|
int pubsub;
|
||||||
|
|
||||||
if (!link) return;
|
if (!link) return;
|
||||||
@ -1205,7 +1205,7 @@ sentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create the instance object. */
|
/* Create the instance object. */
|
||||||
ri = zmalloc(sizeof(*ri), MALLOC_LOCAL);
|
ri = (sentinelRedisInstance*)zmalloc(sizeof(*ri), MALLOC_LOCAL);
|
||||||
/* Note that all the instances are started in the disconnected state,
|
/* Note that all the instances are started in the disconnected state,
|
||||||
* the event loop will take care of connecting them. */
|
* the event loop will take care of connecting them. */
|
||||||
ri->flags = flags;
|
ri->flags = flags;
|
||||||
@ -1303,7 +1303,7 @@ sentinelRedisInstance *sentinelRedisInstanceLookupSlave(
|
|||||||
serverAssert(ri->flags & SRI_MASTER);
|
serverAssert(ri->flags & SRI_MASTER);
|
||||||
anetFormatAddr(buf,sizeof(buf),ip,port);
|
anetFormatAddr(buf,sizeof(buf),ip,port);
|
||||||
key = sdsnew(buf);
|
key = sdsnew(buf);
|
||||||
slave = dictFetchValue(ri->slaves,key);
|
slave = (sentinelRedisInstance*)dictFetchValue(ri->slaves,key);
|
||||||
sdsfree(key);
|
sdsfree(key);
|
||||||
return slave;
|
return slave;
|
||||||
}
|
}
|
||||||
@ -1336,7 +1336,7 @@ int removeMatchingSentinelFromMaster(sentinelRedisInstance *master, char *runid)
|
|||||||
|
|
||||||
di = dictGetSafeIterator(master->sentinels);
|
di = dictGetSafeIterator(master->sentinels);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (ri->runid && strcmp(ri->runid,runid) == 0) {
|
if (ri->runid && strcmp(ri->runid,runid) == 0) {
|
||||||
dictDelete(master->sentinels,ri->name);
|
dictDelete(master->sentinels,ri->name);
|
||||||
@ -1361,7 +1361,7 @@ sentinelRedisInstance *getSentinelRedisInstanceByAddrAndRunID(dict *instances, c
|
|||||||
serverAssert(ip || runid); /* User must pass at least one search param. */
|
serverAssert(ip || runid); /* User must pass at least one search param. */
|
||||||
di = dictGetIterator(instances);
|
di = dictGetIterator(instances);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (runid && !ri->runid) continue;
|
if (runid && !ri->runid) continue;
|
||||||
if ((runid == NULL || strcmp(ri->runid, runid) == 0) &&
|
if ((runid == NULL || strcmp(ri->runid, runid) == 0) &&
|
||||||
@ -1381,7 +1381,7 @@ sentinelRedisInstance *sentinelGetMasterByName(char *name) {
|
|||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
sds sdsname = sdsnew(name);
|
sds sdsname = sdsnew(name);
|
||||||
|
|
||||||
ri = dictFetchValue(sentinel.masters,sdsname);
|
ri = (sentinelRedisInstance*)dictFetchValue(sentinel.masters,sdsname);
|
||||||
sdsfree(sdsname);
|
sdsfree(sdsname);
|
||||||
return ri;
|
return ri;
|
||||||
}
|
}
|
||||||
@ -1393,7 +1393,7 @@ void sentinelAddFlagsToDictOfRedisInstances(dict *instances, int flags) {
|
|||||||
|
|
||||||
di = dictGetIterator(instances);
|
di = dictGetIterator(instances);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
ri->flags |= flags;
|
ri->flags |= flags;
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
@ -1407,7 +1407,7 @@ void sentinelDelFlagsToDictOfRedisInstances(dict *instances, int flags) {
|
|||||||
|
|
||||||
di = dictGetIterator(instances);
|
di = dictGetIterator(instances);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
ri->flags &= ~flags;
|
ri->flags &= ~flags;
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
@ -1467,7 +1467,7 @@ int sentinelResetMastersByPattern(char *pattern, int flags) {
|
|||||||
|
|
||||||
di = dictGetIterator(sentinel.masters);
|
di = dictGetIterator(sentinel.masters);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (ri->name) {
|
if (ri->name) {
|
||||||
if (stringmatch(pattern,ri->name,0)) {
|
if (stringmatch(pattern,ri->name,0)) {
|
||||||
@ -1501,10 +1501,10 @@ int sentinelResetMasterAndChangeAddress(sentinelRedisInstance *master, char *ip,
|
|||||||
* Don't include the one having the address we are switching to. */
|
* Don't include the one having the address we are switching to. */
|
||||||
di = dictGetIterator(master->slaves);
|
di = dictGetIterator(master->slaves);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *slave = dictGetVal(de);
|
sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (sentinelAddrIsEqual(slave->addr,newaddr)) continue;
|
if (sentinelAddrIsEqual(slave->addr,newaddr)) continue;
|
||||||
slaves = zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1), MALLOC_LOCAL);
|
slaves = (sentinelAddr**)zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1), MALLOC_LOCAL);
|
||||||
slaves[numslaves++] = createSentinelAddr(slave->addr->ip,
|
slaves[numslaves++] = createSentinelAddr(slave->addr->ip,
|
||||||
slave->addr->port);
|
slave->addr->port);
|
||||||
}
|
}
|
||||||
@ -1514,7 +1514,7 @@ int sentinelResetMasterAndChangeAddress(sentinelRedisInstance *master, char *ip,
|
|||||||
* as a slave as well, so that we'll be able to sense / reconfigure
|
* as a slave as well, so that we'll be able to sense / reconfigure
|
||||||
* the old master. */
|
* the old master. */
|
||||||
if (!sentinelAddrIsEqual(newaddr,master->addr)) {
|
if (!sentinelAddrIsEqual(newaddr,master->addr)) {
|
||||||
slaves = zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1), MALLOC_LOCAL);
|
slaves = (sentinelAddr**)zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1), MALLOC_LOCAL);
|
||||||
slaves[numslaves++] = createSentinelAddr(master->addr->ip,
|
slaves[numslaves++] = createSentinelAddr(master->addr->ip,
|
||||||
master->addr->port);
|
master->addr->port);
|
||||||
}
|
}
|
||||||
@ -1584,14 +1584,14 @@ void sentinelPropagateDownAfterPeriod(sentinelRedisInstance *master) {
|
|||||||
for (j = 0; d[j]; j++) {
|
for (j = 0; d[j]; j++) {
|
||||||
di = dictGetIterator(d[j]);
|
di = dictGetIterator(d[j]);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
ri->down_after_period = master->down_after_period;
|
ri->down_after_period = master->down_after_period;
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *sentinelGetInstanceTypeString(sentinelRedisInstance *ri) {
|
const char *sentinelGetInstanceTypeString(sentinelRedisInstance *ri) {
|
||||||
if (ri->flags & SRI_MASTER) return "master";
|
if (ri->flags & SRI_MASTER) return "master";
|
||||||
else if (ri->flags & SRI_SLAVE) return "slave";
|
else if (ri->flags & SRI_SLAVE) return "slave";
|
||||||
else if (ri->flags & SRI_SENTINEL) return "sentinel";
|
else if (ri->flags & SRI_SENTINEL) return "sentinel";
|
||||||
@ -1605,16 +1605,16 @@ char *sentinelGetInstanceTypeString(sentinelRedisInstance *ri) {
|
|||||||
* we check the one of the master), and map the command that we should send
|
* we check the one of the master), and map the command that we should send
|
||||||
* to the set of renamed commads. However, if the command was not renamed,
|
* to the set of renamed commads. However, if the command was not renamed,
|
||||||
* we just return "command" itself. */
|
* we just return "command" itself. */
|
||||||
char *sentinelInstanceMapCommand(sentinelRedisInstance *ri, char *command) {
|
const char *sentinelInstanceMapCommand(sentinelRedisInstance *ri, const char *command) {
|
||||||
sds sc = sdsnew(command);
|
sds sc = sdsnew(command);
|
||||||
if (ri->master) ri = ri->master;
|
if (ri->master) ri = ri->master;
|
||||||
char *retval = dictFetchValue(ri->renamed_commands, sc);
|
char *retval = (char*)dictFetchValue(ri->renamed_commands, sc);
|
||||||
sdsfree(sc);
|
sdsfree(sc);
|
||||||
return retval ? retval : command;
|
return retval ? retval : command;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================ Config handling ============================= */
|
/* ============================ Config handling ============================= */
|
||||||
char *sentinelHandleConfiguration(char **argv, int argc) {
|
const char *sentinelHandleConfiguration(char **argv, int argc) {
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
if (!strcasecmp(argv[0],"monitor") && argc == 5) {
|
if (!strcasecmp(argv[0],"monitor") && argc == 5) {
|
||||||
@ -1781,7 +1781,7 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) {
|
|||||||
sentinelAddr *master_addr;
|
sentinelAddr *master_addr;
|
||||||
|
|
||||||
/* sentinel monitor */
|
/* sentinel monitor */
|
||||||
master = dictGetVal(de);
|
master = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
master_addr = sentinelGetCurrentMasterAddress(master);
|
master_addr = sentinelGetCurrentMasterAddress(master);
|
||||||
line = sdscatprintf(sdsempty(),"sentinel monitor %s %s %d %d",
|
line = sdscatprintf(sdsempty(),"sentinel monitor %s %s %d %d",
|
||||||
master->name, master_addr->ip, master_addr->port,
|
master->name, master_addr->ip, master_addr->port,
|
||||||
@ -1853,7 +1853,7 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) {
|
|||||||
while((de = dictNext(di2)) != NULL) {
|
while((de = dictNext(di2)) != NULL) {
|
||||||
sentinelAddr *slave_addr;
|
sentinelAddr *slave_addr;
|
||||||
|
|
||||||
ri = dictGetVal(de);
|
ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
slave_addr = ri->addr;
|
slave_addr = ri->addr;
|
||||||
|
|
||||||
/* If master_addr (obtained using sentinelGetCurrentMasterAddress()
|
/* If master_addr (obtained using sentinelGetCurrentMasterAddress()
|
||||||
@ -1873,7 +1873,7 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) {
|
|||||||
/* sentinel known-sentinel */
|
/* sentinel known-sentinel */
|
||||||
di2 = dictGetIterator(master->sentinels);
|
di2 = dictGetIterator(master->sentinels);
|
||||||
while((de = dictNext(di2)) != NULL) {
|
while((de = dictNext(di2)) != NULL) {
|
||||||
ri = dictGetVal(de);
|
ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
if (ri->runid == NULL) continue;
|
if (ri->runid == NULL) continue;
|
||||||
line = sdscatprintf(sdsempty(),
|
line = sdscatprintf(sdsempty(),
|
||||||
"sentinel known-sentinel %s %s %d %s",
|
"sentinel known-sentinel %s %s %d %s",
|
||||||
@ -1885,8 +1885,8 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) {
|
|||||||
/* sentinel rename-command */
|
/* sentinel rename-command */
|
||||||
di2 = dictGetIterator(master->renamed_commands);
|
di2 = dictGetIterator(master->renamed_commands);
|
||||||
while((de = dictNext(di2)) != NULL) {
|
while((de = dictNext(di2)) != NULL) {
|
||||||
sds oldname = dictGetKey(de);
|
sds oldname = (sds)dictGetKey(de);
|
||||||
sds newname = dictGetVal(de);
|
sds newname = (sds)dictGetVal(de);
|
||||||
line = sdscatprintf(sdsempty(),
|
line = sdscatprintf(sdsempty(),
|
||||||
"sentinel rename-command %s %s %s",
|
"sentinel rename-command %s %s %s",
|
||||||
master->name, oldname, newname);
|
master->name, oldname, newname);
|
||||||
@ -1982,7 +1982,7 @@ void sentinelSendAuthIfNeeded(sentinelRedisInstance *ri, redisAsyncContext *c) {
|
|||||||
*
|
*
|
||||||
* This makes it possible to list all the sentinel instances connected
|
* This makes it possible to list all the sentinel instances connected
|
||||||
* to a Redis servewr with CLIENT LIST, grepping for a specific name format. */
|
* to a Redis servewr with CLIENT LIST, grepping for a specific name format. */
|
||||||
void sentinelSetClientName(sentinelRedisInstance *ri, redisAsyncContext *c, char *type) {
|
void sentinelSetClientName(sentinelRedisInstance *ri, redisAsyncContext *c, const char *type) {
|
||||||
char name[64];
|
char name[64];
|
||||||
|
|
||||||
snprintf(name,sizeof(name),"sentinel-%.8s-%s",sentinel.myid,type);
|
snprintf(name,sizeof(name),"sentinel-%.8s-%s",sentinel.myid,type);
|
||||||
@ -2337,13 +2337,13 @@ void sentinelRefreshInstanceInfo(sentinelRedisInstance *ri, const char *info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
void sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
||||||
sentinelRedisInstance *ri = privdata;
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)privdata;
|
||||||
instanceLink *link = c->data;
|
instanceLink *link = (instanceLink*)c->data;
|
||||||
redisReply *r;
|
redisReply *r;
|
||||||
|
|
||||||
if (!reply || !link) return;
|
if (!reply || !link) return;
|
||||||
link->pending_commands--;
|
link->pending_commands--;
|
||||||
r = reply;
|
r = (redisReply*)reply;
|
||||||
|
|
||||||
if (r->type == REDIS_REPLY_STRING)
|
if (r->type == REDIS_REPLY_STRING)
|
||||||
sentinelRefreshInstanceInfo(ri,r->str);
|
sentinelRefreshInstanceInfo(ri,r->str);
|
||||||
@ -2352,7 +2352,7 @@ void sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata
|
|||||||
/* Just discard the reply. We use this when we are not monitoring the return
|
/* Just discard the reply. We use this when we are not monitoring the return
|
||||||
* value of the command but its effects directly. */
|
* value of the command but its effects directly. */
|
||||||
void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
||||||
instanceLink *link = c->data;
|
instanceLink *link = (instanceLink*)c->data;
|
||||||
UNUSED(reply);
|
UNUSED(reply);
|
||||||
UNUSED(privdata);
|
UNUSED(privdata);
|
||||||
|
|
||||||
@ -2360,13 +2360,13 @@ void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privd
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
void sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
||||||
sentinelRedisInstance *ri = privdata;
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)privdata;
|
||||||
instanceLink *link = c->data;
|
instanceLink *link = (instanceLink*)c->data;
|
||||||
redisReply *r;
|
redisReply *r;
|
||||||
|
|
||||||
if (!reply || !link) return;
|
if (!reply || !link) return;
|
||||||
link->pending_commands--;
|
link->pending_commands--;
|
||||||
r = reply;
|
r = (redisReply*)reply;
|
||||||
|
|
||||||
if (r->type == REDIS_REPLY_STATUS ||
|
if (r->type == REDIS_REPLY_STATUS ||
|
||||||
r->type == REDIS_REPLY_ERROR) {
|
r->type == REDIS_REPLY_ERROR) {
|
||||||
@ -2402,13 +2402,13 @@ void sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata
|
|||||||
/* This is called when we get the reply about the PUBLISH command we send
|
/* This is called when we get the reply about the PUBLISH command we send
|
||||||
* to the master to advertise this sentinel. */
|
* to the master to advertise this sentinel. */
|
||||||
void sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
void sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {
|
||||||
sentinelRedisInstance *ri = privdata;
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)privdata;
|
||||||
instanceLink *link = c->data;
|
instanceLink *link = (instanceLink*)c->data;
|
||||||
redisReply *r;
|
redisReply *r;
|
||||||
|
|
||||||
if (!reply || !link) return;
|
if (!reply || !link) return;
|
||||||
link->pending_commands--;
|
link->pending_commands--;
|
||||||
r = reply;
|
r = (redisReply*)reply;
|
||||||
|
|
||||||
/* Only update pub_time if we actually published our message. Otherwise
|
/* Only update pub_time if we actually published our message. Otherwise
|
||||||
* we'll retry again in 100 milliseconds. */
|
* we'll retry again in 100 milliseconds. */
|
||||||
@ -2421,7 +2421,7 @@ void sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privd
|
|||||||
*
|
*
|
||||||
* If the master name specified in the message is not known, the message is
|
* If the master name specified in the message is not known, the message is
|
||||||
* discarded. */
|
* discarded. */
|
||||||
void sentinelProcessHelloMessage(char *hello, int hello_len) {
|
void sentinelProcessHelloMessage(const char *hello, int hello_len) {
|
||||||
/* Format is composed of 8 tokens:
|
/* Format is composed of 8 tokens:
|
||||||
* 0=ip,1=port,2=runid,3=current_epoch,4=master_name,
|
* 0=ip,1=port,2=runid,3=current_epoch,4=master_name,
|
||||||
* 5=master_ip,6=master_port,7=master_config_epoch. */
|
* 5=master_ip,6=master_port,7=master_config_epoch. */
|
||||||
@ -2526,12 +2526,12 @@ cleanup:
|
|||||||
/* This is our Pub/Sub callback for the Hello channel. It's useful in order
|
/* This is our Pub/Sub callback for the Hello channel. It's useful in order
|
||||||
* to discover other sentinels attached at the same master. */
|
* to discover other sentinels attached at the same master. */
|
||||||
void sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata) {
|
void sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata) {
|
||||||
sentinelRedisInstance *ri = privdata;
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)privdata;
|
||||||
redisReply *r;
|
redisReply *r;
|
||||||
UNUSED(c);
|
UNUSED(c);
|
||||||
|
|
||||||
if (!reply || !ri) return;
|
if (!reply || !ri) return;
|
||||||
r = reply;
|
r = (redisReply*)reply;
|
||||||
|
|
||||||
/* Update the last activity in the pubsub channel. Note that since we
|
/* Update the last activity in the pubsub channel. Note that since we
|
||||||
* receive our messages as well this timestamp can be used to detect
|
* receive our messages as well this timestamp can be used to detect
|
||||||
@ -2613,7 +2613,7 @@ void sentinelForceHelloUpdateDictOfRedisInstances(dict *instances) {
|
|||||||
|
|
||||||
di = dictGetSafeIterator(instances);
|
di = dictGetSafeIterator(instances);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
if (ri->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))
|
if (ri->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))
|
||||||
ri->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);
|
ri->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);
|
||||||
}
|
}
|
||||||
@ -2940,7 +2940,7 @@ void addReplyDictOfRedisInstances(client *c, dict *instances) {
|
|||||||
di = dictGetIterator(instances);
|
di = dictGetIterator(instances);
|
||||||
addReplyArrayLen(c,dictSize(instances));
|
addReplyArrayLen(c,dictSize(instances));
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
addReplySentinelRedisInstance(c,ri);
|
addReplySentinelRedisInstance(c,ri);
|
||||||
}
|
}
|
||||||
@ -2955,7 +2955,7 @@ sentinelRedisInstance *sentinelGetMasterByNameOrReplyError(client *c,
|
|||||||
{
|
{
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
ri = dictFetchValue(sentinel.masters,ptrFromObj(name));
|
ri = (sentinelRedisInstance*)dictFetchValue(sentinel.masters,ptrFromObj(name));
|
||||||
if (!ri) {
|
if (!ri) {
|
||||||
addReplyError(c,"No such master with that name");
|
addReplyError(c,"No such master with that name");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2975,7 +2975,7 @@ int sentinelIsQuorumReachable(sentinelRedisInstance *master, int *usableptr) {
|
|||||||
|
|
||||||
di = dictGetIterator(master->sentinels);
|
di = dictGetIterator(master->sentinels);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (ri->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;
|
if (ri->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;
|
||||||
usable++;
|
usable++;
|
||||||
@ -2989,11 +2989,11 @@ int sentinelIsQuorumReachable(sentinelRedisInstance *master, int *usableptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sentinelCommand(client *c) {
|
void sentinelCommand(client *c) {
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[1]),"masters")) {
|
if (!strcasecmp(szFromObj(c->argv[1]),"masters")) {
|
||||||
/* SENTINEL MASTERS */
|
/* SENTINEL MASTERS */
|
||||||
if (c->argc != 2) goto numargserr;
|
if (c->argc != 2) goto numargserr;
|
||||||
addReplyDictOfRedisInstances(c,sentinel.masters);
|
addReplyDictOfRedisInstances(c,sentinel.masters);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"master")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"master")) {
|
||||||
/* SENTINEL MASTER <name> */
|
/* SENTINEL MASTER <name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
@ -3001,8 +3001,8 @@ void sentinelCommand(client *c) {
|
|||||||
if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))
|
if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))
|
||||||
== NULL) return;
|
== NULL) return;
|
||||||
addReplySentinelRedisInstance(c,ri);
|
addReplySentinelRedisInstance(c,ri);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"slaves") ||
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"slaves") ||
|
||||||
!strcasecmp(ptrFromObj(c->argv[1]),"replicas"))
|
!strcasecmp(szFromObj(c->argv[1]),"replicas"))
|
||||||
{
|
{
|
||||||
/* SENTINEL REPLICAS <master-name> */
|
/* SENTINEL REPLICAS <master-name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
@ -3011,7 +3011,7 @@ void sentinelCommand(client *c) {
|
|||||||
if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
|
if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
|
||||||
return;
|
return;
|
||||||
addReplyDictOfRedisInstances(c,ri->slaves);
|
addReplyDictOfRedisInstances(c,ri->slaves);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"sentinels")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"sentinels")) {
|
||||||
/* SENTINEL SENTINELS <master-name> */
|
/* SENTINEL SENTINELS <master-name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
@ -3019,7 +3019,7 @@ void sentinelCommand(client *c) {
|
|||||||
if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
|
if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
|
||||||
return;
|
return;
|
||||||
addReplyDictOfRedisInstances(c,ri->sentinels);
|
addReplyDictOfRedisInstances(c,ri->sentinels);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"is-master-down-by-addr")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"is-master-down-by-addr")) {
|
||||||
/* SENTINEL IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid>
|
/* SENTINEL IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid>
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
@ -3050,7 +3050,7 @@ void sentinelCommand(client *c) {
|
|||||||
!= C_OK)
|
!= C_OK)
|
||||||
return;
|
return;
|
||||||
ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters,
|
ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters,
|
||||||
ptrFromObj(c->argv[2]),port,NULL);
|
szFromObj(c->argv[2]),port,NULL);
|
||||||
|
|
||||||
/* It exists? Is actually a master? Is subjectively down? It's down.
|
/* It exists? Is actually a master? Is subjectively down? It's down.
|
||||||
* Note: if we are in tilt mode we always reply with "0". */
|
* Note: if we are in tilt mode we always reply with "0". */
|
||||||
@ -3060,9 +3060,9 @@ void sentinelCommand(client *c) {
|
|||||||
|
|
||||||
/* Vote for the master (or fetch the previous vote) if the request
|
/* Vote for the master (or fetch the previous vote) if the request
|
||||||
* includes a runid, otherwise the sender is not seeking for a vote. */
|
* includes a runid, otherwise the sender is not seeking for a vote. */
|
||||||
if (ri && ri->flags & SRI_MASTER && strcasecmp(ptrFromObj(c->argv[5]),"*")) {
|
if (ri && ri->flags & SRI_MASTER && strcasecmp(szFromObj(c->argv[5]),"*")) {
|
||||||
leader = sentinelVoteLeader(ri,(uint64_t)req_epoch,
|
leader = sentinelVoteLeader(ri,(uint64_t)req_epoch,
|
||||||
ptrFromObj(c->argv[5]),
|
szFromObj(c->argv[5]),
|
||||||
&leader_epoch);
|
&leader_epoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3073,16 +3073,16 @@ void sentinelCommand(client *c) {
|
|||||||
addReplyBulkCString(c, leader ? leader : "*");
|
addReplyBulkCString(c, leader ? leader : "*");
|
||||||
addReplyLongLong(c, (long long)leader_epoch);
|
addReplyLongLong(c, (long long)leader_epoch);
|
||||||
if (leader) sdsfree(leader);
|
if (leader) sdsfree(leader);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"reset")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"reset")) {
|
||||||
/* SENTINEL RESET <pattern> */
|
/* SENTINEL RESET <pattern> */
|
||||||
if (c->argc != 3) goto numargserr;
|
if (c->argc != 3) goto numargserr;
|
||||||
addReplyLongLong(c,sentinelResetMastersByPattern(ptrFromObj(c->argv[2]),SENTINEL_GENERATE_EVENT));
|
addReplyLongLong(c,sentinelResetMastersByPattern(szFromObj(c->argv[2]),SENTINEL_GENERATE_EVENT));
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"get-master-addr-by-name")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"get-master-addr-by-name")) {
|
||||||
/* SENTINEL GET-MASTER-ADDR-BY-NAME <master-name> */
|
/* SENTINEL GET-MASTER-ADDR-BY-NAME <master-name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
if (c->argc != 3) goto numargserr;
|
if (c->argc != 3) goto numargserr;
|
||||||
ri = sentinelGetMasterByName(ptrFromObj(c->argv[2]));
|
ri = sentinelGetMasterByName(szFromObj(c->argv[2]));
|
||||||
if (ri == NULL) {
|
if (ri == NULL) {
|
||||||
addReplyNullArray(c);
|
addReplyNullArray(c);
|
||||||
} else {
|
} else {
|
||||||
@ -3092,7 +3092,7 @@ void sentinelCommand(client *c) {
|
|||||||
addReplyBulkCString(c,addr->ip);
|
addReplyBulkCString(c,addr->ip);
|
||||||
addReplyBulkLongLong(c,addr->port);
|
addReplyBulkLongLong(c,addr->port);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"failover")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"failover")) {
|
||||||
/* SENTINEL FAILOVER <master-name> */
|
/* SENTINEL FAILOVER <master-name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
@ -3112,12 +3112,12 @@ void sentinelCommand(client *c) {
|
|||||||
sentinelStartFailover(ri);
|
sentinelStartFailover(ri);
|
||||||
ri->flags |= SRI_FORCE_FAILOVER;
|
ri->flags |= SRI_FORCE_FAILOVER;
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"pending-scripts")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"pending-scripts")) {
|
||||||
/* SENTINEL PENDING-SCRIPTS */
|
/* SENTINEL PENDING-SCRIPTS */
|
||||||
|
|
||||||
if (c->argc != 2) goto numargserr;
|
if (c->argc != 2) goto numargserr;
|
||||||
sentinelPendingScriptsCommand(c);
|
sentinelPendingScriptsCommand(c);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"monitor")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"monitor")) {
|
||||||
/* SENTINEL MONITOR <name> <ip> <port> <quorum> */
|
/* SENTINEL MONITOR <name> <ip> <port> <quorum> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
long quorum, port;
|
long quorum, port;
|
||||||
@ -3137,14 +3137,14 @@ void sentinelCommand(client *c) {
|
|||||||
/* Make sure the IP field is actually a valid IP before passing it
|
/* Make sure the IP field is actually a valid IP before passing it
|
||||||
* to createSentinelRedisInstance(), otherwise we may trigger a
|
* to createSentinelRedisInstance(), otherwise we may trigger a
|
||||||
* DNS lookup at runtime. */
|
* DNS lookup at runtime. */
|
||||||
if (anetResolveIP(NULL,ptrFromObj(c->argv[3]),ip,sizeof(ip)) == ANET_ERR) {
|
if (anetResolveIP(NULL,szFromObj(c->argv[3]),ip,sizeof(ip)) == ANET_ERR) {
|
||||||
addReplyError(c,"Invalid IP address specified");
|
addReplyError(c,"Invalid IP address specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parameters are valid. Try to create the master instance. */
|
/* Parameters are valid. Try to create the master instance. */
|
||||||
ri = createSentinelRedisInstance(ptrFromObj(c->argv[2]),SRI_MASTER,
|
ri = createSentinelRedisInstance(szFromObj(c->argv[2]),SRI_MASTER,
|
||||||
ptrFromObj(c->argv[3]),port,quorum,NULL);
|
szFromObj(c->argv[3]),port,quorum,NULL);
|
||||||
if (ri == NULL) {
|
if (ri == NULL) {
|
||||||
switch(errno) {
|
switch(errno) {
|
||||||
case EBUSY:
|
case EBUSY:
|
||||||
@ -3162,12 +3162,12 @@ void sentinelCommand(client *c) {
|
|||||||
sentinelEvent(LL_WARNING,"+monitor",ri,"%@ quorum %d",ri->quorum);
|
sentinelEvent(LL_WARNING,"+monitor",ri,"%@ quorum %d",ri->quorum);
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"flushconfig")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"flushconfig")) {
|
||||||
if (c->argc != 2) goto numargserr;
|
if (c->argc != 2) goto numargserr;
|
||||||
sentinelFlushConfig();
|
sentinelFlushConfig();
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
return;
|
return;
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"remove")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"remove")) {
|
||||||
/* SENTINEL REMOVE <name> */
|
/* SENTINEL REMOVE <name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
|
|
||||||
@ -3178,7 +3178,7 @@ void sentinelCommand(client *c) {
|
|||||||
dictDelete(sentinel.masters,ptrFromObj(c->argv[2]));
|
dictDelete(sentinel.masters,ptrFromObj(c->argv[2]));
|
||||||
sentinelFlushConfig();
|
sentinelFlushConfig();
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"ckquorum")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"ckquorum")) {
|
||||||
/* SENTINEL CKQUORUM <name> */
|
/* SENTINEL CKQUORUM <name> */
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
int usable;
|
int usable;
|
||||||
@ -3205,10 +3205,10 @@ void sentinelCommand(client *c) {
|
|||||||
e = sdscat(e,"\r\n");
|
e = sdscat(e,"\r\n");
|
||||||
addReplySds(c,e);
|
addReplySds(c,e);
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"set")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"set")) {
|
||||||
if (c->argc < 3) goto numargserr;
|
if (c->argc < 3) goto numargserr;
|
||||||
sentinelSetCommand(c);
|
sentinelSetCommand(c);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"info-cache")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"info-cache")) {
|
||||||
/* SENTINEL INFO-CACHE <name> */
|
/* SENTINEL INFO-CACHE <name> */
|
||||||
if (c->argc < 2) goto numargserr;
|
if (c->argc < 2) goto numargserr;
|
||||||
mstime_t now = mstime();
|
mstime_t now = mstime();
|
||||||
@ -3224,7 +3224,7 @@ void sentinelCommand(client *c) {
|
|||||||
|
|
||||||
for (int i = 2; i < c->argc; i++) {
|
for (int i = 2; i < c->argc; i++) {
|
||||||
sentinelRedisInstance *ri;
|
sentinelRedisInstance *ri;
|
||||||
ri = sentinelGetMasterByName(ptrFromObj(c->argv[i]));
|
ri = sentinelGetMasterByName(szFromObj(c->argv[i]));
|
||||||
if (!ri) continue; /* ignore non-existing names */
|
if (!ri) continue; /* ignore non-existing names */
|
||||||
dictAdd(masters_local, ri->name, ri);
|
dictAdd(masters_local, ri->name, ri);
|
||||||
}
|
}
|
||||||
@ -3244,7 +3244,7 @@ void sentinelCommand(client *c) {
|
|||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
di = dictGetIterator(masters_local);
|
di = dictGetIterator(masters_local);
|
||||||
while ((de = dictNext(di)) != NULL) {
|
while ((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
addReplyBulkCBuffer(c,ri->name,strlen(ri->name));
|
addReplyBulkCBuffer(c,ri->name,strlen(ri->name));
|
||||||
addReplyArrayLen(c,dictSize(ri->slaves) + 1); /* +1 for self */
|
addReplyArrayLen(c,dictSize(ri->slaves) + 1); /* +1 for self */
|
||||||
addReplyArrayLen(c,2);
|
addReplyArrayLen(c,2);
|
||||||
@ -3258,7 +3258,7 @@ void sentinelCommand(client *c) {
|
|||||||
dictEntry *sde;
|
dictEntry *sde;
|
||||||
sdi = dictGetIterator(ri->slaves);
|
sdi = dictGetIterator(ri->slaves);
|
||||||
while ((sde = dictNext(sdi)) != NULL) {
|
while ((sde = dictNext(sdi)) != NULL) {
|
||||||
sentinelRedisInstance *sri = dictGetVal(sde);
|
sentinelRedisInstance *sri = (sentinelRedisInstance*)dictGetVal(sde);
|
||||||
addReplyArrayLen(c,2);
|
addReplyArrayLen(c,2);
|
||||||
addReplyLongLong(c, now - sri->info_refresh);
|
addReplyLongLong(c, now - sri->info_refresh);
|
||||||
if (sri->info)
|
if (sri->info)
|
||||||
@ -3270,24 +3270,24 @@ void sentinelCommand(client *c) {
|
|||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
if (masters_local != sentinel.masters) dictRelease(masters_local);
|
if (masters_local != sentinel.masters) dictRelease(masters_local);
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[1]),"simulate-failure")) {
|
} else if (!strcasecmp(szFromObj(c->argv[1]),"simulate-failure")) {
|
||||||
/* SENTINEL SIMULATE-FAILURE <flag> <flag> ... <flag> */
|
/* SENTINEL SIMULATE-FAILURE <flag> <flag> ... <flag> */
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
sentinel.simfailure_flags = SENTINEL_SIMFAILURE_NONE;
|
sentinel.simfailure_flags = SENTINEL_SIMFAILURE_NONE;
|
||||||
for (j = 2; j < c->argc; j++) {
|
for (j = 2; j < c->argc; j++) {
|
||||||
if (!strcasecmp(ptrFromObj(c->argv[j]),"crash-after-election")) {
|
if (!strcasecmp(szFromObj(c->argv[j]),"crash-after-election")) {
|
||||||
sentinel.simfailure_flags |=
|
sentinel.simfailure_flags |=
|
||||||
SENTINEL_SIMFAILURE_CRASH_AFTER_ELECTION;
|
SENTINEL_SIMFAILURE_CRASH_AFTER_ELECTION;
|
||||||
serverLog(LL_WARNING,"Failure simulation: this Sentinel "
|
serverLog(LL_WARNING,"Failure simulation: this Sentinel "
|
||||||
"will crash after being successfully elected as failover "
|
"will crash after being successfully elected as failover "
|
||||||
"leader");
|
"leader");
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"crash-after-promotion")) {
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"crash-after-promotion")) {
|
||||||
sentinel.simfailure_flags |=
|
sentinel.simfailure_flags |=
|
||||||
SENTINEL_SIMFAILURE_CRASH_AFTER_PROMOTION;
|
SENTINEL_SIMFAILURE_CRASH_AFTER_PROMOTION;
|
||||||
serverLog(LL_WARNING,"Failure simulation: this Sentinel "
|
serverLog(LL_WARNING,"Failure simulation: this Sentinel "
|
||||||
"will crash after promoting the selected replica to master");
|
"will crash after promoting the selected replica to master");
|
||||||
} else if (!strcasecmp(ptrFromObj(c->argv[j]),"help")) {
|
} else if (!strcasecmp(szFromObj(c->argv[j]),"help")) {
|
||||||
addReplyArrayLen(c,2);
|
addReplyArrayLen(c,2);
|
||||||
addReplyBulkCString(c,"crash-after-election");
|
addReplyBulkCString(c,"crash-after-election");
|
||||||
addReplyBulkCString(c,"crash-after-promotion");
|
addReplyBulkCString(c,"crash-after-promotion");
|
||||||
@ -3326,7 +3326,7 @@ void sentinelInfoCommand(client *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int defsections = 0, allsections = 0;
|
int defsections = 0, allsections = 0;
|
||||||
char *section = c->argc == 2 ? ptrFromObj(c->argv[1]) : NULL;
|
char *section = c->argc == 2 ? szFromObj(c->argv[1]) : NULL;
|
||||||
if (section) {
|
if (section) {
|
||||||
allsections = !strcasecmp(section,"all");
|
allsections = !strcasecmp(section,"all");
|
||||||
defsections = !strcasecmp(section,"default");
|
defsections = !strcasecmp(section,"default");
|
||||||
@ -3363,8 +3363,8 @@ void sentinelInfoCommand(client *c) {
|
|||||||
|
|
||||||
di = dictGetIterator(sentinel.masters);
|
di = dictGetIterator(sentinel.masters);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
char *status = "ok";
|
const char *status = "ok";
|
||||||
|
|
||||||
if (ri->flags & SRI_O_DOWN) status = "odown";
|
if (ri->flags & SRI_O_DOWN) status = "odown";
|
||||||
else if (ri->flags & SRI_S_DOWN) status = "sdown";
|
else if (ri->flags & SRI_S_DOWN) status = "sdown";
|
||||||
@ -3394,7 +3394,7 @@ void sentinelRoleCommand(client *c) {
|
|||||||
|
|
||||||
di = dictGetIterator(sentinel.masters);
|
di = dictGetIterator(sentinel.masters);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
addReplyBulkCString(c,ri->name);
|
addReplyBulkCString(c,ri->name);
|
||||||
}
|
}
|
||||||
@ -3414,7 +3414,7 @@ void sentinelSetCommand(client *c) {
|
|||||||
/* Process option - value pairs. */
|
/* Process option - value pairs. */
|
||||||
for (j = 3; j < c->argc; j++) {
|
for (j = 3; j < c->argc; j++) {
|
||||||
int moreargs = (c->argc-1) - j;
|
int moreargs = (c->argc-1) - j;
|
||||||
option = ptrFromObj(c->argv[j]);
|
option = szFromObj(c->argv[j]);
|
||||||
long long ll;
|
long long ll;
|
||||||
int old_j = j; /* Used to know what to log as an event. */
|
int old_j = j; /* Used to know what to log as an event. */
|
||||||
|
|
||||||
@ -3448,7 +3448,7 @@ void sentinelSetCommand(client *c) {
|
|||||||
changes++;
|
changes++;
|
||||||
} else if (!strcasecmp(option,"notification-script") && moreargs > 0) {
|
} else if (!strcasecmp(option,"notification-script") && moreargs > 0) {
|
||||||
/* notification-script <path> */
|
/* notification-script <path> */
|
||||||
char *value = ptrFromObj(c->argv[++j]);
|
char *value = szFromObj(c->argv[++j]);
|
||||||
if (sentinel.deny_scripts_reconfig) {
|
if (sentinel.deny_scripts_reconfig) {
|
||||||
addReplyError(c,
|
addReplyError(c,
|
||||||
"Reconfiguration of scripts path is denied for "
|
"Reconfiguration of scripts path is denied for "
|
||||||
@ -3468,7 +3468,7 @@ void sentinelSetCommand(client *c) {
|
|||||||
changes++;
|
changes++;
|
||||||
} else if (!strcasecmp(option,"client-reconfig-script") && moreargs > 0) {
|
} else if (!strcasecmp(option,"client-reconfig-script") && moreargs > 0) {
|
||||||
/* client-reconfig-script <path> */
|
/* client-reconfig-script <path> */
|
||||||
char *value = ptrFromObj(c->argv[++j]);
|
char *value = szFromObj(c->argv[++j]);
|
||||||
if (sentinel.deny_scripts_reconfig) {
|
if (sentinel.deny_scripts_reconfig) {
|
||||||
addReplyError(c,
|
addReplyError(c,
|
||||||
"Reconfiguration of scripts path is denied for "
|
"Reconfiguration of scripts path is denied for "
|
||||||
@ -3489,7 +3489,7 @@ void sentinelSetCommand(client *c) {
|
|||||||
changes++;
|
changes++;
|
||||||
} else if (!strcasecmp(option,"auth-pass") && moreargs > 0) {
|
} else if (!strcasecmp(option,"auth-pass") && moreargs > 0) {
|
||||||
/* auth-pass <password> */
|
/* auth-pass <password> */
|
||||||
char *value = ptrFromObj(c->argv[++j]);
|
char *value = szFromObj(c->argv[++j]);
|
||||||
sdsfree(ri->auth_pass);
|
sdsfree(ri->auth_pass);
|
||||||
ri->auth_pass = strlen(value) ? sdsnew(value) : NULL;
|
ri->auth_pass = strlen(value) ? sdsnew(value) : NULL;
|
||||||
changes++;
|
changes++;
|
||||||
@ -3504,8 +3504,8 @@ void sentinelSetCommand(client *c) {
|
|||||||
changes++;
|
changes++;
|
||||||
} else if (!strcasecmp(option,"rename-command") && moreargs > 1) {
|
} else if (!strcasecmp(option,"rename-command") && moreargs > 1) {
|
||||||
/* rename-command <oldname> <newname> */
|
/* rename-command <oldname> <newname> */
|
||||||
sds oldname = ptrFromObj(c->argv[++j]);
|
sds oldname = szFromObj(c->argv[++j]);
|
||||||
sds newname = ptrFromObj(c->argv[++j]);
|
sds newname = szFromObj(c->argv[++j]);
|
||||||
|
|
||||||
if ((sdslen(oldname) == 0) || (sdslen(newname) == 0)) {
|
if ((sdslen(oldname) == 0) || (sdslen(newname) == 0)) {
|
||||||
badarg = sdslen(newname) ? j-1 : j;
|
badarg = sdslen(newname) ? j-1 : j;
|
||||||
@ -3565,11 +3565,11 @@ badfmt: /* Bad format errors */
|
|||||||
* Because we have a Sentinel PUBLISH, the code to send hello messages is the same
|
* Because we have a Sentinel PUBLISH, the code to send hello messages is the same
|
||||||
* for all the three kind of instances: masters, slaves, sentinels. */
|
* for all the three kind of instances: masters, slaves, sentinels. */
|
||||||
void sentinelPublishCommand(client *c) {
|
void sentinelPublishCommand(client *c) {
|
||||||
if (strcmp(ptrFromObj(c->argv[1]),SENTINEL_HELLO_CHANNEL)) {
|
if (strcmp(szFromObj(c->argv[1]),SENTINEL_HELLO_CHANNEL)) {
|
||||||
addReplyError(c, "Only HELLO messages are accepted by Sentinel instances.");
|
addReplyError(c, "Only HELLO messages are accepted by Sentinel instances.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sentinelProcessHelloMessage(ptrFromObj(c->argv[2]),sdslen(ptrFromObj(c->argv[2])));
|
sentinelProcessHelloMessage(szFromObj(c->argv[2]),sdslen(szFromObj(c->argv[2])));
|
||||||
addReplyLongLong(c,1);
|
addReplyLongLong(c,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3659,7 +3659,7 @@ void sentinelCheckObjectivelyDown(sentinelRedisInstance *master) {
|
|||||||
/* Count all the other sentinels. */
|
/* Count all the other sentinels. */
|
||||||
di = dictGetIterator(master->sentinels);
|
di = dictGetIterator(master->sentinels);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (ri->flags & SRI_MASTER_DOWN) quorum++;
|
if (ri->flags & SRI_MASTER_DOWN) quorum++;
|
||||||
}
|
}
|
||||||
@ -3686,13 +3686,13 @@ void sentinelCheckObjectivelyDown(sentinelRedisInstance *master) {
|
|||||||
/* Receive the SENTINEL is-master-down-by-addr reply, see the
|
/* Receive the SENTINEL is-master-down-by-addr reply, see the
|
||||||
* sentinelAskMasterStateToOtherSentinels() function for more information. */
|
* sentinelAskMasterStateToOtherSentinels() function for more information. */
|
||||||
void sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *privdata) {
|
void sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *privdata) {
|
||||||
sentinelRedisInstance *ri = privdata;
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)privdata;
|
||||||
instanceLink *link = c->data;
|
instanceLink *link = (instanceLink*)c->data;
|
||||||
redisReply *r;
|
redisReply *r;
|
||||||
|
|
||||||
if (!reply || !link) return;
|
if (!reply || !link) return;
|
||||||
link->pending_commands--;
|
link->pending_commands--;
|
||||||
r = reply;
|
r = (redisReply*)reply;
|
||||||
|
|
||||||
/* Ignore every error or unexpected reply.
|
/* Ignore every error or unexpected reply.
|
||||||
* Note that if the command returns an error for any reason we'll
|
* Note that if the command returns an error for any reason we'll
|
||||||
@ -3734,7 +3734,7 @@ void sentinelAskMasterStateToOtherSentinels(sentinelRedisInstance *master, int f
|
|||||||
|
|
||||||
di = dictGetIterator(master->sentinels);
|
di = dictGetIterator(master->sentinels);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
mstime_t elapsed = mstime() - ri->last_master_down_reply_time;
|
mstime_t elapsed = mstime() - ri->last_master_down_reply_time;
|
||||||
char port[32];
|
char port[32];
|
||||||
int retval;
|
int retval;
|
||||||
@ -3860,7 +3860,7 @@ char *sentinelGetLeader(sentinelRedisInstance *master, uint64_t epoch) {
|
|||||||
/* Count other sentinels votes */
|
/* Count other sentinels votes */
|
||||||
di = dictGetIterator(master->sentinels);
|
di = dictGetIterator(master->sentinels);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
if (ri->leader != NULL && ri->leader_epoch == sentinel.current_epoch)
|
if (ri->leader != NULL && ri->leader_epoch == sentinel.current_epoch)
|
||||||
sentinelLeaderIncr(counters,ri->leader);
|
sentinelLeaderIncr(counters,ri->leader);
|
||||||
}
|
}
|
||||||
@ -3875,7 +3875,7 @@ char *sentinelGetLeader(sentinelRedisInstance *master, uint64_t epoch) {
|
|||||||
|
|
||||||
if (votes > max_votes) {
|
if (votes > max_votes) {
|
||||||
max_votes = votes;
|
max_votes = votes;
|
||||||
winner = dictGetKey(de);
|
winner = (char*)dictGetKey(de);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dictReleaseIterator(di);
|
dictReleaseIterator(di);
|
||||||
@ -3917,7 +3917,7 @@ char *sentinelGetLeader(sentinelRedisInstance *master, uint64_t epoch) {
|
|||||||
* The command returns C_OK if the SLAVEOF command was accepted for
|
* The command returns C_OK if the SLAVEOF command was accepted for
|
||||||
* (later) delivery otherwise C_ERR. The command replies are just
|
* (later) delivery otherwise C_ERR. The command replies are just
|
||||||
* discarded. */
|
* discarded. */
|
||||||
int sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port) {
|
int sentinelSendSlaveOf(sentinelRedisInstance *ri, const char *host, int port) {
|
||||||
char portstr[32];
|
char portstr[32];
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@ -4096,7 +4096,7 @@ int compareSlavesForPromotion(const void *a, const void *b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) {
|
sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) {
|
||||||
sentinelRedisInstance **instance =
|
sentinelRedisInstance **instance = (sentinelRedisInstance**)
|
||||||
zmalloc(sizeof(instance[0])*dictSize(master->slaves), MALLOC_LOCAL);
|
zmalloc(sizeof(instance[0])*dictSize(master->slaves), MALLOC_LOCAL);
|
||||||
sentinelRedisInstance *selected = NULL;
|
sentinelRedisInstance *selected = NULL;
|
||||||
int instances = 0;
|
int instances = 0;
|
||||||
@ -4110,7 +4110,7 @@ sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) {
|
|||||||
|
|
||||||
di = dictGetIterator(master->slaves);
|
di = dictGetIterator(master->slaves);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *slave = dictGetVal(de);
|
sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
mstime_t info_validity_time;
|
mstime_t info_validity_time;
|
||||||
|
|
||||||
if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;
|
if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;
|
||||||
@ -4245,7 +4245,7 @@ void sentinelFailoverDetectEnd(sentinelRedisInstance *master) {
|
|||||||
* configured. */
|
* configured. */
|
||||||
di = dictGetIterator(master->slaves);
|
di = dictGetIterator(master->slaves);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *slave = dictGetVal(de);
|
sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (slave->flags & (SRI_PROMOTED|SRI_RECONF_DONE)) continue;
|
if (slave->flags & (SRI_PROMOTED|SRI_RECONF_DONE)) continue;
|
||||||
if (slave->flags & SRI_S_DOWN) continue;
|
if (slave->flags & SRI_S_DOWN) continue;
|
||||||
@ -4275,7 +4275,7 @@ void sentinelFailoverDetectEnd(sentinelRedisInstance *master) {
|
|||||||
|
|
||||||
di = dictGetIterator(master->slaves);
|
di = dictGetIterator(master->slaves);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *slave = dictGetVal(de);
|
sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (slave->flags & (SRI_RECONF_DONE|SRI_RECONF_SENT)) continue;
|
if (slave->flags & (SRI_RECONF_DONE|SRI_RECONF_SENT)) continue;
|
||||||
@ -4303,7 +4303,7 @@ void sentinelFailoverReconfNextSlave(sentinelRedisInstance *master) {
|
|||||||
|
|
||||||
di = dictGetIterator(master->slaves);
|
di = dictGetIterator(master->slaves);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *slave = dictGetVal(de);
|
sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
if (slave->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG))
|
if (slave->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG))
|
||||||
in_progress++;
|
in_progress++;
|
||||||
@ -4314,7 +4314,7 @@ void sentinelFailoverReconfNextSlave(sentinelRedisInstance *master) {
|
|||||||
while(in_progress < master->parallel_syncs &&
|
while(in_progress < master->parallel_syncs &&
|
||||||
(de = dictNext(di)) != NULL)
|
(de = dictNext(di)) != NULL)
|
||||||
{
|
{
|
||||||
sentinelRedisInstance *slave = dictGetVal(de);
|
sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* Skip the promoted slave, and already configured slaves. */
|
/* Skip the promoted slave, and already configured slaves. */
|
||||||
@ -4461,7 +4461,7 @@ void sentinelHandleDictOfRedisInstances(dict *instances) {
|
|||||||
/* There are a number of things we need to perform against every master. */
|
/* There are a number of things we need to perform against every master. */
|
||||||
di = dictGetIterator(instances);
|
di = dictGetIterator(instances);
|
||||||
while((de = dictNext(di)) != NULL) {
|
while((de = dictNext(di)) != NULL) {
|
||||||
sentinelRedisInstance *ri = dictGetVal(de);
|
sentinelRedisInstance *ri = (sentinelRedisInstance*)dictGetVal(de);
|
||||||
|
|
||||||
sentinelHandleRedisInstance(ri);
|
sentinelHandleRedisInstance(ri);
|
||||||
if (ri->flags & SRI_MASTER) {
|
if (ri->flags & SRI_MASTER) {
|
@ -997,10 +997,6 @@ struct redisCommand redisCommandTable[] = {
|
|||||||
"admin no-script ok-loading ok-stale",
|
"admin no-script ok-loading ok-stale",
|
||||||
0,NULL,0,0,0,0,0,0},
|
0,NULL,0,0,0,0,0,0},
|
||||||
|
|
||||||
{"lolwut",lolwutCommand,-1,
|
|
||||||
"read-only fast",
|
|
||||||
0,NULL,0,0,0,0,0,0},
|
|
||||||
|
|
||||||
{"acl",aclCommand,-2,
|
{"acl",aclCommand,-2,
|
||||||
"admin no-script ok-loading ok-stale",
|
"admin no-script ok-loading ok-stale",
|
||||||
0,NULL,0,0,0,0,0,0},
|
0,NULL,0,0,0,0,0,0},
|
||||||
@ -1139,13 +1135,13 @@ void exitFromChild(int retcode) {
|
|||||||
* keys and redis objects as values (objects can hold SDS strings,
|
* keys and redis objects as values (objects can hold SDS strings,
|
||||||
* lists, sets). */
|
* lists, sets). */
|
||||||
|
|
||||||
extern "C" void dictVanillaFree(void *privdata, void *val)
|
void dictVanillaFree(void *privdata, void *val)
|
||||||
{
|
{
|
||||||
DICT_NOTUSED(privdata);
|
DICT_NOTUSED(privdata);
|
||||||
zfree(val);
|
zfree(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void dictListDestructor(void *privdata, void *val)
|
void dictListDestructor(void *privdata, void *val)
|
||||||
{
|
{
|
||||||
DICT_NOTUSED(privdata);
|
DICT_NOTUSED(privdata);
|
||||||
listRelease((list*)val);
|
listRelease((list*)val);
|
||||||
@ -1165,7 +1161,7 @@ int dictSdsKeyCompare(void *privdata, const void *key1,
|
|||||||
|
|
||||||
/* A case insensitive version used for the command lookup table and other
|
/* A case insensitive version used for the command lookup table and other
|
||||||
* places where case insensitive non binary-safe comparison is needed. */
|
* places where case insensitive non binary-safe comparison is needed. */
|
||||||
extern "C" int dictSdsKeyCaseCompare(void *privdata, const void *key1,
|
int dictSdsKeyCaseCompare(void *privdata, const void *key1,
|
||||||
const void *key2)
|
const void *key2)
|
||||||
{
|
{
|
||||||
DICT_NOTUSED(privdata);
|
DICT_NOTUSED(privdata);
|
||||||
@ -1205,7 +1201,7 @@ uint64_t dictSdsHash(const void *key) {
|
|||||||
return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));
|
return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" uint64_t dictSdsCaseHash(const void *key) {
|
uint64_t dictSdsCaseHash(const void *key) {
|
||||||
return dictGenCaseHashFunction((unsigned char*)key, sdslen((char*)key));
|
return dictGenCaseHashFunction((unsigned char*)key, sdslen((char*)key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2155,7 +2151,7 @@ void afterSleep(struct aeEventLoop *eventLoop) {
|
|||||||
|
|
||||||
/* =========================== Server initialization ======================== */
|
/* =========================== Server initialization ======================== */
|
||||||
|
|
||||||
extern "C" void createSharedObjects(void) {
|
void createSharedObjects(void) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
shared.crlf = createObject(OBJ_STRING,sdsnew("\r\n"));
|
shared.crlf = createObject(OBJ_STRING,sdsnew("\r\n"));
|
||||||
@ -2299,7 +2295,6 @@ void initServerConfig(void) {
|
|||||||
server.unixsocketperm = CONFIG_DEFAULT_UNIX_SOCKET_PERM;
|
server.unixsocketperm = CONFIG_DEFAULT_UNIX_SOCKET_PERM;
|
||||||
server.sofd = -1;
|
server.sofd = -1;
|
||||||
server.protected_mode = CONFIG_DEFAULT_PROTECTED_MODE;
|
server.protected_mode = CONFIG_DEFAULT_PROTECTED_MODE;
|
||||||
server.gopher_enabled = CONFIG_DEFAULT_GOPHER_ENABLED;
|
|
||||||
server.dbnum = CONFIG_DEFAULT_DBNUM;
|
server.dbnum = CONFIG_DEFAULT_DBNUM;
|
||||||
server.verbosity = CONFIG_DEFAULT_VERBOSITY;
|
server.verbosity = CONFIG_DEFAULT_VERBOSITY;
|
||||||
server.maxidletime = CONFIG_DEFAULT_CLIENT_TIMEOUT;
|
server.maxidletime = CONFIG_DEFAULT_CLIENT_TIMEOUT;
|
||||||
@ -4761,7 +4756,7 @@ void redisOutOfMemoryHandler(size_t allocation_size) {
|
|||||||
serverPanic("Redis aborting for OUT OF MEMORY");
|
serverPanic("Redis aborting for OUT OF MEMORY");
|
||||||
}
|
}
|
||||||
|
|
||||||
void redisSetProcTitle(char *title) {
|
void redisSetProcTitle(const char *title) {
|
||||||
#ifdef USE_SETPROCTITLE
|
#ifdef USE_SETPROCTITLE
|
||||||
const char *server_mode = "";
|
const char *server_mode = "";
|
||||||
if (server.cluster_enabled) server_mode = " [cluster]";
|
if (server.cluster_enabled) server_mode = " [cluster]";
|
||||||
@ -4968,7 +4963,7 @@ int main(int argc, char **argv) {
|
|||||||
* the program main. However the program is part of the Redis executable
|
* the program main. However the program is part of the Redis executable
|
||||||
* so that we can easily execute an RDB check on loading errors. */
|
* so that we can easily execute an RDB check on loading errors. */
|
||||||
if (strstr(argv[0],"keydb-check-rdb") != NULL)
|
if (strstr(argv[0],"keydb-check-rdb") != NULL)
|
||||||
redis_check_rdb_main(argc,argv,NULL);
|
redis_check_rdb_main(argc,(const char**)argv,NULL);
|
||||||
else if (strstr(argv[0],"keydb-check-aof") != NULL)
|
else if (strstr(argv[0],"keydb-check-aof") != NULL)
|
||||||
redis_check_aof_main(argc,argv);
|
redis_check_aof_main(argc,argv);
|
||||||
|
|
||||||
|
21
src/server.h
21
src/server.h
@ -136,7 +136,6 @@ extern "C" {
|
|||||||
#define CONFIG_DEFAULT_UNIX_SOCKET_PERM 0
|
#define CONFIG_DEFAULT_UNIX_SOCKET_PERM 0
|
||||||
#define CONFIG_DEFAULT_TCP_KEEPALIVE 300
|
#define CONFIG_DEFAULT_TCP_KEEPALIVE 300
|
||||||
#define CONFIG_DEFAULT_PROTECTED_MODE 1
|
#define CONFIG_DEFAULT_PROTECTED_MODE 1
|
||||||
#define CONFIG_DEFAULT_GOPHER_ENABLED 0
|
|
||||||
#define CONFIG_DEFAULT_LOGFILE ""
|
#define CONFIG_DEFAULT_LOGFILE ""
|
||||||
#define CONFIG_DEFAULT_SYSLOG_ENABLED 0
|
#define CONFIG_DEFAULT_SYSLOG_ENABLED 0
|
||||||
#define CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR 1
|
#define CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR 1
|
||||||
@ -1171,8 +1170,6 @@ struct redisServer {
|
|||||||
dict *migrate_cached_sockets;/* MIGRATE cached sockets */
|
dict *migrate_cached_sockets;/* MIGRATE cached sockets */
|
||||||
uint64_t next_client_id; /* Next client unique ID. Incremental. */
|
uint64_t next_client_id; /* Next client unique ID. Incremental. */
|
||||||
int protected_mode; /* Don't accept external connections. */
|
int protected_mode; /* Don't accept external connections. */
|
||||||
int gopher_enabled; /* If true the server will reply to gopher
|
|
||||||
queries. Will still serve RESP2 queries. */
|
|
||||||
/* RDB / AOF loading information */
|
/* RDB / AOF loading information */
|
||||||
int loading; /* We are loading data from disk if true */
|
int loading; /* We are loading data from disk if true */
|
||||||
off_t loading_total_bytes;
|
off_t loading_total_bytes;
|
||||||
@ -1604,7 +1601,7 @@ void getRandomBytes(unsigned char *p, size_t len);
|
|||||||
uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
|
uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
|
||||||
void exitFromChild(int retcode);
|
void exitFromChild(int retcode);
|
||||||
size_t redisPopcount(void *s, long count);
|
size_t redisPopcount(void *s, long count);
|
||||||
void redisSetProcTitle(char *title);
|
void redisSetProcTitle(const char *title);
|
||||||
|
|
||||||
/* networking.c -- Networking and Client related operations */
|
/* networking.c -- Networking and Client related operations */
|
||||||
client *createClient(int fd, int iel);
|
client *createClient(int fd, int iel);
|
||||||
@ -1621,7 +1618,6 @@ void setDeferredAttributeLen(client *c, void *node, long length);
|
|||||||
void setDeferredPushLen(client *c, void *node, long length);
|
void setDeferredPushLen(client *c, void *node, long length);
|
||||||
void processInputBuffer(client *c, int callFlags);
|
void processInputBuffer(client *c, int callFlags);
|
||||||
void processInputBufferAndReplicate(client *c);
|
void processInputBufferAndReplicate(client *c);
|
||||||
void processGopherRequest(client *c);
|
|
||||||
void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);
|
void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);
|
||||||
void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask);
|
void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask);
|
||||||
void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask);
|
void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask);
|
||||||
@ -1785,7 +1781,7 @@ int getDoubleFromObject(const robj *o, double *target);
|
|||||||
int getLongLongFromObject(robj *o, long long *target);
|
int getLongLongFromObject(robj *o, long long *target);
|
||||||
int getLongDoubleFromObject(robj *o, long double *target);
|
int getLongDoubleFromObject(robj *o, long double *target);
|
||||||
int getLongDoubleFromObjectOrReply(client *c, robj *o, long double *target, const char *msg);
|
int getLongDoubleFromObjectOrReply(client *c, robj *o, long double *target, const char *msg);
|
||||||
char *strEncoding(int encoding);
|
const char *strEncoding(int encoding);
|
||||||
int compareStringObjects(robj *a, robj *b);
|
int compareStringObjects(robj *a, robj *b);
|
||||||
int collateStringObjects(robj *a, robj *b);
|
int collateStringObjects(robj *a, robj *b);
|
||||||
int equalStringObjects(robj *a, robj *b);
|
int equalStringObjects(robj *a, robj *b);
|
||||||
@ -1827,7 +1823,7 @@ void changeReplicationId(void);
|
|||||||
void clearReplicationId2(void);
|
void clearReplicationId2(void);
|
||||||
void chopReplicationBacklog(void);
|
void chopReplicationBacklog(void);
|
||||||
void replicationCacheMasterUsingMyself(struct redisMaster *mi);
|
void replicationCacheMasterUsingMyself(struct redisMaster *mi);
|
||||||
void feedReplicationBacklog(void *ptr, size_t len);
|
void feedReplicationBacklog(const void *ptr, size_t len);
|
||||||
|
|
||||||
/* Generic persistence functions */
|
/* Generic persistence functions */
|
||||||
void startLoading(FILE *fp);
|
void startLoading(FILE *fp);
|
||||||
@ -1881,7 +1877,7 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen);
|
|||||||
sds ACLDefaultUserFirstPassword(void);
|
sds ACLDefaultUserFirstPassword(void);
|
||||||
uint64_t ACLGetCommandCategoryFlagByName(const char *name);
|
uint64_t ACLGetCommandCategoryFlagByName(const char *name);
|
||||||
int ACLAppendUserForLoading(sds *argv, int argc, int *argc_err);
|
int ACLAppendUserForLoading(sds *argv, int argc, int *argc_err);
|
||||||
char *ACLSetUserStringError(void);
|
const char *ACLSetUserStringError(void);
|
||||||
int ACLLoadConfiguredUsers(void);
|
int ACLLoadConfiguredUsers(void);
|
||||||
sds ACLDescribeUser(user *u);
|
sds ACLDescribeUser(user *u);
|
||||||
void ACLLoadUsersAtStartup(void);
|
void ACLLoadUsersAtStartup(void);
|
||||||
@ -2130,12 +2126,12 @@ int clusterSendModuleMessageToTarget(const char *target, uint64_t module_id, uin
|
|||||||
void initSentinelConfig(void);
|
void initSentinelConfig(void);
|
||||||
void initSentinel(void);
|
void initSentinel(void);
|
||||||
void sentinelTimer(void);
|
void sentinelTimer(void);
|
||||||
char *sentinelHandleConfiguration(char **argv, int argc);
|
const char *sentinelHandleConfiguration(char **argv, int argc);
|
||||||
void sentinelIsRunning(void);
|
void sentinelIsRunning(void);
|
||||||
|
|
||||||
/* keydb-check-rdb & aof */
|
/* keydb-check-rdb & aof */
|
||||||
int redis_check_rdb(char *rdbfilename, FILE *fp);
|
int redis_check_rdb(const char *rdbfilename, FILE *fp);
|
||||||
int redis_check_rdb_main(int argc, char **argv, FILE *fp);
|
int redis_check_rdb_main(int argc, const char **argv, FILE *fp);
|
||||||
int redis_check_aof_main(int argc, char **argv);
|
int redis_check_aof_main(int argc, char **argv);
|
||||||
|
|
||||||
/* Scripting */
|
/* Scripting */
|
||||||
@ -2376,7 +2372,6 @@ void xclaimCommand(client *c);
|
|||||||
void xinfoCommand(client *c);
|
void xinfoCommand(client *c);
|
||||||
void xdelCommand(client *c);
|
void xdelCommand(client *c);
|
||||||
void xtrimCommand(client *c);
|
void xtrimCommand(client *c);
|
||||||
void lolwutCommand(client *c);
|
|
||||||
void aclCommand(client *c);
|
void aclCommand(client *c);
|
||||||
void replicaReplayCommand(client *c);
|
void replicaReplayCommand(client *c);
|
||||||
|
|
||||||
@ -2407,7 +2402,7 @@ void watchdogScheduleSignal(int period);
|
|||||||
void serverLogHexDump(int level, const char *descr, void *value, size_t len);
|
void serverLogHexDump(int level, const char *descr, void *value, size_t len);
|
||||||
int memtest_preserving_test(unsigned long *m, size_t bytes, int passes);
|
int memtest_preserving_test(unsigned long *m, size_t bytes, int passes);
|
||||||
void mixDigest(unsigned char *digest, void *ptr, size_t len);
|
void mixDigest(unsigned char *digest, void *ptr, size_t len);
|
||||||
void xorDigest(unsigned char *digest, void *ptr, size_t len);
|
void xorDigest(unsigned char *digest, const void *ptr, size_t len);
|
||||||
int populateCommandTableParseFlags(struct redisCommand *c, const char *strflags);
|
int populateCommandTableParseFlags(struct redisCommand *c, const char *strflags);
|
||||||
|
|
||||||
int moduleGILAcquiredByModule(void);
|
int moduleGILAcquiredByModule(void);
|
||||||
|
@ -46,12 +46,12 @@
|
|||||||
* Incrementing the ref count of all the objects retained is up to
|
* Incrementing the ref count of all the objects retained is up to
|
||||||
* this function. */
|
* this function. */
|
||||||
slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long duration) {
|
slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long duration) {
|
||||||
slowlogEntry *se = zmalloc(sizeof(*se), MALLOC_LOCAL);
|
slowlogEntry *se = (slowlogEntry*)zmalloc(sizeof(*se), MALLOC_LOCAL);
|
||||||
int j, slargc = argc;
|
int j, slargc = argc;
|
||||||
|
|
||||||
if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC;
|
if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC;
|
||||||
se->argc = slargc;
|
se->argc = slargc;
|
||||||
se->argv = zmalloc(sizeof(robj*)*slargc, MALLOC_LOCAL);
|
se->argv = (robj**)zmalloc(sizeof(robj*)*slargc, MALLOC_LOCAL);
|
||||||
for (j = 0; j < slargc; j++) {
|
for (j = 0; j < slargc; j++) {
|
||||||
/* Logging too many arguments is a useless memory waste, so we stop
|
/* Logging too many arguments is a useless memory waste, so we stop
|
||||||
* at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify
|
* at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify
|
||||||
@ -64,13 +64,13 @@ slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long dur
|
|||||||
/* Trim too long strings as well... */
|
/* Trim too long strings as well... */
|
||||||
if (argv[j]->type == OBJ_STRING &&
|
if (argv[j]->type == OBJ_STRING &&
|
||||||
sdsEncodedObject(argv[j]) &&
|
sdsEncodedObject(argv[j]) &&
|
||||||
sdslen(ptrFromObj(argv[j])) > SLOWLOG_ENTRY_MAX_STRING)
|
sdslen(szFromObj(argv[j])) > SLOWLOG_ENTRY_MAX_STRING)
|
||||||
{
|
{
|
||||||
sds s = sdsnewlen(ptrFromObj(argv[j]), SLOWLOG_ENTRY_MAX_STRING);
|
sds s = sdsnewlen(ptrFromObj(argv[j]), SLOWLOG_ENTRY_MAX_STRING);
|
||||||
|
|
||||||
s = sdscatprintf(s,"... (%lu more bytes)",
|
s = sdscatprintf(s,"... (%lu more bytes)",
|
||||||
(unsigned long)
|
(unsigned long)
|
||||||
sdslen(ptrFromObj(argv[j])) - SLOWLOG_ENTRY_MAX_STRING);
|
sdslen(szFromObj(argv[j])) - SLOWLOG_ENTRY_MAX_STRING);
|
||||||
se->argv[j] = createObject(OBJ_STRING,s);
|
se->argv[j] = createObject(OBJ_STRING,s);
|
||||||
} else if (argv[j]->refcount == OBJ_SHARED_REFCOUNT) {
|
} else if (argv[j]->refcount == OBJ_SHARED_REFCOUNT) {
|
||||||
se->argv[j] = argv[j];
|
se->argv[j] = argv[j];
|
||||||
@ -89,7 +89,7 @@ slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long dur
|
|||||||
se->duration = duration;
|
se->duration = duration;
|
||||||
se->id = server.slowlog_entry_id++;
|
se->id = server.slowlog_entry_id++;
|
||||||
se->peerid = sdsnew(getClientPeerId(c));
|
se->peerid = sdsnew(getClientPeerId(c));
|
||||||
se->cname = c->name ? sdsnew(ptrFromObj(c->name)) : sdsempty();
|
se->cname = c->name ? sdsnew(szFromObj(c->name)) : sdsempty();
|
||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ slowlogEntry *slowlogCreateEntry(client *c, robj **argv, int argc, long long dur
|
|||||||
*
|
*
|
||||||
* This function will take care to release all the retained object. */
|
* This function will take care to release all the retained object. */
|
||||||
void slowlogFreeEntry(void *septr) {
|
void slowlogFreeEntry(void *septr) {
|
||||||
slowlogEntry *se = septr;
|
slowlogEntry *se = (slowlogEntry*)septr;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < se->argc; j++)
|
for (j = 0; j < se->argc; j++)
|
||||||
@ -140,7 +140,7 @@ void slowlogReset(void) {
|
|||||||
/* The SLOWLOG command. Implements all the subcommands needed to handle the
|
/* The SLOWLOG command. Implements all the subcommands needed to handle the
|
||||||
* Redis slow log. */
|
* Redis slow log. */
|
||||||
void slowlogCommand(client *c) {
|
void slowlogCommand(client *c) {
|
||||||
if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"help")) {
|
if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"GET [count] -- Return top entries from the slowlog (default: 10)."
|
"GET [count] -- Return top entries from the slowlog (default: 10)."
|
||||||
" Entries are made of:",
|
" Entries are made of:",
|
||||||
@ -150,13 +150,13 @@ void slowlogCommand(client *c) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c, help);
|
addReplyHelp(c, help);
|
||||||
} else if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"reset")) {
|
} else if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"reset")) {
|
||||||
slowlogReset();
|
slowlogReset();
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
} else if (c->argc == 2 && !strcasecmp(ptrFromObj(c->argv[1]),"len")) {
|
} else if (c->argc == 2 && !strcasecmp(szFromObj(c->argv[1]),"len")) {
|
||||||
addReplyLongLong(c,listLength(server.slowlog));
|
addReplyLongLong(c,listLength(server.slowlog));
|
||||||
} else if ((c->argc == 2 || c->argc == 3) &&
|
} else if ((c->argc == 2 || c->argc == 3) &&
|
||||||
!strcasecmp(ptrFromObj(c->argv[1]),"get"))
|
!strcasecmp(szFromObj(c->argv[1]),"get"))
|
||||||
{
|
{
|
||||||
long count = 10, sent = 0;
|
long count = 10, sent = 0;
|
||||||
listIter li;
|
listIter li;
|
||||||
@ -173,7 +173,7 @@ NULL
|
|||||||
while(count-- && (ln = listNext(&li))) {
|
while(count-- && (ln = listNext(&li))) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
se = ln->value;
|
se = (slowlogEntry*)ln->value;
|
||||||
addReplyArrayLen(c,6);
|
addReplyArrayLen(c,6);
|
||||||
addReplyLongLong(c,se->id);
|
addReplyLongLong(c,se->id);
|
||||||
addReplyLongLong(c,se->time);
|
addReplyLongLong(c,se->time);
|
@ -55,7 +55,7 @@ static int label_margin_top = 1;
|
|||||||
|
|
||||||
/* Create a new sequence. */
|
/* Create a new sequence. */
|
||||||
struct sequence *createSparklineSequence(void) {
|
struct sequence *createSparklineSequence(void) {
|
||||||
struct sequence *seq = zmalloc(sizeof(*seq), MALLOC_LOCAL);
|
struct sequence *seq = (sequence*)zmalloc(sizeof(*seq), MALLOC_LOCAL);
|
||||||
seq->length = 0;
|
seq->length = 0;
|
||||||
seq->samples = NULL;
|
seq->samples = NULL;
|
||||||
return seq;
|
return seq;
|
||||||
@ -70,7 +70,7 @@ void sparklineSequenceAddSample(struct sequence *seq, double value, char *label)
|
|||||||
if (value < seq->min) seq->min = value;
|
if (value < seq->min) seq->min = value;
|
||||||
else if (value > seq->max) seq->max = value;
|
else if (value > seq->max) seq->max = value;
|
||||||
}
|
}
|
||||||
seq->samples = zrealloc(seq->samples,sizeof(struct sample)*(seq->length+1), MALLOC_SHARED);
|
seq->samples = (sample*)zrealloc(seq->samples,sizeof(struct sample)*(seq->length+1), MALLOC_SHARED);
|
||||||
seq->samples[seq->length].value = value;
|
seq->samples[seq->length].value = value;
|
||||||
seq->samples[seq->length].label = label;
|
seq->samples[seq->length].label = label;
|
||||||
seq->length++;
|
seq->length++;
|
||||||
@ -99,7 +99,7 @@ sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset,
|
|||||||
double relmax = seq->max - seq->min;
|
double relmax = seq->max - seq->min;
|
||||||
int steps = charset_len*rows;
|
int steps = charset_len*rows;
|
||||||
int row = 0;
|
int row = 0;
|
||||||
char *chars = zmalloc(len, MALLOC_LOCAL);
|
char *chars = (char*)zmalloc(len, MALLOC_LOCAL);
|
||||||
int loop = 1;
|
int loop = 1;
|
||||||
int opt_fill = flags & SPARKLINE_FILL;
|
int opt_fill = flags & SPARKLINE_FILL;
|
||||||
int opt_log = flags & SPARKLINE_LOG_SCALE;
|
int opt_log = flags & SPARKLINE_LOG_SCALE;
|
@ -47,10 +47,18 @@ struct sequence {
|
|||||||
#define SPARKLINE_FILL 1 /* Fill the area under the curve. */
|
#define SPARKLINE_FILL 1 /* Fill the area under the curve. */
|
||||||
#define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */
|
#define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
struct sequence *createSparklineSequence(void);
|
struct sequence *createSparklineSequence(void);
|
||||||
void sparklineSequenceAddSample(struct sequence *seq, double value, char *label);
|
void sparklineSequenceAddSample(struct sequence *seq, double value, char *label);
|
||||||
void freeSparklineSequence(struct sequence *seq);
|
void freeSparklineSequence(struct sequence *seq);
|
||||||
sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags);
|
sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags);
|
||||||
sds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags);
|
sds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __SPARKLINE_H */
|
#endif /* __SPARKLINE_H */
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
#ifndef _ZIPMAP_H
|
#ifndef _ZIPMAP_H
|
||||||
#define _ZIPMAP_H
|
#define _ZIPMAP_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned char *zipmapNew(void);
|
unsigned char *zipmapNew(void);
|
||||||
unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update);
|
unsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update);
|
||||||
unsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted);
|
unsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted);
|
||||||
@ -50,4 +54,8 @@ void zipmapRepr(unsigned char *p);
|
|||||||
int zipmapTest(int argc, char *argv[]);
|
int zipmapTest(int argc, char *argv[]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -358,7 +358,7 @@ int zmalloc_get_allocator_info(size_t *allocated,
|
|||||||
* Example: zmalloc_get_smap_bytes_by_field("Rss:",-1);
|
* Example: zmalloc_get_smap_bytes_by_field("Rss:",-1);
|
||||||
*/
|
*/
|
||||||
#if defined(HAVE_PROC_SMAPS)
|
#if defined(HAVE_PROC_SMAPS)
|
||||||
size_t zmalloc_get_smap_bytes_by_field(char *field, long pid) {
|
size_t zmalloc_get_smap_bytes_by_field(const char *field, long pid) {
|
||||||
char line[1024];
|
char line[1024];
|
||||||
size_t bytes = 0;
|
size_t bytes = 0;
|
||||||
int flen = strlen(field);
|
int flen = strlen(field);
|
||||||
@ -386,7 +386,7 @@ size_t zmalloc_get_smap_bytes_by_field(char *field, long pid) {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
size_t zmalloc_get_smap_bytes_by_field(char *field, long pid) {
|
size_t zmalloc_get_smap_bytes_by_field(const char *field, long pid) {
|
||||||
((void) field);
|
((void) field);
|
||||||
((void) pid);
|
((void) pid);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -96,7 +96,7 @@ void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
|
|||||||
size_t zmalloc_get_rss(void);
|
size_t zmalloc_get_rss(void);
|
||||||
int zmalloc_get_allocator_info(size_t *allocated, size_t *active, size_t *resident);
|
int zmalloc_get_allocator_info(size_t *allocated, size_t *active, size_t *resident);
|
||||||
size_t zmalloc_get_private_dirty(long pid);
|
size_t zmalloc_get_private_dirty(long pid);
|
||||||
size_t zmalloc_get_smap_bytes_by_field(char *field, long pid);
|
size_t zmalloc_get_smap_bytes_by_field(const char *field, long pid);
|
||||||
size_t zmalloc_get_memory_size(void);
|
size_t zmalloc_get_memory_size(void);
|
||||||
void zlibc_free(void *ptr);
|
void zlibc_free(void *ptr);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user