networking.c/writeToClient: handle WSAEWOULDBLOCK

- fixed writeToClient() after failed tests
- adjusted tests to match antirez/redis@4.0.2
This commit is contained in:
Tomasz Poradowski
2018-08-02 00:31:59 +02:00
parent 155111f7e4
commit bdcf80ea4e
30 changed files with 770 additions and 131 deletions
+2 -3
View File
@@ -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"}
}
}
+78
View File
@@ -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"
}
}
}}}
+182
View File
@@ -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}
}
}}}}}
+3 -5
View File
@@ -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 -12
View File
@@ -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]
}
}
+12 -4
View File
@@ -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}
}
}
+3 -2
View File
@@ -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
+7 -20
View File
@@ -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}
}
}
}