networking.c/writeToClient: handle WSAEWOULDBLOCK
- fixed writeToClient() after failed tests - adjusted tests to match antirez/redis@4.0.2
This commit is contained in:
@@ -69,10 +69,9 @@ tags {"aof"} {
|
||||
assert_equal 1 [is_alive $srv]
|
||||
}
|
||||
|
||||
test "Truncated AOF loaded: we expect foo to be equal to 6 now" {
|
||||
assert_equal 1 [is_alive $srv]
|
||||
set client [redis [dict get $srv host] [dict get $srv port]]
|
||||
|
||||
set client [redis [dict get $srv host] [dict get $srv port]]
|
||||
test "Truncated AOF loaded: we expect foo to be equal to 6 now" {
|
||||
assert {[$client get foo] eq "6"}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# Issue 3899 regression test.
|
||||
# We create a chain of three instances: master -> slave -> slave2
|
||||
# and continuously break the link while traffic is generated by
|
||||
# redis-benchmark. At the end we check that the data is the same
|
||||
# everywhere.
|
||||
|
||||
start_server {tags {"psync2"}} {
|
||||
start_server {} {
|
||||
start_server {} {
|
||||
# Config
|
||||
set debug_msg 0 ; # Enable additional debug messages
|
||||
|
||||
set no_exit 0 ; # Do not exit at end of the test
|
||||
|
||||
set duration 20 ; # Total test seconds
|
||||
|
||||
for {set j 0} {$j < 3} {incr j} {
|
||||
set R($j) [srv [expr 0-$j] client]
|
||||
set R_host($j) [srv [expr 0-$j] host]
|
||||
set R_port($j) [srv [expr 0-$j] port]
|
||||
if {$debug_msg} {puts "Log file: [srv [expr 0-$j] stdout]"}
|
||||
}
|
||||
|
||||
# Setup the replication and backlog parameters
|
||||
test "PSYNC2 #3899 regression: setup" {
|
||||
$R(1) slaveof $R_host(0) $R_port(0)
|
||||
$R(2) slaveof $R_host(0) $R_port(0)
|
||||
$R(0) set foo bar
|
||||
wait_for_condition 50 1000 {
|
||||
[$R(1) dbsize] == 1 && [$R(2) dbsize] == 1
|
||||
} else {
|
||||
fail "Slaves not replicating from master"
|
||||
}
|
||||
$R(0) config set repl-backlog-size 10mb
|
||||
$R(1) config set repl-backlog-size 10mb
|
||||
}
|
||||
|
||||
set cycle_start_time [clock milliseconds]
|
||||
set bench_pid [exec src/redis-benchmark -p $R_port(0) -n 10000000 -r 1000 incr __rand_int__ > /dev/null &]
|
||||
while 1 {
|
||||
set elapsed [expr {[clock milliseconds]-$cycle_start_time}]
|
||||
if {$elapsed > $duration*1000} break
|
||||
if {rand() < .05} {
|
||||
test "PSYNC2 #3899 regression: kill first slave" {
|
||||
$R(1) client kill type master
|
||||
}
|
||||
}
|
||||
if {rand() < .05} {
|
||||
test "PSYNC2 #3899 regression: kill chained slave" {
|
||||
$R(2) client kill type master
|
||||
}
|
||||
}
|
||||
after 100
|
||||
}
|
||||
exec kill -9 $bench_pid
|
||||
|
||||
if {$debug_msg} {
|
||||
for {set j 0} {$j < 100} {incr j} {
|
||||
if {
|
||||
[$R(0) debug digest] == [$R(1) debug digest] &&
|
||||
[$R(1) debug digest] == [$R(2) debug digest]
|
||||
} break
|
||||
puts [$R(0) debug digest]
|
||||
puts [$R(1) debug digest]
|
||||
puts [$R(2) debug digest]
|
||||
after 1000
|
||||
}
|
||||
}
|
||||
|
||||
test "PSYNC2 #3899 regression: verify consistency" {
|
||||
wait_for_condition 50 1000 {
|
||||
([$R(0) debug digest] eq [$R(1) debug digest]) &&
|
||||
([$R(1) debug digest] eq [$R(2) debug digest])
|
||||
} else {
|
||||
fail "The three instances have different data sets"
|
||||
}
|
||||
}
|
||||
}}}
|
||||
@@ -0,0 +1,182 @@
|
||||
start_server {tags {"psync2"}} {
|
||||
start_server {} {
|
||||
start_server {} {
|
||||
start_server {} {
|
||||
start_server {} {
|
||||
set master_id 0 ; # Current master
|
||||
set start_time [clock seconds] ; # Test start time
|
||||
set counter_value 0 ; # Current value of the Redis counter "x"
|
||||
|
||||
# Config
|
||||
set debug_msg 0 ; # Enable additional debug messages
|
||||
|
||||
set no_exit 0; ; # Do not exit at end of the test
|
||||
|
||||
set duration 20 ; # Total test seconds
|
||||
|
||||
set genload 1 ; # Load master with writes at every cycle
|
||||
|
||||
set genload_time 5000 ; # Writes duration time in ms
|
||||
|
||||
set disconnect 1 ; # Break replication link between random
|
||||
# master and slave instances while the
|
||||
# master is loaded with writes.
|
||||
|
||||
set disconnect_period 1000 ; # Disconnect repl link every N ms.
|
||||
|
||||
for {set j 0} {$j < 5} {incr j} {
|
||||
set R($j) [srv [expr 0-$j] client]
|
||||
set R_host($j) [srv [expr 0-$j] host]
|
||||
set R_port($j) [srv [expr 0-$j] port]
|
||||
if {$debug_msg} {puts "Log file: [srv [expr 0-$j] stdout]"}
|
||||
}
|
||||
|
||||
set cycle 1
|
||||
while {([clock seconds]-$start_time) < $duration} {
|
||||
test "PSYNC2: --- CYCLE $cycle ---" {
|
||||
incr cycle
|
||||
}
|
||||
|
||||
# Create a random replication layout.
|
||||
# Start with switching master (this simulates a failover).
|
||||
|
||||
# 1) Select the new master.
|
||||
set master_id [randomInt 5]
|
||||
set used [list $master_id]
|
||||
test "PSYNC2: \[NEW LAYOUT\] Set #$master_id as master" {
|
||||
$R($master_id) slaveof no one
|
||||
if {$counter_value == 0} {
|
||||
$R($master_id) set x $counter_value
|
||||
}
|
||||
}
|
||||
|
||||
# 2) Attach all the slaves to a random instance
|
||||
while {[llength $used] != 5} {
|
||||
while 1 {
|
||||
set slave_id [randomInt 5]
|
||||
if {[lsearch -exact $used $slave_id] == -1} break
|
||||
}
|
||||
set rand [randomInt [llength $used]]
|
||||
set mid [lindex $used $rand]
|
||||
set master_host $R_host($mid)
|
||||
set master_port $R_port($mid)
|
||||
|
||||
test "PSYNC2: Set #$slave_id to replicate from #$mid" {
|
||||
$R($slave_id) slaveof $master_host $master_port
|
||||
}
|
||||
lappend used $slave_id
|
||||
}
|
||||
|
||||
# 3) Increment the counter and wait for all the instances
|
||||
# to converge.
|
||||
test "PSYNC2: cluster is consistent after failover" {
|
||||
$R($master_id) incr x; incr counter_value
|
||||
for {set j 0} {$j < 5} {incr j} {
|
||||
wait_for_condition 50 1000 {
|
||||
[$R($j) get x] == $counter_value
|
||||
} else {
|
||||
fail "Instance #$j x variable is inconsistent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 4) Generate load while breaking the connection of random
|
||||
# slave-master pairs.
|
||||
test "PSYNC2: generate load while killing replication links" {
|
||||
set t [clock milliseconds]
|
||||
set next_break [expr {$t+$disconnect_period}]
|
||||
while {[clock milliseconds]-$t < $genload_time} {
|
||||
if {$genload} {
|
||||
$R($master_id) incr x; incr counter_value
|
||||
}
|
||||
if {[clock milliseconds] == $next_break} {
|
||||
set next_break \
|
||||
[expr {[clock milliseconds]+$disconnect_period}]
|
||||
set slave_id [randomInt 5]
|
||||
if {$disconnect} {
|
||||
$R($slave_id) client kill type master
|
||||
if {$debug_msg} {
|
||||
puts "+++ Breaking link for slave #$slave_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 5) Increment the counter and wait for all the instances
|
||||
set x [$R($master_id) get x]
|
||||
test "PSYNC2: cluster is consistent after load (x = $x)" {
|
||||
for {set j 0} {$j < 5} {incr j} {
|
||||
wait_for_condition 50 1000 {
|
||||
[$R($j) get x] == $counter_value
|
||||
} else {
|
||||
fail "Instance #$j x variable is inconsistent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Put down the old master so that it cannot generate more
|
||||
# replication stream, this way in the next master switch, the time at
|
||||
# which we move slaves away is not important, each will have full
|
||||
# history (otherwise PINGs will make certain slaves have more history),
|
||||
# and sometimes a full resync will be needed.
|
||||
$R($master_id) slaveof 127.0.0.1 0 ;# We use port zero to make it fail.
|
||||
|
||||
if {$debug_msg} {
|
||||
for {set j 0} {$j < 5} {incr j} {
|
||||
puts "$j: sync_full: [status $R($j) sync_full]"
|
||||
puts "$j: id1 : [status $R($j) master_replid]:[status $R($j) master_repl_offset]"
|
||||
puts "$j: id2 : [status $R($j) master_replid2]:[status $R($j) second_repl_offset]"
|
||||
puts "$j: backlog : firstbyte=[status $R($j) repl_backlog_first_byte_offset] len=[status $R($j) repl_backlog_histlen]"
|
||||
puts "---"
|
||||
}
|
||||
}
|
||||
|
||||
test "PSYNC2: total sum of full synchronizations is exactly 4" {
|
||||
set sum 0
|
||||
for {set j 0} {$j < 5} {incr j} {
|
||||
incr sum [status $R($j) sync_full]
|
||||
}
|
||||
assert {$sum == 4}
|
||||
}
|
||||
}
|
||||
|
||||
test "PSYNC2: Bring the master back again for next test" {
|
||||
$R($master_id) slaveof no one
|
||||
set master_host $R_host($master_id)
|
||||
set master_port $R_port($master_id)
|
||||
for {set j 0} {$j < 5} {incr j} {
|
||||
if {$j == $master_id} continue
|
||||
$R($j) slaveof $master_host $master_port
|
||||
}
|
||||
|
||||
# Wait for slaves to sync
|
||||
wait_for_condition 50 1000 {
|
||||
[status $R($master_id) connected_slaves] == 4
|
||||
} else {
|
||||
fail "Slave not reconnecting"
|
||||
}
|
||||
}
|
||||
|
||||
test "PSYNC2: Partial resync after restart using RDB aux fields" {
|
||||
# Pick a random slave
|
||||
set slave_id [expr {($master_id+1)%5}]
|
||||
set sync_count [status $R($master_id) sync_full]
|
||||
catch {
|
||||
$R($slave_id) config rewrite
|
||||
$R($slave_id) debug restart
|
||||
}
|
||||
wait_for_condition 50 1000 {
|
||||
[status $R($master_id) connected_slaves] == 4
|
||||
} else {
|
||||
fail "Slave not reconnecting"
|
||||
}
|
||||
set new_sync_count [status $R($master_id) sync_full]
|
||||
assert {$sync_count == $new_sync_count}
|
||||
}
|
||||
|
||||
if {$no_exit} {
|
||||
while 1 { puts -nonewline .; flush stdout; after 1000}
|
||||
}
|
||||
|
||||
}}}}}
|
||||
@@ -50,7 +50,6 @@ proc start_server_and_kill_it {overrides code} {
|
||||
kill_server $srv
|
||||
}
|
||||
|
||||
if { $::tcl_platform(platform) != "windows" } {
|
||||
# Make the RDB file unreadable
|
||||
file attributes [file join $server_path dump.rdb] -permissions 0222
|
||||
|
||||
@@ -67,7 +66,7 @@ if {!$isroot} {
|
||||
test {Server should not start if RDB file can't be open} {
|
||||
wait_for_condition 50 100 {
|
||||
[string match {*Fatal error loading*} \
|
||||
[exec tail -n1 < [dict get $srv stdout]]]
|
||||
[exec tail -1 < [dict get $srv stdout]]]
|
||||
} else {
|
||||
fail "Server started even if RDB was unreadable!"
|
||||
}
|
||||
@@ -90,11 +89,10 @@ close $fd
|
||||
start_server_and_kill_it [list "dir" $server_path] {
|
||||
test {Server should not start if RDB is corrupted} {
|
||||
wait_for_condition 50 100 {
|
||||
[string match {*RDB checksum*} \
|
||||
[exec tail -n10 < [dict get $srv stdout]]]
|
||||
[string match {*CRC error*} \
|
||||
[exec tail -10 < [dict get $srv stdout]]]
|
||||
} else {
|
||||
fail "Server started even if RDB was corrupted!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,7 @@ start_server {tags {"repl"}} {
|
||||
start_server {} {
|
||||
test {First server should have role slave after SLAVEOF} {
|
||||
r -1 slaveof [srv 0 host] [srv 0 port]
|
||||
if { $::tcl_platform(platform) == "windows" } {
|
||||
after 2000
|
||||
} else {
|
||||
after 1000
|
||||
}
|
||||
after 1000
|
||||
s -1 role
|
||||
} {slave}
|
||||
|
||||
@@ -14,9 +10,7 @@ start_server {tags {"repl"}} {
|
||||
r config set min-slaves-to-write 1
|
||||
r config set min-slaves-max-lag 10
|
||||
r set foo 12345
|
||||
|
||||
#WIN_PORT_FIX 'wait_for_condition 50 100' -> 'wait_for_condition 50 250'
|
||||
wait_for_condition 50 250 {
|
||||
wait_for_condition 50 100 {
|
||||
[r -1 get foo] eq {12345}
|
||||
} else {
|
||||
fail "Write did not reached slave"
|
||||
@@ -75,9 +69,6 @@ start_server {tags {"repl"}} {
|
||||
test {MASTER and SLAVE dataset should be identical after complex ops} {
|
||||
createComplexDataset r 10000
|
||||
after 500
|
||||
wait_for_condition 50 100 {
|
||||
[r debug digest] eq [r -1 debug digest]
|
||||
} else {
|
||||
if {[r debug digest] ne [r -1 debug digest]} {
|
||||
set csv1 [csvdump r]
|
||||
set csv2 [csvdump {r -1}]
|
||||
@@ -90,7 +81,6 @@ start_server {tags {"repl"}} {
|
||||
puts "Master - Slave inconsistency"
|
||||
puts "Run diff -u against /tmp/repldump*.txt for more info"
|
||||
}
|
||||
}
|
||||
assert_equal [r debug digest] [r -1 debug digest]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@ start_server {tags {"repl"}} {
|
||||
after 4000 ;# Make sure everything expired before taking the digest
|
||||
r keys * ;# Force DEL syntesizing to slave
|
||||
after 1000 ;# Wait another second. Now everything should be fine.
|
||||
wait_for_condition 50 100 {
|
||||
[r debug digest] eq [r -1 debug digest]
|
||||
} else {
|
||||
if {[r debug digest] ne [r -1 debug digest]} {
|
||||
set csv1 [csvdump r]
|
||||
set csv2 [csvdump {r -1}]
|
||||
@@ -31,9 +28,20 @@ start_server {tags {"repl"}} {
|
||||
puts "Master - Slave inconsistency"
|
||||
puts "Run diff -u against /tmp/repldump*.txt for more info"
|
||||
}
|
||||
}
|
||||
assert_equal [r debug digest] [r -1 debug digest]
|
||||
}
|
||||
|
||||
test {Slave is able to evict keys created in writable slaves} {
|
||||
r -1 select 5
|
||||
assert {[r -1 dbsize] == 0}
|
||||
r -1 config set slave-read-only no
|
||||
r -1 set key1 1 ex 5
|
||||
r -1 set key2 2 ex 5
|
||||
r -1 set key3 3 ex 5
|
||||
assert {[r -1 dbsize] == 3}
|
||||
after 6000
|
||||
r -1 dbsize
|
||||
} {0}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ proc test_psync {descr duration backlog_size backlog_ttl delay cond diskless rec
|
||||
|
||||
# Check that the background clients are actually writing.
|
||||
test {Detect write load to master} {
|
||||
wait_for_condition 50 100 {
|
||||
wait_for_condition 50 1000 {
|
||||
[$master dbsize] > 100
|
||||
} else {
|
||||
fail "Can't detect write load from background clients."
|
||||
@@ -90,6 +90,7 @@ proc test_psync {descr duration backlog_size backlog_ttl delay cond diskless rec
|
||||
incr retry -1
|
||||
}
|
||||
assert {[$master dbsize] > 0}
|
||||
|
||||
if {[$master debug digest] ne [$slave debug digest]} {
|
||||
set csv1 [csvdump r]
|
||||
set csv2 [csvdump {r -1}]
|
||||
@@ -127,7 +128,7 @@ foreach diskless {no yes} {
|
||||
test_psync {no reconnection, just sync} 6 1000000 3600 0 {
|
||||
} $diskless 0
|
||||
|
||||
test_psync {ok psync} 6 1000000 3600 0 {
|
||||
test_psync {ok psync} 6 100000000 3600 0 {
|
||||
assert {[s -1 sync_partial_ok] > 0}
|
||||
} $diskless 1
|
||||
|
||||
|
||||
@@ -243,9 +243,7 @@ foreach dl {no yes} {
|
||||
|
||||
# Make sure that slaves and master have same
|
||||
# number of keys
|
||||
|
||||
#WIN_PORT_FIX 'wait_for_condition 500 100' -> 'wait_for_condition 200 250'
|
||||
wait_for_condition 200 250 {
|
||||
wait_for_condition 500 100 {
|
||||
[$master dbsize] == [[lindex $slaves 0] dbsize] &&
|
||||
[$master dbsize] == [[lindex $slaves 1] dbsize] &&
|
||||
[$master dbsize] == [[lindex $slaves 2] dbsize]
|
||||
@@ -255,24 +253,13 @@ foreach dl {no yes} {
|
||||
|
||||
# Check digests
|
||||
set digest [$master debug digest]
|
||||
set digest0 [[lindex $slaves 0] debug digest]
|
||||
set digest1 [[lindex $slaves 1] debug digest]
|
||||
set digest2 [[lindex $slaves 2] debug digest]
|
||||
assert {$digest ne 0000000000000000000000000000000000000000}
|
||||
|
||||
if { $::tcl_platform(platform) == "windows" } {
|
||||
wait_for_condition 200 250 {
|
||||
$digest eq [[lindex $slaves 0] debug digest] &&
|
||||
$digest eq [[lindex $slaves 1] debug digest] &&
|
||||
$digest eq [[lindex $slaves 2] debug digest]
|
||||
} else {
|
||||
fail "slave digest not equal to master digest"
|
||||
}
|
||||
} else {
|
||||
set digest0 [[lindex $slaves 0] debug digest]
|
||||
set digest1 [[lindex $slaves 1] debug digest]
|
||||
set digest2 [[lindex $slaves 2] debug digest]
|
||||
assert {$digest eq $digest0}
|
||||
assert {$digest eq $digest1}
|
||||
assert {$digest eq $digest2}
|
||||
}
|
||||
assert {$digest eq $digest0}
|
||||
assert {$digest eq $digest1}
|
||||
assert {$digest eq $digest2}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user