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
0681c5ad
Commit
0681c5ad
authored
Jul 12, 2011
by
antirez
Browse files
master branch merged into scripting.
parents
15bc1cc1
34a8b517
Changes
34
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
0681c5ad
...
@@ -14,6 +14,7 @@ clean:
...
@@ -14,6 +14,7 @@ clean:
cd
deps/linenoise
&&
$(MAKE)
$@
cd
deps/linenoise
&&
$(MAKE)
$@
cd
deps/jemalloc
&&
$(MAKE)
distclean
cd
deps/jemalloc
&&
$(MAKE)
distclean
cd
deps/lua
&&
$(MAKE)
$@
cd
deps/lua
&&
$(MAKE)
$@
-
(
cd
deps/jemalloc
&&
$(MAKE)
distclean
)
$(TARGETS)
:
$(TARGETS)
:
cd
src
&&
$(MAKE)
$@
cd
src
&&
$(MAKE)
$@
...
...
deps/hiredis/hiredis.c
View file @
0681c5ad
...
@@ -50,7 +50,7 @@ typedef struct redisReader {
...
@@ -50,7 +50,7 @@ typedef struct redisReader {
size_t
pos
;
/* buffer cursor */
size_t
pos
;
/* buffer cursor */
size_t
len
;
/* buffer length */
size_t
len
;
/* buffer length */
redisReadTask
rstack
[
3
];
/* stack of read tasks */
redisReadTask
rstack
[
9
];
/* stack of read tasks */
int
ridx
;
/* index of stack */
int
ridx
;
/* index of stack */
void
*
privdata
;
/* user-settable arbitrary field */
void
*
privdata
;
/* user-settable arbitrary field */
}
redisReader
;
}
redisReader
;
...
@@ -347,9 +347,9 @@ static int processMultiBulkItem(redisReader *r) {
...
@@ -347,9 +347,9 @@ static int processMultiBulkItem(redisReader *r) {
int
root
=
0
;
int
root
=
0
;
/* Set error for nested multi bulks with depth > 1 */
/* Set error for nested multi bulks with depth > 1 */
if
(
r
->
ridx
==
2
)
{
if
(
r
->
ridx
==
8
)
{
redisSetReplyReaderError
(
r
,
sdscatprintf
(
sdsempty
(),
redisSetReplyReaderError
(
r
,
sdscatprintf
(
sdsempty
(),
"No support for nested multi bulk replies with depth >
1
"
));
"No support for nested multi bulk replies with depth >
7
"
));
return
-
1
;
return
-
1
;
}
}
...
...
redis.conf
View file @
0681c5ad
...
@@ -319,6 +319,30 @@ auto-aof-rewrite-min-size 64mb
...
@@ -319,6 +319,30 @@ auto-aof-rewrite-min-size 64mb
# your server forever. Set it to 0 or a negative value for unlimited execution.
# your server forever. Set it to 0 or a negative value for unlimited execution.
lua
-
time
-
limit
60000
lua
-
time
-
limit
60000
################################## SLOW LOG ###################################
# The Redis Slow Log is a system to log queries that exceeded a specified
# execution time. The execution time does not include the I/O operations
# like talking with the client, sending the reply and so forth,
# but just the time needed to actually execute the command (this is the only
# stage of command execution where the thread is blocked and can not serve
# other requests in the meantime).
#
# You can configure the slow log with two parameters: one tells Redis
# what is the execution time, in microseconds, to exceed in order for the
# command to get logged, and the other parameter is the length of the
# slow log. When a new command is logged the oldest one is removed from the
# queue of logged commands.
# The following time is expressed in microseconds, so 1000000 is equivalent
# to one second. Note that a negative number disables the slow log, while
# a value of zero forces the logging of every command.
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
-
max
-
len
1024
############################### ADVANCED CONFIG ###############################
############################### ADVANCED CONFIG ###############################
# Hashes are encoded in a special way (much more memory efficient) when they
# Hashes are encoded in a special way (much more memory efficient) when they
...
...
src/Makefile
View file @
0681c5ad
...
@@ -61,7 +61,7 @@ QUIET_CC = @printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR
...
@@ -61,7 +61,7 @@ QUIET_CC = @printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR
QUIET_LINK
=
@printf
' %b %b\n'
$(LINKCOLOR)
LINK
$(ENDCOLOR)
$(BINCOLOR)$@$(ENDCOLOR)
;
QUIET_LINK
=
@printf
' %b %b\n'
$(LINKCOLOR)
LINK
$(ENDCOLOR)
$(BINCOLOR)$@$(ENDCOLOR)
;
endif
endif
OBJ
=
adlist.o ae.o anet.o dict.o redis.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 endian.o scripting.o
OBJ
=
adlist.o ae.o anet.o dict.o redis.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 endian.o
slowlog.o
scripting.o
BENCHOBJ
=
ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
BENCHOBJ
=
ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o
CHECKDUMPOBJ
=
redis-check-dump.o lzf_c.o lzf_d.o
CHECKDUMPOBJ
=
redis-check-dump.o lzf_c.o lzf_d.o
...
@@ -86,38 +86,37 @@ ae_kqueue.o: ae_kqueue.c
...
@@ -86,38 +86,37 @@ ae_kqueue.o: ae_kqueue.c
ae_select.o
:
ae_select.c
ae_select.o
:
ae_select.c
anet.o
:
anet.c fmacros.h anet.h
anet.o
:
anet.c fmacros.h anet.h
aof.o
:
aof.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
aof.o
:
aof.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
cluster.o
:
cluster.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
cluster.o
:
cluster.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
slowlog.h
config.o
:
config.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
config.o
:
config.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
crc16.o
:
crc16.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
crc16.o
:
crc16.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
db.o
:
db.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
db.o
:
db.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
debug.o
:
debug.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
debug.o
:
debug.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h sha1.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h slowlog.h
\
dict.o
:
dict.c fmacros.h dict.h zmalloc.h
diskstore.o
:
diskstore.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
sha1.h
sha1.h
dscache.o
:
dscache.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
dict.o
:
dict.c fmacros.h dict.h zmalloc.h
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
endian.o
:
endian.c
endian.o
:
endian.c
intset.o
:
intset.c intset.h zmalloc.h endian.h
intset.o
:
intset.c intset.h zmalloc.h endian.h
lzf_c.o
:
lzf_c.c lzfP.h
lzf_c.o
:
lzf_c.c lzfP.h
lzf_d.o
:
lzf_d.c lzfP.h
lzf_d.o
:
lzf_d.c lzfP.h
multi.o
:
multi.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
multi.o
:
multi.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
networking.o
:
networking.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
networking.o
:
networking.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
slowlog.h
object.o
:
object.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
object.o
:
object.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
pqsort.o
:
pqsort.c
pqsort.o
:
pqsort.c
pubsub.o
:
pubsub.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
pubsub.o
:
pubsub.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
rdb.o
:
rdb.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
rdb.o
:
rdb.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h lzf.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h slowlog.h
\
lzf.h
redis-benchmark.o
:
redis-benchmark.c fmacros.h ae.h
\
redis-benchmark.o
:
redis-benchmark.c fmacros.h ae.h
\
../deps/hiredis/hiredis.h sds.h adlist.h zmalloc.h
../deps/hiredis/hiredis.h sds.h adlist.h zmalloc.h
redis-check-aof.o
:
redis-check-aof.c fmacros.h config.h
redis-check-aof.o
:
redis-check-aof.c fmacros.h config.h
...
@@ -125,27 +124,33 @@ redis-check-dump.o: redis-check-dump.c lzf.h
...
@@ -125,27 +124,33 @@ redis-check-dump.o: redis-check-dump.c lzf.h
redis-cli.o
:
redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h
\
redis-cli.o
:
redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h
\
sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h
sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h
redis.o
:
redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
redis.o
:
redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
\
asciilogo.h
asciilogo.h
release.o
:
release.c release.h
release.o
:
release.c release.h
replication.o
:
replication.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
replication.o
:
replication.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
slowlog.h
sds.o
:
sds.c sds.h zmalloc.h
sds.o
:
sds.c sds.h zmalloc.h
sha1.o
:
sha1.c sha1.h config.h
sha1.o
:
sha1.c sha1.h config.h
slowlog.o
:
slowlog.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
slowlog.h
sort.o
:
sort.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
sort.o
:
sort.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h pqsort.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h slowlog.h
\
pqsort.h
syncio.o
:
syncio.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
syncio.o
:
syncio.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
t_hash.o
:
t_hash.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
t_hash.o
:
t_hash.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
t_list.o
:
t_list.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
t_list.o
:
t_list.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
t_set.o
:
t_set.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
t_set.o
:
t_set.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
t_string.o
:
t_string.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
t_string.o
:
t_string.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
\
slowlog.h
t_zset.o
:
t_zset.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
t_zset.o
:
t_zset.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
slowlog.h
util.o
:
util.c fmacros.h util.h
util.o
:
util.c fmacros.h util.h
ziplist.o
:
ziplist.c zmalloc.h util.h ziplist.h endian.h
ziplist.o
:
ziplist.c zmalloc.h util.h ziplist.h endian.h
zipmap.o
:
zipmap.c zmalloc.h endian.h
zipmap.o
:
zipmap.c zmalloc.h endian.h
...
@@ -197,8 +202,8 @@ clean:
...
@@ -197,8 +202,8 @@ clean:
dep
:
dep
:
$(CC)
-MM
*
.c
-I
../deps/hiredis
-I
../deps/linenoise
$(CC)
-MM
*
.c
-I
../deps/hiredis
-I
../deps/linenoise
test
:
redis-server
test
:
redis-server
redis-check-aof
@
(
cd
..
;
(
which tclsh
>
/dev/null
&&
tclsh tests/test_helper.tcl
--tags
"
${TAGS}
"
--file
"
${FILE}
"
)
||
echo
"You need to install Tcl in order to run tests."
)
@
(
cd
..
;
(
which tclsh
8.5
>
/dev/null
&&
tclsh
8.5
tests/test_helper.tcl
--tags
"
${TAGS}
"
)
||
echo
"You need to install Tcl
(tclsh8.5)
in order to run tests."
)
bench
:
bench
:
./redis-benchmark
./redis-benchmark
...
...
src/aof.c
View file @
0681c5ad
...
@@ -287,6 +287,8 @@ int loadAppendOnlyFile(char *filename) {
...
@@ -287,6 +287,8 @@ int loadAppendOnlyFile(char *filename) {
/* The fake client should not have a reply */
/* The fake client should not have a reply */
redisAssert
(
fakeClient
->
bufpos
==
0
&&
listLength
(
fakeClient
->
reply
)
==
0
);
redisAssert
(
fakeClient
->
bufpos
==
0
&&
listLength
(
fakeClient
->
reply
)
==
0
);
/* The fake client should never get blocked */
redisAssert
((
fakeClient
->
flags
&
REDIS_BLOCKED
)
==
0
);
/* Clean up. Command code may have changed argv/argc so we use the
/* Clean up. Command code may have changed argv/argc so we use the
* argv/argc of the client instead of the local variables. */
* argv/argc of the client instead of the local variables. */
...
...
src/config.c
View file @
0681c5ad
...
@@ -298,6 +298,12 @@ void loadServerConfig(char *filename) {
...
@@ -298,6 +298,12 @@ void loadServerConfig(char *filename) {
server
.
cluster
.
configfile
=
zstrdup
(
argv
[
1
]);
server
.
cluster
.
configfile
=
zstrdup
(
argv
[
1
]);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"lua-time-limit"
)
&&
argc
==
2
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"lua-time-limit"
)
&&
argc
==
2
)
{
server
.
lua_time_limit
=
strtoll
(
argv
[
1
],
NULL
,
10
);
server
.
lua_time_limit
=
strtoll
(
argv
[
1
],
NULL
,
10
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"slowlog-log-slower-than"
)
&&
argc
==
2
)
{
server
.
slowlog_log_slower_than
=
strtoll
(
argv
[
1
],
NULL
,
10
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"slowlog-max-len"
)
&&
argc
==
2
)
{
server
.
slowlog_max_len
=
strtoll
(
argv
[
1
],
NULL
,
10
);
}
else
{
}
else
{
err
=
"Bad directive or wrong number of arguments"
;
goto
loaderr
;
err
=
"Bad directive or wrong number of arguments"
;
goto
loaderr
;
}
}
...
@@ -471,6 +477,12 @@ void configSetCommand(redisClient *c) {
...
@@ -471,6 +477,12 @@ void configSetCommand(redisClient *c) {
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"lua-time-limit"
))
{
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"lua-time-limit"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
lua_time_limit
=
ll
;
server
.
lua_time_limit
=
ll
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"slowlog-log-slower-than"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
)
goto
badfmt
;
server
.
slowlog_log_slower_than
=
ll
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"slowlog-max-len"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
server
.
slowlog_max_len
=
(
unsigned
)
ll
;
}
else
{
}
else
{
addReplyErrorFormat
(
c
,
"Unsupported CONFIG parameter: %s"
,
addReplyErrorFormat
(
c
,
"Unsupported CONFIG parameter: %s"
,
(
char
*
)
c
->
argv
[
2
]
->
ptr
);
(
char
*
)
c
->
argv
[
2
]
->
ptr
);
...
@@ -645,6 +657,14 @@ void configGetCommand(redisClient *c) {
...
@@ -645,6 +657,14 @@ void configGetCommand(redisClient *c) {
if
(
stringmatch
(
pattern
,
"lua-time-limit"
,
0
))
{
if
(
stringmatch
(
pattern
,
"lua-time-limit"
,
0
))
{
addReplyBulkCString
(
c
,
"lua-time-limit"
);
addReplyBulkCString
(
c
,
"lua-time-limit"
);
addReplyBulkLongLong
(
c
,
server
.
lua_time_limit
);
addReplyBulkLongLong
(
c
,
server
.
lua_time_limit
);
if
(
stringmatch
(
pattern
,
"slowlog-log-slower-than"
,
0
))
{
addReplyBulkCString
(
c
,
"slowlog-log-slower-than"
);
addReplyBulkLongLong
(
c
,
server
.
slowlog_log_slower_than
);
matches
++
;
}
if
(
stringmatch
(
pattern
,
"slowlog-max-len"
,
0
))
{
addReplyBulkCString
(
c
,
"slowlog-max-len"
);
addReplyBulkLongLong
(
c
,
server
.
slowlog_max_len
);
matches
++
;
matches
++
;
}
}
setDeferredMultiBulkLength
(
c
,
replylen
,
matches
*
2
);
setDeferredMultiBulkLength
(
c
,
replylen
,
matches
*
2
);
...
...
src/db.c
View file @
0681c5ad
...
@@ -476,6 +476,9 @@ int expireIfNeeded(redisDb *db, robj *key) {
...
@@ -476,6 +476,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.
...
@@ -513,10 +516,24 @@ void expireGenericCommand(redisClient *c, robj *key, robj *param, long offset) {
...
@@ -513,10 +516,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
);
signalModifiedKey
(
c
->
db
,
key
);
signalModifiedKey
(
c
->
db
,
key
);
addReply
(
c
,
shared
.
cone
);
return
;
return
;
}
else
{
}
else
{
time_t
when
=
time
(
NULL
)
+
seconds
;
time_t
when
=
time
(
NULL
)
+
seconds
;
...
...
src/debug.c
View file @
0681c5ad
...
@@ -281,6 +281,12 @@ void debugCommand(redisClient *c) {
...
@@ -281,6 +281,12 @@ void debugCommand(redisClient *c) {
d
=
sdscatprintf
(
d
,
"%02x"
,
digest
[
j
]);
d
=
sdscatprintf
(
d
,
"%02x"
,
digest
[
j
]);
addReplyStatus
(
c
,
d
);
addReplyStatus
(
c
,
d
);
sdsfree
(
d
);
sdsfree
(
d
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"sleep"
)
&&
c
->
argc
==
3
)
{
double
dtime
=
strtod
(
c
->
argv
[
2
]
->
ptr
,
NULL
);
long
long
utime
=
dtime
*
1000000
;
usleep
(
utime
);
addReply
(
c
,
shared
.
ok
);
}
else
{
}
else
{
addReplyError
(
c
,
addReplyError
(
c
,
"Syntax error, try DEBUG [SEGFAULT|OBJECT <key>|SWAPIN <key>|SWAPOUT <key>|RELOAD]"
);
"Syntax error, try DEBUG [SEGFAULT|OBJECT <key>|SWAPIN <key>|SWAPOUT <key>|RELOAD]"
);
...
...
src/multi.c
View file @
0681c5ad
...
@@ -24,14 +24,14 @@ void freeClientMultiState(redisClient *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) {
...
@@ -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) {
...
@@ -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
);
...
...
src/networking.c
View file @
0681c5ad
...
@@ -36,6 +36,7 @@ redisClient *createClient(int fd) {
...
@@ -36,6 +36,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
;
...
@@ -461,6 +462,7 @@ static void freeClientArgv(redisClient *c) {
...
@@ -461,6 +462,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
)
{
...
@@ -961,5 +963,7 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
...
@@ -961,5 +963,7 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
/* Replace argv and argc with our new versions. */
/* Replace argv and argc with our new versions. */
c
->
argv
=
argv
;
c
->
argv
=
argv
;
c
->
argc
=
argc
;
c
->
argc
=
argc
;
c
->
cmd
=
lookupCommand
(
c
->
argv
[
0
]
->
ptr
);
redisAssert
(
c
->
cmd
!=
NULL
);
va_end
(
ap
);
va_end
(
ap
);
}
}
src/redis.c
View file @
0681c5ad
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
*/
*/
#include "redis.h"
#include "redis.h"
#include "slowlog.h"
#ifdef HAVE_BACKTRACE
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
#include <execinfo.h>
...
@@ -194,7 +195,8 @@ struct redisCommand redisCommandTable[] = {
...
@@ -194,7 +195,8 @@ struct redisCommand redisCommandTable[] = {
{
"object"
,
objectCommand
,
-
2
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"object"
,
objectCommand
,
-
2
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"client"
,
clientCommand
,
-
2
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"client"
,
clientCommand
,
-
2
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"eval"
,
evalCommand
,
-
3
,
REDIS_CMD_DENYOOM
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"eval"
,
evalCommand
,
-
3
,
REDIS_CMD_DENYOOM
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"evalsha"
,
evalShaCommand
,
-
3
,
REDIS_CMD_DENYOOM
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
}
{
"evalsha"
,
evalShaCommand
,
-
3
,
REDIS_CMD_DENYOOM
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"slowlog"
,
slowlogCommand
,
-
2
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
};
};
/*============================ Utility functions ============================ */
/*============================ Utility functions ============================ */
...
@@ -871,6 +873,10 @@ void initServerConfig() {
...
@@ -871,6 +873,10 @@ void initServerConfig() {
populateCommandTable
();
populateCommandTable
();
server
.
delCommand
=
lookupCommandByCString
(
"del"
);
server
.
delCommand
=
lookupCommandByCString
(
"del"
);
server
.
multiCommand
=
lookupCommandByCString
(
"multi"
);
server
.
multiCommand
=
lookupCommandByCString
(
"multi"
);
/* Slow log */
server
.
slowlog_log_slower_than
=
REDIS_SLOWLOG_LOG_SLOWER_THAN
;
server
.
slowlog_max_len
=
REDIS_SLOWLOG_MAX_LEN
;
}
}
void
initServer
()
{
void
initServer
()
{
...
@@ -958,6 +964,7 @@ void initServer() {
...
@@ -958,6 +964,7 @@ void initServer() {
if
(
server
.
cluster_enabled
)
clusterInit
();
if
(
server
.
cluster_enabled
)
clusterInit
();
scriptingInit
();
scriptingInit
();
slowlogInit
();
srand
(
time
(
NULL
)
^
getpid
());
srand
(
time
(
NULL
)
^
getpid
());
}
}
...
@@ -1004,18 +1011,20 @@ struct redisCommand *lookupCommandByCString(char *s) {
...
@@ -1004,18 +1011,20 @@ 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
();
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
;
cmd
->
microseconds
+=
ustime
()
-
start
;
duration
=
ustime
()
-
start
;
cmd
->
calls
++
;
c
->
cmd
->
microseconds
+=
duration
;
slowlogPushEntryIfNeeded
(
c
->
argv
,
c
->
argc
,
duration
);
c
->
cmd
->
calls
++
;
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
))
...
@@ -1032,8 +1041,6 @@ void call(redisClient *c, struct redisCommand *cmd) {
...
@@ -1032,8 +1041,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
...
@@ -1045,28 +1052,29 @@ int processCommand(redisClient *c) {
...
@@ -1045,28 +1052,29 @@ 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
;
}
}
/* If cluster is enabled, redirect here */
/* If cluster is enabled, redirect here */
if
(
server
.
cluster_enabled
&&
if
(
server
.
cluster_enabled
&&
!
(
cmd
->
getkeys_proc
==
NULL
&&
cmd
->
firstkey
==
0
))
{
!
(
c
->
cmd
->
getkeys_proc
==
NULL
&&
c
->
cmd
->
firstkey
==
0
))
{
int
hashslot
;
int
hashslot
;
if
(
server
.
cluster
.
state
!=
REDIS_CLUSTER_OK
)
{
if
(
server
.
cluster
.
state
!=
REDIS_CLUSTER_OK
)
{
...
@@ -1074,7 +1082,7 @@ int processCommand(redisClient *c) {
...
@@ -1074,7 +1082,7 @@ int processCommand(redisClient *c) {
return
REDIS_OK
;
return
REDIS_OK
;
}
else
{
}
else
{
int
ask
;
int
ask
;
clusterNode
*
n
=
getNodeByQuery
(
c
,
cmd
,
c
->
argv
,
c
->
argc
,
&
hashslot
,
&
ask
);
clusterNode
*
n
=
getNodeByQuery
(
c
,
c
->
cmd
,
c
->
argv
,
c
->
argc
,
&
hashslot
,
&
ask
);
if
(
n
==
NULL
)
{
if
(
n
==
NULL
)
{
addReplyError
(
c
,
"Multi keys request invalid in cluster"
);
addReplyError
(
c
,
"Multi keys request invalid in cluster"
);
return
REDIS_OK
;
return
REDIS_OK
;
...
@@ -1093,7 +1101,7 @@ int processCommand(redisClient *c) {
...
@@ -1093,7 +1101,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'"
);
...
@@ -1103,8 +1111,10 @@ int processCommand(redisClient *c) {
...
@@ -1103,8 +1111,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
;
}
}
...
@@ -1113,7 +1123,7 @@ int processCommand(redisClient *c) {
...
@@ -1113,7 +1123,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"
);
...
@@ -1121,20 +1131,20 @@ int processCommand(redisClient *c) {
...
@@ -1121,20 +1131,20 @@ 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
{
call
(
c
,
cmd
);
call
(
c
);
}
}
return
REDIS_OK
;
return
REDIS_OK
;
}
}
...
@@ -1305,22 +1315,6 @@ sds genRedisInfoString(char *section) {
...
@@ -1305,22 +1315,6 @@ sds genRedisInfoString(char *section) {
);
);
}
}
/* Allocation statistics */
if
(
allsections
||
!
strcasecmp
(
section
,
"allocstats"
))
{
if
(
sections
++
)
info
=
sdscat
(
info
,
"
\r\n
"
);
info
=
sdscat
(
info
,
"# Allocstats
\r\n
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
"
);
}
/* Persistence */
/* Persistence */
if
(
allsections
||
defsections
||
!
strcasecmp
(
section
,
"persistence"
))
{
if
(
allsections
||
defsections
||
!
strcasecmp
(
section
,
"persistence"
))
{
if
(
sections
++
)
info
=
sdscat
(
info
,
"
\r\n
"
);
if
(
sections
++
)
info
=
sdscat
(
info
,
"
\r\n
"
);
...
@@ -1456,8 +1450,8 @@ sds genRedisInfoString(char *section) {
...
@@ -1456,8 +1450,8 @@ sds genRedisInfoString(char *section) {
"# CPU
\r\n
"
"# CPU
\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_children
s
:%.2f
\r\n
"
"used_cpu_sys_children:%.2f
\r\n
"
"used_cpu_user_children
s
:%.2f
\r\n
"
,
"used_cpu_user_children:%.2f
\r\n
"
,
(
float
)
self_ru
.
ru_utime
.
tv_sec
+
(
float
)
self_ru
.
ru_utime
.
tv_usec
/
1000000
,
(
float
)
self_ru
.
ru_utime
.
tv_sec
+
(
float
)
self_ru
.
ru_utime
.
tv_usec
/
1000000
,
(
float
)
self_ru
.
ru_stime
.
tv_sec
+
(
float
)
self_ru
.
ru_stime
.
tv_usec
/
1000000
,
(
float
)
self_ru
.
ru_stime
.
tv_sec
+
(
float
)
self_ru
.
ru_stime
.
tv_usec
/
1000000
,
(
float
)
c_ru
.
ru_utime
.
tv_sec
+
(
float
)
c_ru
.
ru_utime
.
tv_usec
/
1000000
,
(
float
)
c_ru
.
ru_utime
.
tv_sec
+
(
float
)
c_ru
.
ru_utime
.
tv_usec
/
1000000
,
...
...
src/redis.h
View file @
0681c5ad
...
@@ -21,17 +21,17 @@
...
@@ -21,17 +21,17 @@
#include <netinet/in.h>
#include <netinet/in.h>
#include <lua.h>
#include <lua.h>
#include "ae.h"
/* Event driven programming library */
#include "ae.h"
/* Event driven programming library */
#include "sds.h"
/* Dynamic safe strings */
#include "sds.h"
/* Dynamic safe strings */
#include "dict.h"
/* Hash tables */
#include "dict.h"
/* Hash tables */
#include "adlist.h"
/* Linked lists */
#include "adlist.h"
/* Linked lists */
#include "zmalloc.h"
/* total memory usage aware version of malloc/free */
#include "zmalloc.h"
/* total memory usage aware version of malloc/free */
#include "anet.h"
/* Networking the easy way */
#include "anet.h"
/* Networking the easy way */
#include "zipmap.h"
/* Compact string -> string data structure */
#include "zipmap.h"
/* Compact string -> string data structure */
#include "ziplist.h"
/* Compact list data structure */
#include "ziplist.h"
/* Compact list data structure */
#include "intset.h"
/* Compact integer set structure */
#include "intset.h"
/* Compact integer set structure */
#include "version.h"
#include "version.h"
/* Version macro */
#include "util.h"
#include "util.h"
/* Misc functions useful in many places */
/* Error codes */
/* Error codes */
#define REDIS_OK 0
#define REDIS_OK 0
...
@@ -53,6 +53,8 @@
...
@@ -53,6 +53,8 @@
#define REDIS_MAX_LOGMSG_LEN 1024
/* Default maximum length of syslog messages */
#define REDIS_MAX_LOGMSG_LEN 1024
/* Default maximum length of syslog messages */
#define REDIS_AUTO_AOFREWRITE_PERC 100
#define REDIS_AUTO_AOFREWRITE_PERC 100
#define REDIS_AUTO_AOFREWRITE_MIN_SIZE (1024*1024)
#define REDIS_AUTO_AOFREWRITE_MIN_SIZE (1024*1024)
#define REDIS_SLOWLOG_LOG_SLOWER_THAN 10000
#define REDIS_SLOWLOG_MAX_LEN 64
/* Hash table parameters */
/* Hash table parameters */
#define REDIS_HT_MINFILL 10
/* Minimal hash table fill 10% */
#define REDIS_HT_MINFILL 10
/* Minimal hash table fill 10% */
...
@@ -312,6 +314,7 @@ typedef struct redisClient {
...
@@ -312,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 */
...
@@ -530,6 +533,10 @@ struct redisServer {
...
@@ -530,6 +533,10 @@ struct redisServer {
long
long
stat_keyspace_misses
;
/* number of failed lookups of keys */
long
long
stat_keyspace_misses
;
/* number of failed lookups of keys */
size_t
stat_peak_memory
;
/* max used memory record */
size_t
stat_peak_memory
;
/* max used memory record */
long
long
stat_fork_time
;
/* time needed to perform latets fork() */
long
long
stat_fork_time
;
/* time needed to perform latets fork() */
list
*
slowlog
;
long
long
slowlog_entry_id
;
long
long
slowlog_log_slower_than
;
unsigned
long
slowlog_max_len
;
/* Configuration */
/* Configuration */
int
verbosity
;
int
verbosity
;
int
maxidletime
;
int
maxidletime
;
...
@@ -807,7 +814,7 @@ void popGenericCommand(redisClient *c, int where);
...
@@ -807,7 +814,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
);
...
@@ -918,7 +925,7 @@ int processCommand(redisClient *c);
...
@@ -918,7 +925,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
redisLogRaw
(
int
level
,
const
char
*
msg
);
void
redisLogRaw
(
int
level
,
const
char
*
msg
);
...
...
src/slowlog.c
0 → 100644
View file @
0681c5ad
#include "redis.h"
#include "slowlog.h"
/* Slowlog implements a system that is able to remember the latest N
* queries that took more than M microseconds to execute.
*
* The execution time to reach to be logged in the slow log is set
* using the 'slowlog-log-slower-than' config directive, that is also
* readable and writable using the CONFIG SET/GET command.
*
* The slow queries log is actually not "logged" in the Redis log file
* but is accessible thanks to the SLOWLOG command. */
/* Create a new slowlog entry.
* Incrementing the ref count of all the objects retained is up to
* this function. */
slowlogEntry
*
slowlogCreateEntry
(
robj
**
argv
,
int
argc
,
long
long
duration
)
{
slowlogEntry
*
se
=
zmalloc
(
sizeof
(
*
se
));
int
j
;
se
->
argc
=
argc
;
se
->
argv
=
zmalloc
(
sizeof
(
robj
*
)
*
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
se
->
argv
[
j
]
=
argv
[
j
];
incrRefCount
(
argv
[
j
]);
}
se
->
time
=
time
(
NULL
);
se
->
duration
=
duration
;
se
->
id
=
server
.
slowlog_entry_id
++
;
return
se
;
}
/* Free a slow log entry. The argument is void so that the prototype of this
* function matches the one of the 'free' method of adlist.c.
*
* This function will take care to release all the retained object. */
void
slowlogFreeEntry
(
void
*
septr
)
{
slowlogEntry
*
se
=
septr
;
int
j
;
for
(
j
=
0
;
j
<
se
->
argc
;
j
++
)
decrRefCount
(
se
->
argv
[
j
]);
zfree
(
se
->
argv
);
zfree
(
se
);
}
/* Initialize the slow log. This function should be called a single time
* at server startup. */
void
slowlogInit
(
void
)
{
server
.
slowlog
=
listCreate
();
server
.
slowlog_entry_id
=
0
;
listSetFreeMethod
(
server
.
slowlog
,
slowlogFreeEntry
);
}
/* Push a new entry into the slow log.
* This function will make sure to trim the slow log accordingly to the
* configured max length. */
void
slowlogPushEntryIfNeeded
(
robj
**
argv
,
int
argc
,
long
long
duration
)
{
if
(
server
.
slowlog_log_slower_than
<
0
)
return
;
/* Slowlog disabled */
if
(
duration
>=
server
.
slowlog_log_slower_than
)
listAddNodeHead
(
server
.
slowlog
,
slowlogCreateEntry
(
argv
,
argc
,
duration
));
/* Remove old entries if needed. */
while
(
listLength
(
server
.
slowlog
)
>
server
.
slowlog_max_len
)
listDelNode
(
server
.
slowlog
,
listLast
(
server
.
slowlog
));
}
/* Remove all the entries from the current slow log. */
void
slowlogReset
(
void
)
{
while
(
listLength
(
server
.
slowlog
)
>
0
)
listDelNode
(
server
.
slowlog
,
listLast
(
server
.
slowlog
));
}
/* The SLOWLOG command. Implements all the subcommands needed to handle the
* Redis slow log. */
void
slowlogCommand
(
redisClient
*
c
)
{
if
(
c
->
argc
==
2
&&
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"reset"
))
{
slowlogReset
();
addReply
(
c
,
shared
.
ok
);
}
else
if
(
c
->
argc
==
2
&&
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"len"
))
{
addReplyLongLong
(
c
,
listLength
(
server
.
slowlog
));
}
else
if
((
c
->
argc
==
2
||
c
->
argc
==
3
)
&&
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"get"
))
{
long
count
=
10
,
sent
=
0
;
listIter
li
;
void
*
totentries
;
listNode
*
ln
;
slowlogEntry
*
se
;
if
(
c
->
argc
==
3
&&
getLongFromObjectOrReply
(
c
,
c
->
argv
[
2
],
&
count
,
NULL
)
!=
REDIS_OK
)
return
;
listRewind
(
server
.
slowlog
,
&
li
);
totentries
=
addDeferredMultiBulkLength
(
c
);
while
(
count
--
&&
(
ln
=
listNext
(
&
li
)))
{
int
j
;
se
=
ln
->
value
;
addReplyMultiBulkLen
(
c
,
4
);
addReplyLongLong
(
c
,
se
->
id
);
addReplyLongLong
(
c
,
se
->
time
);
addReplyLongLong
(
c
,
se
->
duration
);
addReplyMultiBulkLen
(
c
,
se
->
argc
);
for
(
j
=
0
;
j
<
se
->
argc
;
j
++
)
addReplyBulk
(
c
,
se
->
argv
[
j
]);
sent
++
;
}
setDeferredMultiBulkLength
(
c
,
totentries
,
sent
);
}
else
{
addReplyError
(
c
,
"Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN."
);
}
}
src/slowlog.h
0 → 100644
View file @
0681c5ad
/* This structure defines an entry inside the slow log list */
typedef
struct
slowlogEntry
{
robj
**
argv
;
int
argc
;
long
long
id
;
/* Unique entry identifier. */
long
long
duration
;
/* Time spent by the query, in nanoseconds. */
time_t
time
;
/* Unix time at which the query was executed. */
}
slowlogEntry
;
/* Exported API */
void
slowlogInit
(
void
);
void
slowlogPushEntryIfNeeded
(
robj
**
argv
,
int
argc
,
long
long
duration
);
/* Exported commands */
void
slowlogCommand
(
redisClient
*
c
);
src/t_list.c
View file @
0681c5ad
...
@@ -910,6 +910,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
...
@@ -910,6 +910,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
;
...
@@ -917,6 +918,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
...
@@ -917,6 +918,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
;
...
@@ -934,6 +936,7 @@ void blockingPopGenericCommand(redisClient *c, int where) {
...
@@ -934,6 +936,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
;
}
}
...
...
src/valgrind.sup
View file @
0681c5ad
...
@@ -3,3 +3,15 @@
...
@@ -3,3 +3,15 @@
Memcheck:Cond
Memcheck:Cond
fun:lzf_compress
fun:lzf_compress
}
}
{
<lzf_unitialized_hash_table>
Memcheck:Value4
fun:lzf_compress
}
{
<lzf_unitialized_hash_table>
Memcheck:Value8
fun:lzf_compress
}
src/zmalloc.c
View file @
0681c5ad
...
@@ -60,16 +60,13 @@
...
@@ -60,16 +60,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)
...
@@ -88,8 +85,6 @@
...
@@ -88,8 +85,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
"
,
...
@@ -190,11 +185,6 @@ size_t zmalloc_used_memory(void) {
...
@@ -190,11 +185,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
;
}
}
...
...
src/zmalloc.h
View file @
0681c5ad
...
@@ -75,8 +75,5 @@ size_t zmalloc_used_memory(void);
...
@@ -75,8 +75,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 */
tests/integration/aof.tcl
View file @
0681c5ad
...
@@ -32,6 +32,7 @@ tags {"aof"} {
...
@@ -32,6 +32,7 @@ tags {"aof"} {
start_server_aof
[
list dir $server_path
]
{
start_server_aof
[
list dir $server_path
]
{
test
"Unfinished MULTI: Server should not have been started"
{
test
"Unfinished MULTI: Server should not have been started"
{
if
{
$::valgrind
}
{
after 2000
}
assert_equal 0
[
is_alive $srv
]
assert_equal 0
[
is_alive $srv
]
}
}
...
@@ -49,6 +50,7 @@ tags {"aof"} {
...
@@ -49,6 +50,7 @@ tags {"aof"} {
start_server_aof
[
list dir $server_path
]
{
start_server_aof
[
list dir $server_path
]
{
test
"Short read: Server should not have been started"
{
test
"Short read: Server should not have been started"
{
if
{
$::valgrind
}
{
after 2000
}
assert_equal 0
[
is_alive $srv
]
assert_equal 0
[
is_alive $srv
]
}
}
...
@@ -101,4 +103,29 @@ tags {"aof"} {
...
@@ -101,4 +103,29 @@ 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
]
}
}
start_server
{
overrides
{
appendonly
{
yes
}
appendfilename
{
appendonly.aof
}}}
{
test
{
Redis should not try to convert DEL into EXPIREAT for EXPIRE -1
}
{
r set x 10
r expire x -1
}
}
}
}
tests/integration/replication-2.tcl
0 → 100644
View file @
0681c5ad
start_server
{
tags
{
"repl"
}}
{
start_server
{}
{
test
{
First server should have role slave after SLAVEOF
}
{
r -1 slaveof
[
srv 0 host
]
[
srv 0 port
]
after 1000
s -1 role
}
{
slave
}
test
{
MASTER and SLAVE dataset should be identical after complex ops
}
{
createComplexDataset r 10000
after 500
if
{[
r debug digest
]
ne
[
r -1 debug digest
]}
{
set csv1
[
csvdump r
]
set csv2
[
csvdump
{
r -1
}]
set fd
[
open /tmp/repldump1.txt w
]
puts -nonewline $fd $csv1
close $fd
set fd
[
open /tmp/repldump2.txt w
]
puts -nonewline $fd $csv2
close $fd
puts
"Master - Slave inconsistency"
puts
"Run diff -u against /tmp/repldump*.txt for more info"
}
assert_equal
[
r debug digest
]
[
r -1 debug digest
]
}
}
}
Prev
1
2
Next
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