Commit 77a7ec72 authored by antirez's avatar antirez
Browse files

Merge branch 'unstable' into 5.0 branch

parents 48dfd42d 4ff47a0b
...@@ -507,7 +507,7 @@ static int zslParseRange(robj *min, robj *max, zrangespec *spec) { ...@@ -507,7 +507,7 @@ static int zslParseRange(robj *min, robj *max, zrangespec *spec) {
* + means the max string possible * + means the max string possible
* *
* If the string is valid the *dest pointer is set to the redis object * If the string is valid the *dest pointer is set to the redis object
* that will be used for the comparision, and ex will be set to 0 or 1 * that will be used for the comparison, and ex will be set to 0 or 1
* respectively if the item is exclusive or inclusive. C_OK will be * respectively if the item is exclusive or inclusive. C_OK will be
* returned. * returned.
* *
......
...@@ -451,7 +451,7 @@ int string2ld(const char *s, size_t slen, long double *dp) { ...@@ -451,7 +451,7 @@ int string2ld(const char *s, size_t slen, long double *dp) {
/* Convert a double to a string representation. Returns the number of bytes /* Convert a double to a string representation. Returns the number of bytes
* required. The representation should always be parsable by strtod(3). * required. The representation should always be parsable by strtod(3).
* This function does not support human-friendly formatting like ld2string * This function does not support human-friendly formatting like ld2string
* does. It is intented mainly to be used inside t_zset.c when writing scores * does. It is intended mainly to be used inside t_zset.c when writing scores
* into a ziplist representing a sorted set. */ * into a ziplist representing a sorted set. */
int d2string(char *buf, size_t len, double value) { int d2string(char *buf, size_t len, double value) {
if (isnan(value)) { if (isnan(value)) {
......
...@@ -269,7 +269,7 @@ ...@@ -269,7 +269,7 @@
* Note that this is not how the data is actually encoded, is just what we * Note that this is not how the data is actually encoded, is just what we
* get filled by a function in order to operate more easily. */ * get filled by a function in order to operate more easily. */
typedef struct zlentry { typedef struct zlentry {
unsigned int prevrawlensize; /* Bytes used to encode the previos entry len*/ unsigned int prevrawlensize; /* Bytes used to encode the previous entry len*/
unsigned int prevrawlen; /* Previous entry len. */ unsigned int prevrawlen; /* Previous entry len. */
unsigned int lensize; /* Bytes used to encode this entry type/len. unsigned int lensize; /* Bytes used to encode this entry type/len.
For example strings have a 1, 2 or 5 bytes For example strings have a 1, 2 or 5 bytes
...@@ -431,7 +431,7 @@ unsigned int zipStorePrevEntryLength(unsigned char *p, unsigned int len) { ...@@ -431,7 +431,7 @@ unsigned int zipStorePrevEntryLength(unsigned char *p, unsigned int len) {
/* Return the length of the previous element, and the number of bytes that /* Return the length of the previous element, and the number of bytes that
* are used in order to encode the previous element length. * are used in order to encode the previous element length.
* 'ptr' must point to the prevlen prefix of an entry (that encodes the * 'ptr' must point to the prevlen prefix of an entry (that encodes the
* length of the previos entry in order to navigate the elements backward). * length of the previous entry in order to navigate the elements backward).
* The length of the previous entry is stored in 'prevlen', the number of * The length of the previous entry is stored in 'prevlen', the number of
* bytes needed to encode the previous entry length are stored in * bytes needed to encode the previous entry length are stored in
* 'prevlensize'. */ * 'prevlensize'. */
......
...@@ -165,7 +165,7 @@ void *zrealloc(void *ptr, size_t size) { ...@@ -165,7 +165,7 @@ void *zrealloc(void *ptr, size_t size) {
*((size_t*)newptr) = size; *((size_t*)newptr) = size;
update_zmalloc_stat_free(oldsize); update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(size); update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)newptr+PREFIX_SIZE; return (char*)newptr+PREFIX_SIZE;
#endif #endif
} }
...@@ -182,6 +182,9 @@ size_t zmalloc_size(void *ptr) { ...@@ -182,6 +182,9 @@ size_t zmalloc_size(void *ptr) {
if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1)); if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));
return size+PREFIX_SIZE; return size+PREFIX_SIZE;
} }
size_t zmalloc_usable(void *ptr) {
return zmalloc_usable(ptr)-PREFIX_SIZE;
}
#endif #endif
void zfree(void *ptr) { void zfree(void *ptr) {
...@@ -380,7 +383,7 @@ size_t zmalloc_get_private_dirty(long pid) { ...@@ -380,7 +383,7 @@ size_t zmalloc_get_private_dirty(long pid) {
} }
/* Returns the size of physical memory (RAM) in bytes. /* Returns the size of physical memory (RAM) in bytes.
* It looks ugly, but this is the cleanest way to achive cross platform results. * It looks ugly, but this is the cleanest way to achieve cross platform results.
* Cleaned up from: * Cleaned up from:
* *
* http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system * http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
......
...@@ -63,6 +63,11 @@ ...@@ -63,6 +63,11 @@
#ifndef ZMALLOC_LIB #ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc" #define ZMALLOC_LIB "libc"
#ifdef __GLIBC__
#include <malloc.h>
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_usable_size(p)
#endif
#endif #endif
/* We can enable the Redis defrag capabilities only if we are using Jemalloc /* We can enable the Redis defrag capabilities only if we are using Jemalloc
...@@ -93,6 +98,9 @@ void *zmalloc_no_tcache(size_t size); ...@@ -93,6 +98,9 @@ void *zmalloc_no_tcache(size_t size);
#ifndef HAVE_MALLOC_SIZE #ifndef HAVE_MALLOC_SIZE
size_t zmalloc_size(void *ptr); size_t zmalloc_size(void *ptr);
size_t zmalloc_usable(void *ptr);
#else
#define zmalloc_usable(p) zmalloc_size(p)
#endif #endif
#endif /* __ZMALLOC_H */ #endif /* __ZMALLOC_H */
...@@ -92,3 +92,80 @@ test "Node #10 should eventually replicate node #5" { ...@@ -92,3 +92,80 @@ test "Node #10 should eventually replicate node #5" {
fail "#10 didn't became slave of #5" fail "#10 didn't became slave of #5"
} }
} }
source "../tests/includes/init-tests.tcl"
# Create a cluster with 3 master and 15 slaves, so that we have 5
# slaves for eatch master.
test "Create a 3 nodes cluster" {
create_cluster 3 15
}
test "Cluster is up" {
assert_cluster_state ok
}
test "The first master has actually 5 slaves" {
assert {[llength [lindex [R 0 role] 2]] == 5}
}
test {Slaves of #0 are instance #3, #6, #9, #12 and #15 as expected} {
set port0 [get_instance_attrib redis 0 port]
assert {[lindex [R 3 role] 2] == $port0}
assert {[lindex [R 6 role] 2] == $port0}
assert {[lindex [R 9 role] 2] == $port0}
assert {[lindex [R 12 role] 2] == $port0}
assert {[lindex [R 15 role] 2] == $port0}
}
test {Instance #3, #6, #9, #12 and #15 synced with the master} {
wait_for_condition 1000 50 {
[RI 3 master_link_status] eq {up} &&
[RI 6 master_link_status] eq {up} &&
[RI 9 master_link_status] eq {up} &&
[RI 12 master_link_status] eq {up} &&
[RI 15 master_link_status] eq {up}
} else {
fail "Instance #3 or #6 or #9 or #12 or #15 master link status is not up"
}
}
proc master_detected {instances} {
foreach instance [dict keys $instances] {
if {[RI $instance role] eq {master}} {
return true
}
}
return false
}
test "New Master down consecutively" {
set instances [dict create 0 1 3 1 6 1 9 1 12 1 15 1]
set loops [expr {[dict size $instances]-1}]
for {set i 0} {$i < $loops} {incr i} {
set master_id -1
foreach instance [dict keys $instances] {
if {[RI $instance role] eq {master}} {
set master_id $instance
break;
}
}
if {$master_id eq -1} {
fail "no master detected, #loop $i"
}
set instances [dict remove $instances $master_id]
kill_instance redis $master_id
wait_for_condition 1000 50 {
[master_detected $instances]
} else {
failover "No failover detected when master $master_id fails"
}
assert_cluster_state ok
}
}
...@@ -39,6 +39,25 @@ start_server [list overrides [list "dir" $server_path]] { ...@@ -39,6 +39,25 @@ start_server [list overrides [list "dir" $server_path]] {
} {0000000000000000000000000000000000000000} } {0000000000000000000000000000000000000000}
} }
start_server [list overrides [list "dir" $server_path]] {
test {Test RDB stream encoding} {
for {set j 0} {$j < 1000} {incr j} {
if {rand() < 0.9} {
r xadd stream * foo $j
} else {
r xadd stream * bar $j
}
}
r xgroup create stream mygroup 0
r xreadgroup GROUP mygroup Alice COUNT 1 STREAMS stream >
set digest [r debug digest]
r debug reload
set newdigest [r debug digest]
assert {$digest eq $newdigest}
r del stream
}
}
# Helper function to start a server and kill it, just to check the error # Helper function to start a server and kill it, just to check the error
# logged. # logged.
set defaults {} set defaults {}
......
...@@ -11,7 +11,7 @@ proc stop_bg_complex_data {handle} { ...@@ -11,7 +11,7 @@ proc stop_bg_complex_data {handle} {
# partial resyncs attempts, all this while flooding the master with # partial resyncs attempts, all this while flooding the master with
# write queries. # write queries.
# #
# You can specifiy backlog size, ttl, delay before reconnection, test duration # You can specify backlog size, ttl, delay before reconnection, test duration
# in seconds, and an additional condition to verify at the end. # in seconds, and an additional condition to verify at the end.
# #
# If reconnect is > 0, the test actually try to break the connection and # If reconnect is > 0, the test actually try to break the connection and
......
...@@ -66,3 +66,13 @@ test "SDOWN is triggered by misconfigured instance repling with errors" { ...@@ -66,3 +66,13 @@ test "SDOWN is triggered by misconfigured instance repling with errors" {
R 0 bgsave R 0 bgsave
ensure_master_up ensure_master_up
} }
# We use this test setup to also test command renaming, as a side
# effect of the master going down if we send PONG instead of PING
test "SDOWN is triggered if we rename PING to PONG" {
ensure_master_up
S 4 SENTINEL SET mymaster rename-command PING PONG
ensure_master_down
S 4 SENTINEL SET mymaster rename-command PING PING
ensure_master_up
}
...@@ -276,6 +276,12 @@ proc start_server {options {code undefined}} { ...@@ -276,6 +276,12 @@ proc start_server {options {code undefined}} {
error_and_quit $config_file $line error_and_quit $config_file $line
} }
if {$::wait_server} {
set msg "server started PID: [dict get $srv "pid"]. press any key to continue..."
puts $msg
read stdin 1
}
while 1 { while 1 {
# check that the server actually started and is ready for connections # check that the server actually started and is ready for connections
if {[exec grep -i "Ready to accept" | wc -l < $stdout] > 0} { if {[exec grep -i "Ready to accept" | wc -l < $stdout] > 0} {
......
...@@ -375,3 +375,19 @@ proc start_write_load {host port seconds} { ...@@ -375,3 +375,19 @@ proc start_write_load {host port seconds} {
proc stop_write_load {handle} { proc stop_write_load {handle} {
catch {exec /bin/kill -9 $handle} catch {exec /bin/kill -9 $handle}
} }
proc K { x y } { set x }
# Shuffle a list. From Tcl wiki. Originally from Steve Cohen that improved
# other versions. Code should be under public domain.
proc lshuffle {list} {
set n [llength $list]
while {$n>0} {
set j [expr {int(rand()*$n)}]
lappend slist [lindex $list $j]
incr n -1
set temp [lindex $list $n]
set list [lreplace [K $list [set list {}]] $j $j $temp]
}
return $slist
}
...@@ -61,6 +61,7 @@ set ::all_tests { ...@@ -61,6 +61,7 @@ set ::all_tests {
unit/hyperloglog unit/hyperloglog
unit/lazyfree unit/lazyfree
unit/wait unit/wait
unit/pendingquerybuf
} }
# Index to the next test to run in the ::all_tests list. # Index to the next test to run in the ::all_tests list.
set ::next_test 0 set ::next_test 0
...@@ -82,6 +83,8 @@ set ::force_failure 0 ...@@ -82,6 +83,8 @@ set ::force_failure 0
set ::timeout 600; # 10 minutes without progresses will quit the test. set ::timeout 600; # 10 minutes without progresses will quit the test.
set ::last_progress [clock seconds] set ::last_progress [clock seconds]
set ::active_servers {} ; # Pids of active Redis instances. set ::active_servers {} ; # Pids of active Redis instances.
set ::dont_clean 0
set ::wait_server 0
# Set to 1 when we are running in client mode. The Redis test uses a # Set to 1 when we are running in client mode. The Redis test uses a
# server-client model to run tests simultaneously. The server instance # server-client model to run tests simultaneously. The server instance
...@@ -175,6 +178,9 @@ proc s {args} { ...@@ -175,6 +178,9 @@ proc s {args} {
} }
proc cleanup {} { proc cleanup {} {
if {$::dont_clean} {
return
}
if {!$::quiet} {puts -nonewline "Cleanup: may take some time... "} if {!$::quiet} {puts -nonewline "Cleanup: may take some time... "}
flush stdout flush stdout
catch {exec rm -rf {*}[glob tests/tmp/redis.conf.*]} catch {exec rm -rf {*}[glob tests/tmp/redis.conf.*]}
...@@ -224,6 +230,7 @@ proc test_server_cron {} { ...@@ -224,6 +230,7 @@ proc test_server_cron {} {
if {$elapsed > $::timeout} { if {$elapsed > $::timeout} {
set err "\[[colorstr red TIMEOUT]\]: clients state report follows." set err "\[[colorstr red TIMEOUT]\]: clients state report follows."
puts $err puts $err
lappend ::failed_tests $err
show_clients_state show_clients_state
kill_clients kill_clients
force_kill_all_servers force_kill_all_servers
...@@ -410,6 +417,8 @@ proc print_help_screen {} { ...@@ -410,6 +417,8 @@ proc print_help_screen {} {
"--clients <num> Number of test clients (default 16)." "--clients <num> Number of test clients (default 16)."
"--timeout <sec> Test timeout in seconds (default 10 min)." "--timeout <sec> Test timeout in seconds (default 10 min)."
"--force-failure Force the execution of a test that always fails." "--force-failure Force the execution of a test that always fails."
"--dont-clean don't delete redis log files after the run"
"--wait-server wait after server is started (so that you can attach a debugger)"
"--help Print this help screen." "--help Print this help screen."
} "\n"] } "\n"]
} }
...@@ -463,6 +472,10 @@ for {set j 0} {$j < [llength $argv]} {incr j} { ...@@ -463,6 +472,10 @@ for {set j 0} {$j < [llength $argv]} {incr j} {
} elseif {$opt eq {--clients}} { } elseif {$opt eq {--clients}} {
set ::numclients $arg set ::numclients $arg
incr j incr j
} elseif {$opt eq {--dont-clean}} {
set ::dont_clean 1
} elseif {$opt eq {--wait-server}} {
set ::wait_server 1
} elseif {$opt eq {--timeout}} { } elseif {$opt eq {--timeout}} {
set ::timeout $arg set ::timeout $arg
incr j incr j
......
...@@ -26,6 +26,39 @@ start_server {tags {"dump"}} { ...@@ -26,6 +26,39 @@ start_server {tags {"dump"}} {
r get foo r get foo
} {bar} } {bar}
test {RESTORE can set an absolute expire} {
r set foo bar
set encoded [r dump foo]
r del foo
set now [clock milliseconds]
r restore foo [expr $now+3000] $encoded absttl
set ttl [r pttl foo]
assert {$ttl >= 2998 && $ttl <= 3000}
r get foo
} {bar}
test {RESTORE can set LRU} {
r set foo bar
set encoded [r dump foo]
r del foo
r config set maxmemory-policy allkeys-lru
r restore foo 0 $encoded idletime 1000
set idle [r object idletime foo]
assert {$idle >= 1000 && $idle <= 1002}
r get foo
} {bar}
test {RESTORE can set LFU} {
r set foo bar
set encoded [r dump foo]
r del foo
r config set maxmemory-policy allkeys-lfu
r restore foo 0 $encoded freq 100
set freq [r object freq foo]
assert {$freq == 100}
r get foo
} {bar}
test {RESTORE returns an error of the key already exists} { test {RESTORE returns an error of the key already exists} {
r set foo bar r set foo bar
set e {} set e {}
...@@ -246,7 +279,7 @@ start_server {tags {"dump"}} { ...@@ -246,7 +279,7 @@ start_server {tags {"dump"}} {
set e set e
} {*empty string*} } {*empty string*}
test {MIGRATE with mutliple keys migrate just existing ones} { test {MIGRATE with multiple keys migrate just existing ones} {
set first [srv 0 client] set first [srv 0 client]
r set key1 "v1" r set key1 "v1"
r set key2 "v2" r set key2 "v2"
......
...@@ -121,7 +121,7 @@ start_server {tags {"expire"}} { ...@@ -121,7 +121,7 @@ start_server {tags {"expire"}} {
list $a $b list $a $b
} {somevalue {}} } {somevalue {}}
test {TTL returns tiem to live in seconds} { test {TTL returns time to live in seconds} {
r del x r del x
r setex x 10 somevalue r setex x 10 somevalue
set ttl [r ttl x] set ttl [r ttl x]
......
...@@ -142,3 +142,95 @@ start_server {tags {"maxmemory"}} { ...@@ -142,3 +142,95 @@ start_server {tags {"maxmemory"}} {
} }
} }
} }
proc test_slave_buffers {cmd_count payload_len limit_memory pipeline} {
start_server {tags {"maxmemory"}} {
start_server {} {
set slave [srv 0 client]
set slave_host [srv 0 host]
set slave_port [srv 0 port]
set master [srv -1 client]
set master_host [srv -1 host]
set master_port [srv -1 port]
# add 100 keys of 100k (10MB total)
for {set j 0} {$j < 100} {incr j} {
$master setrange "key:$j" 100000 asdf
}
$master config set maxmemory-policy allkeys-random
$master config set client-output-buffer-limit "slave 100000000 100000000 60"
$master config set repl-backlog-size [expr {10*1024}]
$slave slaveof $master_host $master_port
wait_for_condition 50 100 {
[s 0 master_link_status] eq {up}
} else {
fail "Replication not started."
}
# measure used memory after the slave connected and set maxmemory
set orig_used [s -1 used_memory]
set orig_client_buf [s -1 mem_clients_normal]
set orig_mem_not_counted_for_evict [s -1 mem_not_counted_for_evict]
set orig_used_no_repl [expr {$orig_used - $orig_mem_not_counted_for_evict}]
set limit [expr {$orig_used - $orig_mem_not_counted_for_evict + 20*1024}]
if {$limit_memory==1} {
$master config set maxmemory $limit
}
# put the slave to sleep
set rd_slave [redis_deferring_client]
$rd_slave debug sleep 60
# send some 10mb woth of commands that don't increase the memory usage
if {$pipeline == 1} {
set rd_master [redis_deferring_client -1]
for {set k 0} {$k < $cmd_count} {incr k} {
$rd_master setrange key:0 0 [string repeat A $payload_len]
}
for {set k 0} {$k < $cmd_count} {incr k} {
#$rd_master read
}
} else {
for {set k 0} {$k < $cmd_count} {incr k} {
$master setrange key:0 0 [string repeat A $payload_len]
}
}
set new_used [s -1 used_memory]
set slave_buf [s -1 mem_clients_slaves]
set client_buf [s -1 mem_clients_normal]
set mem_not_counted_for_evict [s -1 mem_not_counted_for_evict]
set used_no_repl [expr {$new_used - $mem_not_counted_for_evict}]
set delta [expr {($used_no_repl - $client_buf) - ($orig_used_no_repl - $orig_client_buf)}]
assert {[$master dbsize] == 100}
assert {$slave_buf > 2*1024*1024} ;# some of the data may have been pushed to the OS buffers
assert {$delta < 50*1024 && $delta > -50*1024} ;# 1 byte unaccounted for, with 1M commands will consume some 1MB
$master client kill type slave
set killed_used [s -1 used_memory]
set killed_slave_buf [s -1 mem_clients_slaves]
set killed_mem_not_counted_for_evict [s -1 mem_not_counted_for_evict]
set killed_used_no_repl [expr {$killed_used - $killed_mem_not_counted_for_evict}]
set delta_no_repl [expr {$killed_used_no_repl - $used_no_repl}]
assert {$killed_slave_buf == 0}
assert {$delta_no_repl > -50*1024 && $delta_no_repl < 50*1024} ;# 1 byte unaccounted for, with 1M commands will consume some 1MB
}
}
}
test {slave buffer are counted correctly} {
# we wanna use many small commands, and we don't wanna wait long
# so we need to use a pipeline (redis_deferring_client)
# that may cause query buffer to fill and induce eviction, so we disable it
test_slave_buffers 1000000 10 0 1
}
test {slave buffer don't induce eviction} {
# test again with fewer (and bigger) commands without pipeline, but with eviction
test_slave_buffers 100000 100 1 0
}
...@@ -41,7 +41,7 @@ start_server {tags {"defrag"}} { ...@@ -41,7 +41,7 @@ start_server {tags {"defrag"}} {
test "Active defrag" { test "Active defrag" {
r config set activedefrag no r config set activedefrag no
r config set active-defrag-threshold-lower 5 r config set active-defrag-threshold-lower 5
r config set active-defrag-cycle-min 25 r config set active-defrag-cycle-min 65
r config set active-defrag-cycle-max 75 r config set active-defrag-cycle-max 75
r config set active-defrag-ignore-bytes 2mb r config set active-defrag-ignore-bytes 2mb
r config set maxmemory 100mb r config set maxmemory 100mb
...@@ -66,9 +66,10 @@ start_server {tags {"defrag"}} { ...@@ -66,9 +66,10 @@ start_server {tags {"defrag"}} {
} }
# Wait for the active defrag to stop working. # Wait for the active defrag to stop working.
wait_for_condition 100 100 { wait_for_condition 150 100 {
[s active_defrag_running] eq 0 [s active_defrag_running] eq 0
} else { } else {
after 120 ;# serverCron only updates the info once in 100ms
puts [r info memory] puts [r info memory]
puts [r memory malloc-stats] puts [r memory malloc-stats]
fail "defrag didn't stop." fail "defrag didn't stop."
...@@ -97,10 +98,15 @@ start_server {tags {"defrag"}} { ...@@ -97,10 +98,15 @@ start_server {tags {"defrag"}} {
r config set active-defrag-ignore-bytes 2mb r config set active-defrag-ignore-bytes 2mb
r config set maxmemory 0 r config set maxmemory 0
r config set list-max-ziplist-size 5 ;# list of 10k items will have 2000 quicklist nodes r config set list-max-ziplist-size 5 ;# list of 10k items will have 2000 quicklist nodes
r config set stream-node-max-entries 5
r hmset hash h1 v1 h2 v2 h3 v3 r hmset hash h1 v1 h2 v2 h3 v3
r lpush list a b c d r lpush list a b c d
r zadd zset 0 a 1 b 2 c 3 d r zadd zset 0 a 1 b 2 c 3 d
r sadd set a b c d r sadd set a b c d
r xadd stream * item 1 value a
r xadd stream * item 2 value b
r xgroup create stream mygroup 0
r xreadgroup GROUP mygroup Alice COUNT 1 STREAMS stream >
# create big keys with 10k items # create big keys with 10k items
set rd [redis_deferring_client] set rd [redis_deferring_client]
...@@ -109,8 +115,9 @@ start_server {tags {"defrag"}} { ...@@ -109,8 +115,9 @@ start_server {tags {"defrag"}} {
$rd lpush biglist [concat "asdfasdfasdf" $j] $rd lpush biglist [concat "asdfasdfasdf" $j]
$rd zadd bigzset $j [concat "asdfasdfasdf" $j] $rd zadd bigzset $j [concat "asdfasdfasdf" $j]
$rd sadd bigset [concat "asdfasdfasdf" $j] $rd sadd bigset [concat "asdfasdfasdf" $j]
$rd xadd bigstream * item 1 value a
} }
for {set j 0} {$j < 40000} {incr j} { for {set j 0} {$j < 50000} {incr j} {
$rd read ; # Discard replies $rd read ; # Discard replies
} }
...@@ -134,7 +141,7 @@ start_server {tags {"defrag"}} { ...@@ -134,7 +141,7 @@ start_server {tags {"defrag"}} {
for {set j 0} {$j < 500000} {incr j} { for {set j 0} {$j < 500000} {incr j} {
$rd read ; # Discard replies $rd read ; # Discard replies
} }
assert {[r dbsize] == 500008} assert {[r dbsize] == 500010}
# create some fragmentation # create some fragmentation
for {set j 0} {$j < 500000} {incr j 2} { for {set j 0} {$j < 500000} {incr j 2} {
...@@ -143,7 +150,7 @@ start_server {tags {"defrag"}} { ...@@ -143,7 +150,7 @@ start_server {tags {"defrag"}} {
for {set j 0} {$j < 500000} {incr j 2} { for {set j 0} {$j < 500000} {incr j 2} {
$rd read ; # Discard replies $rd read ; # Discard replies
} }
assert {[r dbsize] == 250008} assert {[r dbsize] == 250010}
# start defrag # start defrag
after 120 ;# serverCron only updates the info once in 100ms after 120 ;# serverCron only updates the info once in 100ms
...@@ -155,6 +162,7 @@ start_server {tags {"defrag"}} { ...@@ -155,6 +162,7 @@ start_server {tags {"defrag"}} {
r config set latency-monitor-threshold 5 r config set latency-monitor-threshold 5
r latency reset r latency reset
set digest [r debug digest]
catch {r config set activedefrag yes} e catch {r config set activedefrag yes} e
if {![string match {DISABLED*} $e]} { if {![string match {DISABLED*} $e]} {
# wait for the active defrag to start working (decision once a second) # wait for the active defrag to start working (decision once a second)
...@@ -168,6 +176,7 @@ start_server {tags {"defrag"}} { ...@@ -168,6 +176,7 @@ start_server {tags {"defrag"}} {
wait_for_condition 500 100 { wait_for_condition 500 100 {
[s active_defrag_running] eq 0 [s active_defrag_running] eq 0
} else { } else {
after 120 ;# serverCron only updates the info once in 100ms
puts [r info memory] puts [r info memory]
puts [r memory malloc-stats] puts [r memory malloc-stats]
fail "defrag didn't stop." fail "defrag didn't stop."
...@@ -193,9 +202,11 @@ start_server {tags {"defrag"}} { ...@@ -193,9 +202,11 @@ start_server {tags {"defrag"}} {
# due to high fragmentation, 10hz, and active-defrag-cycle-max set to 75, # due to high fragmentation, 10hz, and active-defrag-cycle-max set to 75,
# we expect max latency to be not much higher than 75ms # we expect max latency to be not much higher than 75ms
assert {$max_latency <= 80} assert {$max_latency <= 80}
} else {
set _ ""
} }
} {} # verify the data isn't corrupted or changed
set newdigest [r debug digest]
assert {$digest eq $newdigest}
r save ;# saving an rdb iterates over all the data / pointers
} {OK}
} }
} }
proc info_memory {r property} {
if {[regexp "\r\n$property:(.*?)\r\n" [{*}$r info memory] _ value]} {
set _ $value
}
}
proc prepare_value {size} {
set _v "c"
for {set i 1} {$i < $size} {incr i} {
append _v 0
}
return $_v
}
start_server {tags {"wait"}} {
start_server {} {
set slave [srv 0 client]
set slave_host [srv 0 host]
set slave_port [srv 0 port]
set master [srv -1 client]
set master_host [srv -1 host]
set master_port [srv -1 port]
test "pending querybuf: check size of pending_querybuf after set a big value" {
$slave slaveof $master_host $master_port
set _v [prepare_value [expr 32*1024*1024]]
$master set key $_v
after 2000
set m_usedmemory [info_memory $master used_memory]
set s_usedmemory [info_memory $slave used_memory]
if { $s_usedmemory > $m_usedmemory + 10*1024*1024 } {
fail "the used_memory of slave is too larger than master.Master:$m_usedmemory Slave:$s_usedmemory"
}
}
}}
...@@ -246,7 +246,7 @@ start_server {tags {"scan"}} { ...@@ -246,7 +246,7 @@ start_server {tags {"scan"}} {
array set found {} array set found {}
# Populate the set # Populate the set
set numele [expr {100+[randomInt 1000]}] set numele [expr {101+[randomInt 1000]}]
for {set j 0} {$j < $numele} {incr j} { for {set j 0} {$j < $numele} {incr j} {
r sadd set $j r sadd set $j
if {$j >= 100} { if {$j >= 100} {
......
...@@ -517,7 +517,7 @@ start_server {tags {"scripting"}} { ...@@ -517,7 +517,7 @@ start_server {tags {"scripting"}} {
# Note: keep this test at the end of this server stanza because it # Note: keep this test at the end of this server stanza because it
# kills the server. # kills the server.
test {SHUTDOWN NOSAVE can kill a timedout script anyway} { test {SHUTDOWN NOSAVE can kill a timedout script anyway} {
# The server sould be still unresponding to normal commands. # The server could be still unresponding to normal commands.
catch {r ping} e catch {r ping} e
assert_match {BUSY*} $e assert_match {BUSY*} $e
catch {r shutdown nosave} catch {r shutdown nosave}
......
...@@ -78,4 +78,14 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} { ...@@ -78,4 +78,14 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} {
set e [lindex [r slowlog get] 0] set e [lindex [r slowlog get] 0]
assert_equal {lastentry_client} [lindex $e 5] assert_equal {lastentry_client} [lindex $e 5]
} }
test {SLOWLOG - can be disabled} {
r config set slowlog-log-slower-than 1
r slowlog reset
assert_equal [r slowlog len] 1
r config set slowlog-log-slower-than -1
r slowlog reset
r debug sleep 0.2
assert_equal [r slowlog len] 0
}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment