mirror of
https://github.com/fluencelabs/redis
synced 2025-06-02 20:11:19 +00:00
Merge remote-tracking branch 'origin/2.2' into 2.2
This commit is contained in:
commit
c1b270127c
@ -12,6 +12,22 @@ for 2.0.
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
What's new in Redis 2.2.12
|
||||||
|
==========================
|
||||||
|
|
||||||
|
* The Slowlog feature was backported to Redis 2.2.
|
||||||
|
* A number of fixes related blocking operations on lists when mixed with
|
||||||
|
AOF and Replication.
|
||||||
|
* Fixed bad interactions between EXPIRE, EXPIREAT, and in general volatile
|
||||||
|
keys when AOF is enabled. More details in the Redis Google Group here:
|
||||||
|
http://groups.google.com/group/redis-db/browse_frm/thread/5a931fefb88b16d5?tvc=1
|
||||||
|
* no more allocation stats info in INFO.
|
||||||
|
* colorized make for 2.2 as well.
|
||||||
|
* Fixed a problem with AOF when it is stopped via CONFIG SET appendonly no.
|
||||||
|
* Warn the user enabling VM that VM is deprecated and discouraged.
|
||||||
|
* prepareForShutdown() fixed for correctness.
|
||||||
|
* Close the listening sockets on exit for faster restarts.
|
||||||
|
|
||||||
What's new in Redis 2.2.11
|
What's new in Redis 2.2.11
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
@ -314,10 +314,13 @@ slowlog-log-slower-than 10000
|
|||||||
|
|
||||||
# There is no limit to this length. Just be aware that it will consume memory.
|
# There is no limit to this length. Just be aware that it will consume memory.
|
||||||
# You can reclaim memory used by the slow log with SLOWLOG RESET.
|
# You can reclaim memory used by the slow log with SLOWLOG RESET.
|
||||||
slowlog-log-len 1024
|
slowlog-max-len 1024
|
||||||
|
|
||||||
################################ VIRTUAL MEMORY ###############################
|
################################ VIRTUAL MEMORY ###############################
|
||||||
|
|
||||||
|
### WARNING! Virtual Memory is deprecated in Redis 2.4
|
||||||
|
### The use of Virtual Memory is strongly discouraged.
|
||||||
|
|
||||||
# Virtual Memory allows Redis to work with datasets bigger than the actual
|
# Virtual Memory allows Redis to work with datasets bigger than the actual
|
||||||
# amount of RAM needed to hold the whole dataset in memory.
|
# amount of RAM needed to hold the whole dataset in memory.
|
||||||
# In order to do so very used keys are taken in memory while the other keys
|
# In order to do so very used keys are taken in memory while the other keys
|
||||||
|
34
src/Makefile
34
src/Makefile
@ -5,6 +5,19 @@
|
|||||||
release_hdr := $(shell sh -c './mkreleasehdr.sh')
|
release_hdr := $(shell sh -c './mkreleasehdr.sh')
|
||||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||||
OPTIMIZATION?=-O2
|
OPTIMIZATION?=-O2
|
||||||
|
|
||||||
|
CCCOLOR="\033[34m"
|
||||||
|
LINKCOLOR="\033[34;1m"
|
||||||
|
SRCCOLOR="\033[33m"
|
||||||
|
BINCOLOR="\033[37;1m"
|
||||||
|
MAKECOLOR="\033[32;1m"
|
||||||
|
ENDCOLOR="\033[0m"
|
||||||
|
|
||||||
|
ifndef V
|
||||||
|
QUIET_CC = @printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR);
|
||||||
|
QUIET_LINK = @printf ' %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR);
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(uname_S),SunOS)
|
ifeq ($(uname_S),SunOS)
|
||||||
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6
|
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6
|
||||||
CCLINK?= -ldl -lnsl -lsocket -lm -lpthread
|
CCLINK?= -ldl -lnsl -lsocket -lm -lpthread
|
||||||
@ -111,33 +124,36 @@ zipmap.o: zipmap.c zmalloc.h
|
|||||||
zmalloc.o: zmalloc.c config.h zmalloc.h
|
zmalloc.o: zmalloc.c config.h zmalloc.h
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)hiredis$(ENDCOLOR)
|
||||||
cd ../deps/hiredis && $(MAKE) static ARCH="$(ARCH)"
|
cd ../deps/hiredis && $(MAKE) static ARCH="$(ARCH)"
|
||||||
|
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)linenoise$(ENDCOLOR)
|
||||||
cd ../deps/linenoise && $(MAKE) ARCH="$(ARCH)"
|
cd ../deps/linenoise && $(MAKE) ARCH="$(ARCH)"
|
||||||
|
|
||||||
redis-server: $(OBJ)
|
redis-server: $(OBJ)
|
||||||
$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ)
|
$(QUIET_LINK)$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ)
|
||||||
|
|
||||||
redis-benchmark: dependencies $(BENCHOBJ)
|
redis-benchmark: dependencies $(BENCHOBJ)
|
||||||
cd ../deps/hiredis && $(MAKE) static
|
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)hiredis$(ENDCOLOR)
|
||||||
$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a
|
cd ../deps/hiredis && $(MAKE) static ARCH="$(ARCH)"
|
||||||
|
$(QUIET_LINK)$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a
|
||||||
|
|
||||||
redis-benchmark.o:
|
redis-benchmark.o:
|
||||||
$(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $<
|
$(QUIET_CC)$(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $<
|
||||||
|
|
||||||
redis-cli: dependencies $(CLIOBJ)
|
redis-cli: dependencies $(CLIOBJ)
|
||||||
$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o
|
$(QUIET_LINK)$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o
|
||||||
|
|
||||||
redis-cli.o:
|
redis-cli.o:
|
||||||
$(CC) -c $(CFLAGS) -I../deps/hiredis -I../deps/linenoise $(DEBUG) $(COMPILE_TIME) $<
|
$(QUIET_CC)$(CC) -c $(CFLAGS) -I../deps/hiredis -I../deps/linenoise $(DEBUG) $(COMPILE_TIME) $<
|
||||||
|
|
||||||
redis-check-dump: $(CHECKDUMPOBJ)
|
redis-check-dump: $(CHECKDUMPOBJ)
|
||||||
$(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ)
|
$(QUIET_LINK)$(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ)
|
||||||
|
|
||||||
redis-check-aof: $(CHECKAOFOBJ)
|
redis-check-aof: $(CHECKAOFOBJ)
|
||||||
$(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ)
|
$(QUIET_LINK)$(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ)
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $<
|
$(QUIET_CC)$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PRGNAME) $(BENCHPRGNAME) $(CLIPRGNAME) $(CHECKDUMPPRGNAME) $(CHECKAOFPRGNAME) *.o *.gcda *.gcno *.gcov
|
rm -rf $(PRGNAME) $(BENCHPRGNAME) $(CLIPRGNAME) $(CHECKDUMPPRGNAME) $(CHECKAOFPRGNAME) *.o *.gcda *.gcno *.gcov
|
||||||
|
@ -19,15 +19,15 @@ void stopAppendOnly(void) {
|
|||||||
server.appendseldb = -1;
|
server.appendseldb = -1;
|
||||||
server.appendonly = 0;
|
server.appendonly = 0;
|
||||||
/* rewrite operation in progress? kill it, wait child exit */
|
/* rewrite operation in progress? kill it, wait child exit */
|
||||||
if (server.bgsavechildpid != -1) {
|
if (server.bgrewritechildpid != -1) {
|
||||||
int statloc;
|
int statloc;
|
||||||
|
|
||||||
if (kill(server.bgsavechildpid,SIGKILL) != -1)
|
if (kill(server.bgrewritechildpid,SIGKILL) != -1)
|
||||||
wait3(&statloc,0,NULL);
|
wait3(&statloc,0,NULL);
|
||||||
/* reset the buffer accumulating changes while the child saves */
|
/* reset the buffer accumulating changes while the child saves */
|
||||||
sdsfree(server.bgrewritebuf);
|
sdsfree(server.bgrewritebuf);
|
||||||
server.bgrewritebuf = sdsempty();
|
server.bgrewritebuf = sdsempty();
|
||||||
server.bgsavechildpid = -1;
|
server.bgrewritechildpid = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
src/config.c
15
src/config.c
@ -30,6 +30,7 @@ void loadServerConfig(char *filename) {
|
|||||||
char buf[REDIS_CONFIGLINE_MAX+1], *err = NULL;
|
char buf[REDIS_CONFIGLINE_MAX+1], *err = NULL;
|
||||||
int linenum = 0;
|
int linenum = 0;
|
||||||
sds line = NULL;
|
sds line = NULL;
|
||||||
|
int really_use_vm = 0;
|
||||||
|
|
||||||
if (filename[0] == '-' && filename[1] == '\0')
|
if (filename[0] == '-' && filename[1] == '\0')
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
@ -243,6 +244,10 @@ void loadServerConfig(char *filename) {
|
|||||||
if ((server.vm_enabled = yesnotoi(argv[1])) == -1) {
|
if ((server.vm_enabled = 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],"really-use-vm") && argc == 2) {
|
||||||
|
if ((really_use_vm = yesnotoi(argv[1])) == -1) {
|
||||||
|
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
||||||
|
}
|
||||||
} else if (!strcasecmp(argv[0],"vm-swap-file") && argc == 2) {
|
} else if (!strcasecmp(argv[0],"vm-swap-file") && argc == 2) {
|
||||||
zfree(server.vm_swap_file);
|
zfree(server.vm_swap_file);
|
||||||
server.vm_swap_file = zstrdup(argv[1]);
|
server.vm_swap_file = zstrdup(argv[1]);
|
||||||
@ -303,6 +308,7 @@ void loadServerConfig(char *filename) {
|
|||||||
sdsfree(line);
|
sdsfree(line);
|
||||||
}
|
}
|
||||||
if (fp != stdin) fclose(fp);
|
if (fp != stdin) fclose(fp);
|
||||||
|
if (server.vm_enabled && !really_use_vm) goto vm_warning;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
loaderr:
|
loaderr:
|
||||||
@ -311,6 +317,15 @@ loaderr:
|
|||||||
fprintf(stderr, ">>> '%s'\n", line);
|
fprintf(stderr, ">>> '%s'\n", line);
|
||||||
fprintf(stderr, "%s\n", err);
|
fprintf(stderr, "%s\n", err);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
|
vm_warning:
|
||||||
|
fprintf(stderr, "\nARE YOU SURE YOU WANT TO USE VM?\n\n");
|
||||||
|
fprintf(stderr, "Redis Virtual Memory is going to be deprecated soon,\n");
|
||||||
|
fprintf(stderr, "we think you should NOT use it, but use Redis only if\n");
|
||||||
|
fprintf(stderr, "your data is suitable for an in-memory database.\n");
|
||||||
|
fprintf(stderr, "If you *really* want VM add this in the config file:\n");
|
||||||
|
fprintf(stderr, "\n really-use-vm yes\n\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
|
23
src/db.c
23
src/db.c
@ -455,6 +455,9 @@ int expireIfNeeded(redisDb *db, robj *key) {
|
|||||||
|
|
||||||
if (when < 0) return 0; /* No expire for this key */
|
if (when < 0) return 0; /* No expire for this key */
|
||||||
|
|
||||||
|
/* Don't expire anything while loading. It will be done later. */
|
||||||
|
if (server.loading) return 0;
|
||||||
|
|
||||||
/* If we are running in the context of a slave, return ASAP:
|
/* If we are running in the context of a slave, return ASAP:
|
||||||
* the slave key expiration is controlled by the master that will
|
* the slave key expiration is controlled by the master that will
|
||||||
* send us synthesized DEL operations for expired keys.
|
* send us synthesized DEL operations for expired keys.
|
||||||
@ -492,10 +495,24 @@ void expireGenericCommand(redisClient *c, robj *key, robj *param, long offset) {
|
|||||||
addReply(c,shared.czero);
|
addReply(c,shared.czero);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (seconds <= 0) {
|
/* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past
|
||||||
if (dbDelete(c->db,key)) server.dirty++;
|
* should never be executed as a DEL when load the AOF or in the context
|
||||||
addReply(c, shared.cone);
|
* of a slave instance.
|
||||||
|
*
|
||||||
|
* Instead we take the other branch of the IF statement setting an expire
|
||||||
|
* (possibly in the past) and wait for an explicit DEL from the master. */
|
||||||
|
if (seconds <= 0 && !server.loading && !server.masterhost) {
|
||||||
|
robj *aux;
|
||||||
|
|
||||||
|
redisAssert(dbDelete(c->db,key));
|
||||||
|
server.dirty++;
|
||||||
|
|
||||||
|
/* Replicate/AOF this as an explicit DEL. */
|
||||||
|
aux = createStringObject("DEL",3);
|
||||||
|
rewriteClientCommandVector(c,2,aux,key);
|
||||||
|
decrRefCount(aux);
|
||||||
touchWatchedKey(c->db,key);
|
touchWatchedKey(c->db,key);
|
||||||
|
addReply(c, shared.cone);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
time_t when = time(NULL)+seconds;
|
time_t when = time(NULL)+seconds;
|
||||||
|
11
src/multi.c
11
src/multi.c
@ -24,14 +24,14 @@ void freeClientMultiState(redisClient *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new command into the MULTI commands queue */
|
/* Add a new command into the MULTI commands queue */
|
||||||
void queueMultiCommand(redisClient *c, struct redisCommand *cmd) {
|
void queueMultiCommand(redisClient *c) {
|
||||||
multiCmd *mc;
|
multiCmd *mc;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
c->mstate.commands = zrealloc(c->mstate.commands,
|
c->mstate.commands = zrealloc(c->mstate.commands,
|
||||||
sizeof(multiCmd)*(c->mstate.count+1));
|
sizeof(multiCmd)*(c->mstate.count+1));
|
||||||
mc = c->mstate.commands+c->mstate.count;
|
mc = c->mstate.commands+c->mstate.count;
|
||||||
mc->cmd = cmd;
|
mc->cmd = c->cmd;
|
||||||
mc->argc = c->argc;
|
mc->argc = c->argc;
|
||||||
mc->argv = zmalloc(sizeof(robj*)*c->argc);
|
mc->argv = zmalloc(sizeof(robj*)*c->argc);
|
||||||
memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);
|
memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);
|
||||||
@ -78,6 +78,7 @@ void execCommand(redisClient *c) {
|
|||||||
int j;
|
int j;
|
||||||
robj **orig_argv;
|
robj **orig_argv;
|
||||||
int orig_argc;
|
int orig_argc;
|
||||||
|
struct redisCommand *orig_cmd;
|
||||||
|
|
||||||
if (!(c->flags & REDIS_MULTI)) {
|
if (!(c->flags & REDIS_MULTI)) {
|
||||||
addReplyError(c,"EXEC without MULTI");
|
addReplyError(c,"EXEC without MULTI");
|
||||||
@ -105,18 +106,22 @@ void execCommand(redisClient *c) {
|
|||||||
unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */
|
unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */
|
||||||
orig_argv = c->argv;
|
orig_argv = c->argv;
|
||||||
orig_argc = c->argc;
|
orig_argc = c->argc;
|
||||||
|
orig_cmd = c->cmd;
|
||||||
addReplyMultiBulkLen(c,c->mstate.count);
|
addReplyMultiBulkLen(c,c->mstate.count);
|
||||||
for (j = 0; j < c->mstate.count; j++) {
|
for (j = 0; j < c->mstate.count; j++) {
|
||||||
c->argc = c->mstate.commands[j].argc;
|
c->argc = c->mstate.commands[j].argc;
|
||||||
c->argv = c->mstate.commands[j].argv;
|
c->argv = c->mstate.commands[j].argv;
|
||||||
call(c,c->mstate.commands[j].cmd);
|
c->cmd = c->mstate.commands[j].cmd;
|
||||||
|
call(c);
|
||||||
|
|
||||||
/* Commands may alter argc/argv, restore mstate. */
|
/* Commands may alter argc/argv, restore mstate. */
|
||||||
c->mstate.commands[j].argc = c->argc;
|
c->mstate.commands[j].argc = c->argc;
|
||||||
c->mstate.commands[j].argv = c->argv;
|
c->mstate.commands[j].argv = c->argv;
|
||||||
|
c->mstate.commands[j].cmd = c->cmd;
|
||||||
}
|
}
|
||||||
c->argv = orig_argv;
|
c->argv = orig_argv;
|
||||||
c->argc = orig_argc;
|
c->argc = orig_argc;
|
||||||
|
c->cmd = orig_cmd;
|
||||||
freeClientMultiState(c);
|
freeClientMultiState(c);
|
||||||
initClientMultiState(c);
|
initClientMultiState(c);
|
||||||
c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS);
|
c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS);
|
||||||
|
@ -31,6 +31,7 @@ redisClient *createClient(int fd) {
|
|||||||
c->reqtype = 0;
|
c->reqtype = 0;
|
||||||
c->argc = 0;
|
c->argc = 0;
|
||||||
c->argv = NULL;
|
c->argv = NULL;
|
||||||
|
c->cmd = NULL;
|
||||||
c->multibulklen = 0;
|
c->multibulklen = 0;
|
||||||
c->bulklen = -1;
|
c->bulklen = -1;
|
||||||
c->sentlen = 0;
|
c->sentlen = 0;
|
||||||
@ -444,6 +445,7 @@ static void freeClientArgv(redisClient *c) {
|
|||||||
for (j = 0; j < c->argc; j++)
|
for (j = 0; j < c->argc; j++)
|
||||||
decrRefCount(c->argv[j]);
|
decrRefCount(c->argv[j]);
|
||||||
c->argc = 0;
|
c->argc = 0;
|
||||||
|
c->cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeClient(redisClient *c) {
|
void freeClient(redisClient *c) {
|
||||||
@ -896,4 +898,3 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
|
|||||||
c->argc = argc;
|
c->argc = argc;
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
101
src/redis.c
101
src/redis.c
@ -677,7 +677,7 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
|||||||
readQueryFromClient, c);
|
readQueryFromClient, c);
|
||||||
cmd = lookupCommand(c->argv[0]->ptr);
|
cmd = lookupCommand(c->argv[0]->ptr);
|
||||||
redisAssert(cmd != NULL);
|
redisAssert(cmd != NULL);
|
||||||
call(c,cmd);
|
call(c);
|
||||||
resetClient(c);
|
resetClient(c);
|
||||||
/* There may be more data to process in the input buffer. */
|
/* There may be more data to process in the input buffer. */
|
||||||
if (c->querybuf && sdslen(c->querybuf) > 0)
|
if (c->querybuf && sdslen(c->querybuf) > 0)
|
||||||
@ -958,18 +958,18 @@ struct redisCommand *lookupCommandByCString(char *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Call() is the core of Redis execution of a command */
|
/* Call() is the core of Redis execution of a command */
|
||||||
void call(redisClient *c, struct redisCommand *cmd) {
|
void call(redisClient *c) {
|
||||||
long long dirty, start = ustime(), duration;
|
long long dirty, start = ustime(), duration;
|
||||||
|
|
||||||
dirty = server.dirty;
|
dirty = server.dirty;
|
||||||
cmd->proc(c);
|
c->cmd->proc(c);
|
||||||
dirty = server.dirty-dirty;
|
dirty = server.dirty-dirty;
|
||||||
duration = ustime()-start;
|
duration = ustime()-start;
|
||||||
slowlogPushEntryIfNeeded(c->argv,c->argc,duration);
|
slowlogPushEntryIfNeeded(c->argv,c->argc,duration);
|
||||||
|
|
||||||
if (server.appendonly && dirty)
|
if (server.appendonly && dirty)
|
||||||
feedAppendOnlyFile(cmd,c->db->id,c->argv,c->argc);
|
feedAppendOnlyFile(c->cmd,c->db->id,c->argv,c->argc);
|
||||||
if ((dirty || cmd->flags & REDIS_CMD_FORCE_REPLICATION) &&
|
if ((dirty || c->cmd->flags & REDIS_CMD_FORCE_REPLICATION) &&
|
||||||
listLength(server.slaves))
|
listLength(server.slaves))
|
||||||
replicationFeedSlaves(server.slaves,c->db->id,c->argv,c->argc);
|
replicationFeedSlaves(server.slaves,c->db->id,c->argv,c->argc);
|
||||||
if (listLength(server.monitors))
|
if (listLength(server.monitors))
|
||||||
@ -986,8 +986,6 @@ void call(redisClient *c, struct redisCommand *cmd) {
|
|||||||
* and other operations can be performed by the caller. Otherwise
|
* and other operations can be performed by the caller. Otherwise
|
||||||
* if 0 is returned the client was destroied (i.e. after QUIT). */
|
* if 0 is returned the client was destroied (i.e. after QUIT). */
|
||||||
int processCommand(redisClient *c) {
|
int processCommand(redisClient *c) {
|
||||||
struct redisCommand *cmd;
|
|
||||||
|
|
||||||
/* The QUIT command is handled separately. Normal command procs will
|
/* The QUIT command is handled separately. Normal command procs will
|
||||||
* go through checking for replication and QUIT will cause trouble
|
* go through checking for replication and QUIT will cause trouble
|
||||||
* when FORCE_REPLICATION is enabled and would be implemented in
|
* when FORCE_REPLICATION is enabled and would be implemented in
|
||||||
@ -999,21 +997,22 @@ int processCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now lookup the command and check ASAP about trivial error conditions
|
/* Now lookup the command and check ASAP about trivial error conditions
|
||||||
* such wrong arity, bad command name and so forth. */
|
* such as wrong arity, bad command name and so forth. */
|
||||||
cmd = lookupCommand(c->argv[0]->ptr);
|
c->cmd = lookupCommand(c->argv[0]->ptr);
|
||||||
if (!cmd) {
|
if (!c->cmd) {
|
||||||
addReplyErrorFormat(c,"unknown command '%s'",
|
addReplyErrorFormat(c,"unknown command '%s'",
|
||||||
(char*)c->argv[0]->ptr);
|
(char*)c->argv[0]->ptr);
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
} else if ((cmd->arity > 0 && cmd->arity != c->argc) ||
|
} else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) ||
|
||||||
(c->argc < -cmd->arity)) {
|
(c->argc < -c->cmd->arity)) {
|
||||||
addReplyErrorFormat(c,"wrong number of arguments for '%s' command",
|
addReplyErrorFormat(c,"wrong number of arguments for '%s' command",
|
||||||
cmd->name);
|
c->cmd->name);
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the user is authenticated */
|
/* Check if the user is authenticated */
|
||||||
if (server.requirepass && !c->authenticated && cmd->proc != authCommand) {
|
if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)
|
||||||
|
{
|
||||||
addReplyError(c,"operation not permitted");
|
addReplyError(c,"operation not permitted");
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
@ -1024,7 +1023,7 @@ int processCommand(redisClient *c) {
|
|||||||
* keys in the dataset). If there are not the only thing we can do
|
* keys in the dataset). If there are not the only thing we can do
|
||||||
* is returning an error. */
|
* is returning an error. */
|
||||||
if (server.maxmemory) freeMemoryIfNeeded();
|
if (server.maxmemory) freeMemoryIfNeeded();
|
||||||
if (server.maxmemory && (cmd->flags & REDIS_CMD_DENYOOM) &&
|
if (server.maxmemory && (c->cmd->flags & REDIS_CMD_DENYOOM) &&
|
||||||
zmalloc_used_memory() > server.maxmemory)
|
zmalloc_used_memory() > server.maxmemory)
|
||||||
{
|
{
|
||||||
addReplyError(c,"command not allowed when used memory > 'maxmemory'");
|
addReplyError(c,"command not allowed when used memory > 'maxmemory'");
|
||||||
@ -1034,8 +1033,10 @@ int processCommand(redisClient *c) {
|
|||||||
/* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */
|
/* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */
|
||||||
if ((dictSize(c->pubsub_channels) > 0 || listLength(c->pubsub_patterns) > 0)
|
if ((dictSize(c->pubsub_channels) > 0 || listLength(c->pubsub_patterns) > 0)
|
||||||
&&
|
&&
|
||||||
cmd->proc != subscribeCommand && cmd->proc != unsubscribeCommand &&
|
c->cmd->proc != subscribeCommand &&
|
||||||
cmd->proc != psubscribeCommand && cmd->proc != punsubscribeCommand) {
|
c->cmd->proc != unsubscribeCommand &&
|
||||||
|
c->cmd->proc != psubscribeCommand &&
|
||||||
|
c->cmd->proc != punsubscribeCommand) {
|
||||||
addReplyError(c,"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context");
|
addReplyError(c,"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context");
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
@ -1044,7 +1045,7 @@ int processCommand(redisClient *c) {
|
|||||||
* we are a slave with a broken link with master. */
|
* we are a slave with a broken link with master. */
|
||||||
if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED &&
|
if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED &&
|
||||||
server.repl_serve_stale_data == 0 &&
|
server.repl_serve_stale_data == 0 &&
|
||||||
cmd->proc != infoCommand && cmd->proc != slaveofCommand)
|
c->cmd->proc != infoCommand && c->cmd->proc != slaveofCommand)
|
||||||
{
|
{
|
||||||
addReplyError(c,
|
addReplyError(c,
|
||||||
"link with MASTER is down and slave-serve-stale-data is set to no");
|
"link with MASTER is down and slave-serve-stale-data is set to no");
|
||||||
@ -1052,22 +1053,22 @@ int processCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Loading DB? Return an error if the command is not INFO */
|
/* Loading DB? Return an error if the command is not INFO */
|
||||||
if (server.loading && cmd->proc != infoCommand) {
|
if (server.loading && c->cmd->proc != infoCommand) {
|
||||||
addReply(c, shared.loadingerr);
|
addReply(c, shared.loadingerr);
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exec the command */
|
/* Exec the command */
|
||||||
if (c->flags & REDIS_MULTI &&
|
if (c->flags & REDIS_MULTI &&
|
||||||
cmd->proc != execCommand && cmd->proc != discardCommand &&
|
c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&
|
||||||
cmd->proc != multiCommand && cmd->proc != watchCommand)
|
c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)
|
||||||
{
|
{
|
||||||
queueMultiCommand(c,cmd);
|
queueMultiCommand(c);
|
||||||
addReply(c,shared.queued);
|
addReply(c,shared.queued);
|
||||||
} else {
|
} else {
|
||||||
if (server.vm_enabled && server.vm_max_threads > 0 &&
|
if (server.vm_enabled && server.vm_max_threads > 0 &&
|
||||||
blockClientOnSwappedKeys(c,cmd)) return REDIS_ERR;
|
blockClientOnSwappedKeys(c)) return REDIS_ERR;
|
||||||
call(c,cmd);
|
call(c);
|
||||||
}
|
}
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
@ -1075,20 +1076,29 @@ int processCommand(redisClient *c) {
|
|||||||
/*================================== Shutdown =============================== */
|
/*================================== Shutdown =============================== */
|
||||||
|
|
||||||
int prepareForShutdown() {
|
int prepareForShutdown() {
|
||||||
redisLog(REDIS_WARNING,"User requested shutdown, saving DB...");
|
redisLog(REDIS_WARNING,"User requested shutdown...");
|
||||||
/* Kill the saving child if there is a background saving in progress.
|
/* Kill the saving child if there is a background saving in progress.
|
||||||
We want to avoid race conditions, for instance our saving child may
|
We want to avoid race conditions, for instance our saving child may
|
||||||
overwrite the synchronous saving did by SHUTDOWN. */
|
overwrite the synchronous saving did by SHUTDOWN. */
|
||||||
if (server.bgsavechildpid != -1) {
|
if (server.bgsavechildpid != -1) {
|
||||||
redisLog(REDIS_WARNING,"There is a live saving child. Killing it!");
|
redisLog(REDIS_WARNING,"There is a child saving an .rdb. Killing it!");
|
||||||
kill(server.bgsavechildpid,SIGKILL);
|
kill(server.bgsavechildpid,SIGKILL);
|
||||||
rdbRemoveTempFile(server.bgsavechildpid);
|
rdbRemoveTempFile(server.bgsavechildpid);
|
||||||
}
|
}
|
||||||
if (server.appendonly) {
|
if (server.appendonly) {
|
||||||
|
/* Kill the AOF saving child as the AOF we already have may be longer
|
||||||
|
* but contains the full dataset anyway. */
|
||||||
|
if (server.bgrewritechildpid != -1) {
|
||||||
|
redisLog(REDIS_WARNING,
|
||||||
|
"There is a child rewriting the AOF. Killing it!");
|
||||||
|
kill(server.bgrewritechildpid,SIGKILL);
|
||||||
|
}
|
||||||
/* Append only file: fsync() the AOF and exit */
|
/* Append only file: fsync() the AOF and exit */
|
||||||
|
redisLog(REDIS_NOTICE,"Calling fsync() on the AOF file.");
|
||||||
aof_fsync(server.appendfd);
|
aof_fsync(server.appendfd);
|
||||||
if (server.vm_enabled) unlink(server.vm_swap_file);
|
}
|
||||||
} else if (server.saveparamslen > 0) {
|
if (server.saveparamslen > 0) {
|
||||||
|
redisLog(REDIS_NOTICE,"Saving the final RDB snapshot before exiting.");
|
||||||
/* Snapshotting. Perform a SYNC SAVE and exit */
|
/* Snapshotting. Perform a SYNC SAVE and exit */
|
||||||
if (rdbSave(server.dbfilename) != REDIS_OK) {
|
if (rdbSave(server.dbfilename) != REDIS_OK) {
|
||||||
/* Ooops.. error saving! The best we can do is to continue
|
/* Ooops.. error saving! The best we can do is to continue
|
||||||
@ -1096,14 +1106,23 @@ int prepareForShutdown() {
|
|||||||
* in the next cron() Redis will be notified that the background
|
* in the next cron() Redis will be notified that the background
|
||||||
* saving aborted, handling special stuff like slaves pending for
|
* saving aborted, handling special stuff like slaves pending for
|
||||||
* synchronization... */
|
* synchronization... */
|
||||||
redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit");
|
redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit.");
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
redisLog(REDIS_WARNING,"Not saving DB.");
|
|
||||||
}
|
}
|
||||||
if (server.daemonize) unlink(server.pidfile);
|
if (server.vm_enabled) {
|
||||||
redisLog(REDIS_WARNING,"Server exit now, bye bye...");
|
redisLog(REDIS_NOTICE,"Removing the swap file.");
|
||||||
|
unlink(server.vm_swap_file);
|
||||||
|
}
|
||||||
|
if (server.daemonize) {
|
||||||
|
redisLog(REDIS_NOTICE,"Removing the pid file.");
|
||||||
|
unlink(server.pidfile);
|
||||||
|
}
|
||||||
|
/* Close the listening sockets. Apparently this allows faster restarts. */
|
||||||
|
if (server.ipfd != -1) close(server.ipfd);
|
||||||
|
if (server.sofd != -1) close(server.sofd);
|
||||||
|
|
||||||
|
redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,8 +1195,8 @@ sds genRedisInfoString(void) {
|
|||||||
"lru_clock:%ld\r\n"
|
"lru_clock:%ld\r\n"
|
||||||
"used_cpu_sys:%.2f\r\n"
|
"used_cpu_sys:%.2f\r\n"
|
||||||
"used_cpu_user:%.2f\r\n"
|
"used_cpu_user:%.2f\r\n"
|
||||||
"used_cpu_sys_childrens:%.2f\r\n"
|
"used_cpu_sys_children:%.2f\r\n"
|
||||||
"used_cpu_user_childrens:%.2f\r\n"
|
"used_cpu_user_children:%.2f\r\n"
|
||||||
"connected_clients:%d\r\n"
|
"connected_clients:%d\r\n"
|
||||||
"connected_slaves:%d\r\n"
|
"connected_slaves:%d\r\n"
|
||||||
"client_longest_output_list:%lu\r\n"
|
"client_longest_output_list:%lu\r\n"
|
||||||
@ -1335,18 +1354,6 @@ sds genRedisInfoString(void) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
info = sdscat(info,"allocation_stats:");
|
|
||||||
for (j = 0; j <= ZMALLOC_MAX_ALLOC_STAT; j++) {
|
|
||||||
size_t count = zmalloc_allocations_for_size(j);
|
|
||||||
if (count) {
|
|
||||||
if (info[sdslen(info)-1] != ':') info = sdscatlen(info,",",1);
|
|
||||||
info = sdscatprintf(info,"%s%d=%zu",
|
|
||||||
(j == ZMALLOC_MAX_ALLOC_STAT) ? ">=" : "",
|
|
||||||
j,count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info = sdscat(info,"\r\n");
|
|
||||||
|
|
||||||
for (j = 0; j < server.dbnum; j++) {
|
for (j = 0; j < server.dbnum; j++) {
|
||||||
long long keys, vkeys;
|
long long keys, vkeys;
|
||||||
|
|
||||||
|
@ -314,6 +314,7 @@ typedef struct redisClient {
|
|||||||
sds querybuf;
|
sds querybuf;
|
||||||
int argc;
|
int argc;
|
||||||
robj **argv;
|
robj **argv;
|
||||||
|
struct redisCommand *cmd;
|
||||||
int reqtype;
|
int reqtype;
|
||||||
int multibulklen; /* number of multi bulk arguments left to read */
|
int multibulklen; /* number of multi bulk arguments left to read */
|
||||||
long bulklen; /* length of bulk argument in multi bulk request */
|
long bulklen; /* length of bulk argument in multi bulk request */
|
||||||
@ -700,7 +701,7 @@ void popGenericCommand(redisClient *c, int where);
|
|||||||
void unwatchAllKeys(redisClient *c);
|
void unwatchAllKeys(redisClient *c);
|
||||||
void initClientMultiState(redisClient *c);
|
void initClientMultiState(redisClient *c);
|
||||||
void freeClientMultiState(redisClient *c);
|
void freeClientMultiState(redisClient *c);
|
||||||
void queueMultiCommand(redisClient *c, struct redisCommand *cmd);
|
void queueMultiCommand(redisClient *c);
|
||||||
void touchWatchedKey(redisDb *db, robj *key);
|
void touchWatchedKey(redisDb *db, robj *key);
|
||||||
void touchWatchedKeysOnFlush(int dbid);
|
void touchWatchedKeysOnFlush(int dbid);
|
||||||
|
|
||||||
@ -788,7 +789,7 @@ int processCommand(redisClient *c);
|
|||||||
void setupSignalHandlers(void);
|
void setupSignalHandlers(void);
|
||||||
struct redisCommand *lookupCommand(sds name);
|
struct redisCommand *lookupCommand(sds name);
|
||||||
struct redisCommand *lookupCommandByCString(char *s);
|
struct redisCommand *lookupCommandByCString(char *s);
|
||||||
void call(redisClient *c, struct redisCommand *cmd);
|
void call(redisClient *c);
|
||||||
int prepareForShutdown();
|
int prepareForShutdown();
|
||||||
void redisLog(int level, const char *fmt, ...);
|
void redisLog(int level, const char *fmt, ...);
|
||||||
void usage();
|
void usage();
|
||||||
@ -819,7 +820,7 @@ void vmReopenSwapFile(void);
|
|||||||
int vmFreePage(off_t page);
|
int vmFreePage(off_t page);
|
||||||
void zunionInterBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
|
void zunionInterBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
|
||||||
void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
|
void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int argc, robj **argv);
|
||||||
int blockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd);
|
int blockClientOnSwappedKeys(redisClient *c);
|
||||||
int dontWaitForSwappedKey(redisClient *c, robj *key);
|
int dontWaitForSwappedKey(redisClient *c, robj *key);
|
||||||
void handleClientsBlockedOnSwappedKey(redisDb *db, robj *key);
|
void handleClientsBlockedOnSwappedKey(redisDb *db, robj *key);
|
||||||
vmpointer *vmSwapObjectBlocking(robj *val);
|
vmpointer *vmSwapObjectBlocking(robj *val);
|
||||||
|
@ -904,6 +904,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
|
|||||||
if (listTypeLength(o) != 0) {
|
if (listTypeLength(o) != 0) {
|
||||||
/* If the list contains elements fall back to the usual
|
/* If the list contains elements fall back to the usual
|
||||||
* non-blocking POP operation */
|
* non-blocking POP operation */
|
||||||
|
struct redisCommand *orig_cmd;
|
||||||
robj *argv[2], **orig_argv;
|
robj *argv[2], **orig_argv;
|
||||||
int orig_argc;
|
int orig_argc;
|
||||||
|
|
||||||
@ -911,6 +912,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
|
|||||||
* popGenericCommand() as the command takes a single key. */
|
* popGenericCommand() as the command takes a single key. */
|
||||||
orig_argv = c->argv;
|
orig_argv = c->argv;
|
||||||
orig_argc = c->argc;
|
orig_argc = c->argc;
|
||||||
|
orig_cmd = c->cmd;
|
||||||
argv[1] = c->argv[j];
|
argv[1] = c->argv[j];
|
||||||
c->argv = argv;
|
c->argv = argv;
|
||||||
c->argc = 2;
|
c->argc = 2;
|
||||||
@ -928,6 +930,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
|
|||||||
/* Fix the client structure with the original stuff */
|
/* Fix the client structure with the original stuff */
|
||||||
c->argv = orig_argv;
|
c->argv = orig_argv;
|
||||||
c->argc = orig_argc;
|
c->argc = orig_argc;
|
||||||
|
c->cmd = orig_cmd;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
#define REDIS_VERSION "2.2.11"
|
#define REDIS_VERSION "2.2.12"
|
||||||
|
8
src/vm.c
8
src/vm.c
@ -1064,11 +1064,11 @@ void execBlockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd, int
|
|||||||
*
|
*
|
||||||
* Return 1 if the client is marked as blocked, 0 if the client can
|
* Return 1 if the client is marked as blocked, 0 if the client can
|
||||||
* continue as the keys it is going to access appear to be in memory. */
|
* continue as the keys it is going to access appear to be in memory. */
|
||||||
int blockClientOnSwappedKeys(redisClient *c, struct redisCommand *cmd) {
|
int blockClientOnSwappedKeys(redisClient *c) {
|
||||||
if (cmd->vm_preload_proc != NULL) {
|
if (c->cmd->vm_preload_proc != NULL) {
|
||||||
cmd->vm_preload_proc(c,cmd,c->argc,c->argv);
|
c->cmd->vm_preload_proc(c,c->cmd,c->argc,c->argv);
|
||||||
} else {
|
} else {
|
||||||
waitForMultipleSwappedKeys(c,cmd,c->argc,c->argv);
|
waitForMultipleSwappedKeys(c,c->cmd,c->argc,c->argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the client was blocked for at least one key, mark it as blocked. */
|
/* If the client was blocked for at least one key, mark it as blocked. */
|
||||||
|
@ -55,16 +55,13 @@
|
|||||||
|
|
||||||
#define update_zmalloc_stat_alloc(__n,__size) do { \
|
#define update_zmalloc_stat_alloc(__n,__size) do { \
|
||||||
size_t _n = (__n); \
|
size_t _n = (__n); \
|
||||||
size_t _stat_slot = (__size < ZMALLOC_MAX_ALLOC_STAT) ? __size : ZMALLOC_MAX_ALLOC_STAT; \
|
|
||||||
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
|
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
|
||||||
if (zmalloc_thread_safe) { \
|
if (zmalloc_thread_safe) { \
|
||||||
pthread_mutex_lock(&used_memory_mutex); \
|
pthread_mutex_lock(&used_memory_mutex); \
|
||||||
used_memory += _n; \
|
used_memory += _n; \
|
||||||
zmalloc_allocations[_stat_slot]++; \
|
|
||||||
pthread_mutex_unlock(&used_memory_mutex); \
|
pthread_mutex_unlock(&used_memory_mutex); \
|
||||||
} else { \
|
} else { \
|
||||||
used_memory += _n; \
|
used_memory += _n; \
|
||||||
zmalloc_allocations[_stat_slot]++; \
|
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
@ -83,8 +80,6 @@
|
|||||||
static size_t used_memory = 0;
|
static size_t used_memory = 0;
|
||||||
static int zmalloc_thread_safe = 0;
|
static int zmalloc_thread_safe = 0;
|
||||||
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
/* Note that malloc_allocations elements are initialized to zero by C */
|
|
||||||
size_t zmalloc_allocations[ZMALLOC_MAX_ALLOC_STAT+1];
|
|
||||||
|
|
||||||
static void zmalloc_oom(size_t size) {
|
static void zmalloc_oom(size_t size) {
|
||||||
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
|
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
|
||||||
@ -185,11 +180,6 @@ size_t zmalloc_used_memory(void) {
|
|||||||
return um;
|
return um;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t zmalloc_allocations_for_size(size_t size) {
|
|
||||||
if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;
|
|
||||||
return zmalloc_allocations[size];
|
|
||||||
}
|
|
||||||
|
|
||||||
void zmalloc_enable_thread_safeness(void) {
|
void zmalloc_enable_thread_safeness(void) {
|
||||||
zmalloc_thread_safe = 1;
|
zmalloc_thread_safe = 1;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,5 @@ size_t zmalloc_used_memory(void);
|
|||||||
void zmalloc_enable_thread_safeness(void);
|
void zmalloc_enable_thread_safeness(void);
|
||||||
float zmalloc_get_fragmentation_ratio(void);
|
float zmalloc_get_fragmentation_ratio(void);
|
||||||
size_t zmalloc_get_rss(void);
|
size_t zmalloc_get_rss(void);
|
||||||
size_t zmalloc_allocations_for_size(size_t size);
|
|
||||||
|
|
||||||
#define ZMALLOC_MAX_ALLOC_STAT 256
|
|
||||||
|
|
||||||
#endif /* _ZMALLOC_H */
|
#endif /* _ZMALLOC_H */
|
||||||
|
@ -101,4 +101,22 @@ tags {"aof"} {
|
|||||||
assert_equal 1 [$client scard set]
|
assert_equal 1 [$client scard set]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## Test that EXPIREAT is loaded correctly
|
||||||
|
create_aof {
|
||||||
|
append_to_aof [formatCommand rpush list foo]
|
||||||
|
append_to_aof [formatCommand expireat list 1000]
|
||||||
|
append_to_aof [formatCommand rpush list bar]
|
||||||
|
}
|
||||||
|
|
||||||
|
start_server_aof [list dir $server_path] {
|
||||||
|
test "AOF+EXPIRE: Server should have been started" {
|
||||||
|
assert_equal 1 [is_alive $srv]
|
||||||
|
}
|
||||||
|
|
||||||
|
test "AOF+EXPIRE: List should be empty" {
|
||||||
|
set client [redis [dict get $srv host] [dict get $srv port]]
|
||||||
|
assert_equal 0 [$client llen list]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ proc execute_everything {} {
|
|||||||
execute_tests "unit/slowlog"
|
execute_tests "unit/slowlog"
|
||||||
|
|
||||||
# run tests with VM enabled
|
# run tests with VM enabled
|
||||||
set ::global_overrides {vm-enabled yes}
|
set ::global_overrides {vm-enabled yes really-use-vm yes}
|
||||||
execute_tests "unit/protocol"
|
execute_tests "unit/protocol"
|
||||||
execute_tests "unit/basic"
|
execute_tests "unit/basic"
|
||||||
execute_tests "unit/type/list"
|
execute_tests "unit/type/list"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user