Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
c1b27012
Commit
c1b27012
authored
Jul 27, 2011
by
antirez
Browse files
Merge remote-tracking branch 'origin/2.2' into 2.2
parents
62e6f6c2
5960ac9d
Changes
17
Hide whitespace changes
Inline
Side-by-side
00-RELEASENOTES
View file @
c1b27012
...
...
@@ -12,6 +12,22 @@ for 2.0.
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
==========================
...
...
redis.conf
View file @
c1b27012
...
...
@@ -314,10 +314,13 @@ slowlog-log-slower-than 10000
# 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.
slowlog
-
log
-
len
1024
slowlog
-
max
-
len
1024
################################ 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
# 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
...
...
src/Makefile
View file @
c1b27012
...
...
@@ -5,6 +5,19 @@
release_hdr
:=
$(
shell
sh
-c
'./mkreleasehdr.sh'
)
uname_S
:=
$(
shell
sh
-c
'uname -s 2>/dev/null || echo not'
)
OPTIMIZATION
?=
-O2
CCCOLOR
=
"
\0
33[34m"
LINKCOLOR
=
"
\0
33[34;1m"
SRCCOLOR
=
"
\0
33[33m"
BINCOLOR
=
"
\0
33[37;1m"
MAKECOLOR
=
"
\0
33[32;1m"
ENDCOLOR
=
"
\0
33[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)
CFLAGS
?=
-std
=
c99
-pedantic
$(OPTIMIZATION)
-Wall
-W
-D__EXTENSIONS__
-D_XPG6
CCLINK
?=
-ldl
-lnsl
-lsocket
-lm
-lpthread
...
...
@@ -111,33 +124,36 @@ zipmap.o: zipmap.c zmalloc.h
zmalloc.o
:
zmalloc.c config.h zmalloc.h
dependencies
:
@
printf
'%b %b\n'
$(MAKECOLOR)
MAKE
$(ENDCOLOR)
$(BINCOLOR)
hiredis
$(ENDCOLOR)
cd
../deps/hiredis
&&
$(MAKE)
static
ARCH
=
"
$(ARCH)
"
@
printf
'%b %b\n'
$(MAKECOLOR)
MAKE
$(ENDCOLOR)
$(BINCOLOR)
linenoise
$(ENDCOLOR)
cd
../deps/linenoise
&&
$(MAKE)
ARCH
=
"
$(ARCH)
"
redis-server
:
$(OBJ)
$(CC)
-o
$(PRGNAME)
$(CCOPT)
$(DEBUG)
$(OBJ)
$(QUIET_LINK)
$(CC)
-o
$(PRGNAME)
$(CCOPT)
$(DEBUG)
$(OBJ)
redis-benchmark
:
dependencies $(BENCHOBJ)
cd
../deps/hiredis
&&
$(MAKE)
static
$(CC)
-o
$(BENCHPRGNAME)
$(CCOPT)
$(DEBUG)
$(BENCHOBJ)
../deps/hiredis/libhiredis.a
@
printf
'%b %b\n'
$(MAKECOLOR)
MAKE
$(ENDCOLOR)
$(BINCOLOR)
hiredis
$(ENDCOLOR)
cd
../deps/hiredis
&&
$(MAKE)
static
ARCH
=
"
$(ARCH)
"
$(QUIET_LINK)$(CC)
-o
$(BENCHPRGNAME)
$(CCOPT)
$(DEBUG)
$(BENCHOBJ)
../deps/hiredis/libhiredis.a
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)
$(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
:
$(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)
$(CC)
-o
$(CHECKDUMPPRGNAME)
$(CCOPT)
$(DEBUG)
$(CHECKDUMPOBJ)
$(QUIET_LINK)
$(CC)
-o
$(CHECKDUMPPRGNAME)
$(CCOPT)
$(DEBUG)
$(CHECKDUMPOBJ)
redis-check-aof
:
$(CHECKAOFOBJ)
$(CC)
-o
$(CHECKAOFPRGNAME)
$(CCOPT)
$(DEBUG)
$(CHECKAOFOBJ)
$(QUIET_LINK)
$(CC)
-o
$(CHECKAOFPRGNAME)
$(CCOPT)
$(DEBUG)
$(CHECKAOFOBJ)
.c.o
:
$(CC)
-c
$(CFLAGS)
$(DEBUG)
$(COMPILE_TIME)
$<
$(QUIET_CC)
$(CC)
-c
$(CFLAGS)
$(DEBUG)
$(COMPILE_TIME)
$<
clean
:
rm
-rf
$(PRGNAME)
$(BENCHPRGNAME)
$(CLIPRGNAME)
$(CHECKDUMPPRGNAME)
$(CHECKAOFPRGNAME)
*
.o
*
.gcda
*
.gcno
*
.gcov
...
...
src/aof.c
View file @
c1b27012
...
...
@@ -19,15 +19,15 @@ void stopAppendOnly(void) {
server
.
appendseldb
=
-
1
;
server
.
appendonly
=
0
;
/* rewrite operation in progress? kill it, wait child exit */
if
(
server
.
bg
sav
echildpid
!=
-
1
)
{
if
(
server
.
bg
rewrit
echildpid
!=
-
1
)
{
int
statloc
;
if
(
kill
(
server
.
bg
sav
echildpid
,
SIGKILL
)
!=
-
1
)
if
(
kill
(
server
.
bg
rewrit
echildpid
,
SIGKILL
)
!=
-
1
)
wait3
(
&
statloc
,
0
,
NULL
);
/* reset the buffer accumulating changes while the child saves */
sdsfree
(
server
.
bgrewritebuf
);
server
.
bgrewritebuf
=
sdsempty
();
server
.
bg
sav
echildpid
=
-
1
;
server
.
bg
rewrit
echildpid
=
-
1
;
}
}
...
...
src/config.c
View file @
c1b27012
...
...
@@ -30,6 +30,7 @@ void loadServerConfig(char *filename) {
char
buf
[
REDIS_CONFIGLINE_MAX
+
1
],
*
err
=
NULL
;
int
linenum
=
0
;
sds
line
=
NULL
;
int
really_use_vm
=
0
;
if
(
filename
[
0
]
==
'-'
&&
filename
[
1
]
==
'\0'
)
fp
=
stdin
;
...
...
@@ -243,6 +244,10 @@ void loadServerConfig(char *filename) {
if
((
server
.
vm_enabled
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
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
)
{
zfree
(
server
.
vm_swap_file
);
server
.
vm_swap_file
=
zstrdup
(
argv
[
1
]);
...
...
@@ -303,6 +308,7 @@ void loadServerConfig(char *filename) {
sdsfree
(
line
);
}
if
(
fp
!=
stdin
)
fclose
(
fp
);
if
(
server
.
vm_enabled
&&
!
really_use_vm
)
goto
vm_warning
;
return
;
loaderr:
...
...
@@ -311,6 +317,15 @@ loaderr:
fprintf
(
stderr
,
">>> '%s'
\n
"
,
line
);
fprintf
(
stderr
,
"%s
\n
"
,
err
);
exit
(
1
);
vm_warning:
fprintf
(
stderr
,
"
\n
ARE 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
);
}
/*-----------------------------------------------------------------------------
...
...
src/db.c
View file @
c1b27012
...
...
@@ -455,6 +455,9 @@ int expireIfNeeded(redisDb *db, robj *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:
* the slave key expiration is controlled by the master that will
* 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
);
return
;
}
if
(
seconds
<=
0
)
{
if
(
dbDelete
(
c
->
db
,
key
))
server
.
dirty
++
;
addReply
(
c
,
shared
.
cone
);
/* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past
* should never be executed as a DEL when load the AOF or in the context
* 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
);
addReply
(
c
,
shared
.
cone
);
return
;
}
else
{
time_t
when
=
time
(
NULL
)
+
seconds
;
...
...
src/multi.c
View file @
c1b27012
...
...
@@ -24,14 +24,14 @@ void freeClientMultiState(redisClient *c) {
}
/* Add a new command into the MULTI commands queue */
void
queueMultiCommand
(
redisClient
*
c
,
struct
redisCommand
*
cmd
)
{
void
queueMultiCommand
(
redisClient
*
c
)
{
multiCmd
*
mc
;
int
j
;
c
->
mstate
.
commands
=
zrealloc
(
c
->
mstate
.
commands
,
sizeof
(
multiCmd
)
*
(
c
->
mstate
.
count
+
1
));
mc
=
c
->
mstate
.
commands
+
c
->
mstate
.
count
;
mc
->
cmd
=
cmd
;
mc
->
cmd
=
c
->
cmd
;
mc
->
argc
=
c
->
argc
;
mc
->
argv
=
zmalloc
(
sizeof
(
robj
*
)
*
c
->
argc
);
memcpy
(
mc
->
argv
,
c
->
argv
,
sizeof
(
robj
*
)
*
c
->
argc
);
...
...
@@ -78,6 +78,7 @@ void execCommand(redisClient *c) {
int
j
;
robj
**
orig_argv
;
int
orig_argc
;
struct
redisCommand
*
orig_cmd
;
if
(
!
(
c
->
flags
&
REDIS_MULTI
))
{
addReplyError
(
c
,
"EXEC without MULTI"
);
...
...
@@ -105,18 +106,22 @@ void execCommand(redisClient *c) {
unwatchAllKeys
(
c
);
/* Unwatch ASAP otherwise we'll waste CPU cycles */
orig_argv
=
c
->
argv
;
orig_argc
=
c
->
argc
;
orig_cmd
=
c
->
cmd
;
addReplyMultiBulkLen
(
c
,
c
->
mstate
.
count
);
for
(
j
=
0
;
j
<
c
->
mstate
.
count
;
j
++
)
{
c
->
argc
=
c
->
mstate
.
commands
[
j
].
argc
;
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. */
c
->
mstate
.
commands
[
j
].
argc
=
c
->
argc
;
c
->
mstate
.
commands
[
j
].
argv
=
c
->
argv
;
c
->
mstate
.
commands
[
j
].
cmd
=
c
->
cmd
;
}
c
->
argv
=
orig_argv
;
c
->
argc
=
orig_argc
;
c
->
cmd
=
orig_cmd
;
freeClientMultiState
(
c
);
initClientMultiState
(
c
);
c
->
flags
&=
~
(
REDIS_MULTI
|
REDIS_DIRTY_CAS
);
...
...
src/networking.c
View file @
c1b27012
...
...
@@ -31,6 +31,7 @@ redisClient *createClient(int fd) {
c
->
reqtype
=
0
;
c
->
argc
=
0
;
c
->
argv
=
NULL
;
c
->
cmd
=
NULL
;
c
->
multibulklen
=
0
;
c
->
bulklen
=
-
1
;
c
->
sentlen
=
0
;
...
...
@@ -444,6 +445,7 @@ static void freeClientArgv(redisClient *c) {
for
(
j
=
0
;
j
<
c
->
argc
;
j
++
)
decrRefCount
(
c
->
argv
[
j
]);
c
->
argc
=
0
;
c
->
cmd
=
NULL
;
}
void
freeClient
(
redisClient
*
c
)
{
...
...
@@ -896,4 +898,3 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
c
->
argc
=
argc
;
va_end
(
ap
);
}
src/redis.c
View file @
c1b27012
...
...
@@ -677,7 +677,7 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
readQueryFromClient
,
c
);
cmd
=
lookupCommand
(
c
->
argv
[
0
]
->
ptr
);
redisAssert
(
cmd
!=
NULL
);
call
(
c
,
cmd
);
call
(
c
);
resetClient
(
c
);
/* There may be more data to process in the input buffer. */
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 */
void
call
(
redisClient
*
c
,
struct
redisCommand
*
cmd
)
{
void
call
(
redisClient
*
c
)
{
long
long
dirty
,
start
=
ustime
(),
duration
;
dirty
=
server
.
dirty
;
cmd
->
proc
(
c
);
c
->
cmd
->
proc
(
c
);
dirty
=
server
.
dirty
-
dirty
;
duration
=
ustime
()
-
start
;
slowlogPushEntryIfNeeded
(
c
->
argv
,
c
->
argc
,
duration
);
if
(
server
.
appendonly
&&
dirty
)
feedAppendOnlyFile
(
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
((
dirty
||
cmd
->
flags
&
REDIS_CMD_FORCE_REPLICATION
)
&&
feedAppendOnlyFile
(
c
->
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
((
dirty
||
c
->
cmd
->
flags
&
REDIS_CMD_FORCE_REPLICATION
)
&&
listLength
(
server
.
slaves
))
replicationFeedSlaves
(
server
.
slaves
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
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
* if 0 is returned the client was destroied (i.e. after QUIT). */
int
processCommand
(
redisClient
*
c
)
{
struct
redisCommand
*
cmd
;
/* The QUIT command is handled separately. Normal command procs will
* go through checking for replication and QUIT will cause trouble
* 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
* such wrong arity, bad command name and so forth. */
cmd
=
lookupCommand
(
c
->
argv
[
0
]
->
ptr
);
if
(
!
cmd
)
{
* such
as
wrong arity, bad command name and so forth. */
c
->
cmd
=
lookupCommand
(
c
->
argv
[
0
]
->
ptr
);
if
(
!
c
->
cmd
)
{
addReplyErrorFormat
(
c
,
"unknown command '%s'"
,
(
char
*
)
c
->
argv
[
0
]
->
ptr
);
return
REDIS_OK
;
}
else
if
((
cmd
->
arity
>
0
&&
cmd
->
arity
!=
c
->
argc
)
||
(
c
->
argc
<
-
cmd
->
arity
))
{
}
else
if
((
c
->
cmd
->
arity
>
0
&&
c
->
cmd
->
arity
!=
c
->
argc
)
||
(
c
->
argc
<
-
c
->
cmd
->
arity
))
{
addReplyErrorFormat
(
c
,
"wrong number of arguments for '%s' command"
,
cmd
->
name
);
c
->
cmd
->
name
);
return
REDIS_OK
;
}
/* 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"
);
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
* is returning an error. */
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
)
{
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 */
if
((
dictSize
(
c
->
pubsub_channels
)
>
0
||
listLength
(
c
->
pubsub_patterns
)
>
0
)
&&
cmd
->
proc
!=
subscribeCommand
&&
cmd
->
proc
!=
unsubscribeCommand
&&
cmd
->
proc
!=
psubscribeCommand
&&
cmd
->
proc
!=
punsubscribeCommand
)
{
c
->
cmd
->
proc
!=
subscribeCommand
&&
c
->
cmd
->
proc
!=
unsubscribeCommand
&&
c
->
cmd
->
proc
!=
psubscribeCommand
&&
c
->
cmd
->
proc
!=
punsubscribeCommand
)
{
addReplyError
(
c
,
"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context"
);
return
REDIS_OK
;
}
...
...
@@ -1044,7 +1045,7 @@ int processCommand(redisClient *c) {
* we are a slave with a broken link with master. */
if
(
server
.
masterhost
&&
server
.
replstate
!=
REDIS_REPL_CONNECTED
&&
server
.
repl_serve_stale_data
==
0
&&
cmd
->
proc
!=
infoCommand
&&
cmd
->
proc
!=
slaveofCommand
)
c
->
cmd
->
proc
!=
infoCommand
&&
c
->
cmd
->
proc
!=
slaveofCommand
)
{
addReplyError
(
c
,
"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 */
if
(
server
.
loading
&&
cmd
->
proc
!=
infoCommand
)
{
if
(
server
.
loading
&&
c
->
cmd
->
proc
!=
infoCommand
)
{
addReply
(
c
,
shared
.
loadingerr
);
return
REDIS_OK
;
}
/* Exec the command */
if
(
c
->
flags
&
REDIS_MULTI
&&
cmd
->
proc
!=
execCommand
&&
cmd
->
proc
!=
discardCommand
&&
cmd
->
proc
!=
multiCommand
&&
cmd
->
proc
!=
watchCommand
)
c
->
cmd
->
proc
!=
execCommand
&&
c
->
cmd
->
proc
!=
discardCommand
&&
c
->
cmd
->
proc
!=
multiCommand
&&
c
->
cmd
->
proc
!=
watchCommand
)
{
queueMultiCommand
(
c
,
cmd
);
queueMultiCommand
(
c
);
addReply
(
c
,
shared
.
queued
);
}
else
{
if
(
server
.
vm_enabled
&&
server
.
vm_max_threads
>
0
&&
blockClientOnSwappedKeys
(
c
,
cmd
))
return
REDIS_ERR
;
call
(
c
,
cmd
);
blockClientOnSwappedKeys
(
c
))
return
REDIS_ERR
;
call
(
c
);
}
return
REDIS_OK
;
}
...
...
@@ -1075,20 +1076,29 @@ int processCommand(redisClient *c) {
/*================================== Shutdown =============================== */
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.
We want to avoid race conditions, for instance our saving child may
overwrite the synchronous saving did by SHUTDOWN. */
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
);
rdbRemoveTempFile
(
server
.
bgsavechildpid
);
}
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 */
redisLog
(
REDIS_NOTICE
,
"Calling fsync() on the AOF file."
);
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 */
if
(
rdbSave
(
server
.
dbfilename
)
!=
REDIS_OK
)
{
/* 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
* saving aborted, handling special stuff like slaves pending for
* 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
;
}
}
else
{
redisLog
(
REDIS_WARNING
,
"Not saving DB."
);
}
if
(
server
.
daemonize
)
unlink
(
server
.
pidfile
);
redisLog
(
REDIS_WARNING
,
"Server exit now, bye bye..."
);
if
(
server
.
vm_enabled
)
{
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
;
}
...
...
@@ -1176,8 +1195,8 @@ sds genRedisInfoString(void) {
"lru_clock:%ld
\r\n
"
"used_cpu_sys:%.2f
\r\n
"
"used_cpu_user:%.2f
\r\n
"
"used_cpu_sys_children
s
:%.2f
\r\n
"
"used_cpu_user_children
s
:%.2f
\r\n
"
"used_cpu_sys_children:%.2f
\r\n
"
"used_cpu_user_children:%.2f
\r\n
"
"connected_clients:%d
\r\n
"
"connected_slaves:%d
\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
++
)
{
long
long
keys
,
vkeys
;
...
...
src/redis.h
View file @
c1b27012
...
...
@@ -314,6 +314,7 @@ typedef struct redisClient {
sds
querybuf
;
int
argc
;
robj
**
argv
;
struct
redisCommand
*
cmd
;
int
reqtype
;
int
multibulklen
;
/* number of multi bulk arguments left to read */
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
initClientMultiState
(
redisClient
*
c
);
void
freeClientMultiState
(
redisClient
*
c
);
void
queueMultiCommand
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
void
queueMultiCommand
(
redisClient
*
c
);
void
touchWatchedKey
(
redisDb
*
db
,
robj
*
key
);
void
touchWatchedKeysOnFlush
(
int
dbid
);
...
...
@@ -788,7 +789,7 @@ int processCommand(redisClient *c);
void
setupSignalHandlers
(
void
);
struct
redisCommand
*
lookupCommand
(
sds
name
);
struct
redisCommand
*
lookupCommandByCString
(
char
*
s
);
void
call
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
void
call
(
redisClient
*
c
);
int
prepareForShutdown
();
void
redisLog
(
int
level
,
const
char
*
fmt
,
...);
void
usage
();
...
...
@@ -819,7 +820,7 @@ void vmReopenSwapFile(void);
int
vmFreePage
(
off_t
page
);
void
zunionInterBlockClientOnSwappedKeys
(
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
);
void
handleClientsBlockedOnSwappedKey
(
redisDb
*
db
,
robj
*
key
);
vmpointer
*
vmSwapObjectBlocking
(
robj
*
val
);
...
...
src/t_list.c
View file @
c1b27012
...
...
@@ -904,6 +904,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
if
(
listTypeLength
(
o
)
!=
0
)
{
/* If the list contains elements fall back to the usual
* non-blocking POP operation */
struct
redisCommand
*
orig_cmd
;
robj
*
argv
[
2
],
**
orig_argv
;
int
orig_argc
;
...
...
@@ -911,6 +912,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
* popGenericCommand() as the command takes a single key. */
orig_argv
=
c
->
argv
;
orig_argc
=
c
->
argc
;
orig_cmd
=
c
->
cmd
;
argv
[
1
]
=
c
->
argv
[
j
];
c
->
argv
=
argv
;
c
->
argc
=
2
;
...
...
@@ -928,6 +930,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
/* Fix the client structure with the original stuff */
c
->
argv
=
orig_argv
;
c
->
argc
=
orig_argc
;
c
->
cmd
=
orig_cmd
;
return
;
}
...
...
src/version.h
View file @
c1b27012
#define REDIS_VERSION "2.2.1
1
"
#define REDIS_VERSION "2.2.1
2
"
src/vm.c
View file @
c1b27012
...
...
@@ -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
* continue as the keys it is going to access appear to be in memory. */
int
blockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
)
{
if
(
cmd
->
vm_preload_proc
!=
NULL
)
{
cmd
->
vm_preload_proc
(
c
,
cmd
,
c
->
argc
,
c
->
argv
);
int
blockClientOnSwappedKeys
(
redisClient
*
c
)
{
if
(
c
->
cmd
->
vm_preload_proc
!=
NULL
)
{
c
->
cmd
->
vm_preload_proc
(
c
,
c
->
cmd
,
c
->
argc
,
c
->
argv
);
}
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. */
...
...
src/zmalloc.c
View file @
c1b27012
...
...
@@ -55,16 +55,13 @@
#define update_zmalloc_stat_alloc(__n,__size) do { \
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 (zmalloc_thread_safe) { \
pthread_mutex_lock(&used_memory_mutex); \
used_memory += _n; \
zmalloc_allocations[_stat_slot]++; \
pthread_mutex_unlock(&used_memory_mutex); \
} else { \
used_memory += _n; \
zmalloc_allocations[_stat_slot]++; \
} \
} while(0)
...
...
@@ -83,8 +80,6 @@
static
size_t
used_memory
=
0
;
static
int
zmalloc_thread_safe
=
0
;
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
)
{
fprintf
(
stderr
,
"zmalloc: Out of memory trying to allocate %zu bytes
\n
"
,
...
...
@@ -185,11 +180,6 @@ size_t zmalloc_used_memory(void) {
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
)
{
zmalloc_thread_safe
=
1
;
}
...
...
src/zmalloc.h
View file @
c1b27012
...
...
@@ -40,8 +40,5 @@ size_t zmalloc_used_memory(void);
void
zmalloc_enable_thread_safeness
(
void
);
float
zmalloc_get_fragmentation_ratio
(
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 */
tests/integration/aof.tcl
View file @
c1b27012
...
...
@@ -101,4 +101,22 @@ tags {"aof"} {
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
]
}
}
}
tests/test_helper.tcl
View file @
c1b27012
...
...
@@ -128,7 +128,7 @@ proc execute_everything {} {
execute_tests
"unit/slowlog"
# 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/basic"
execute_tests
"unit/type/list"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment