123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- proc log_file_matches {log pattern} {
- set fp [open $log r]
- set content [read $fp]
- close $fp
- string match $pattern $content
- }
- start_server {tags {"repl"}} {
- set slave [srv 0 client]
- set slave_host [srv 0 host]
- set slave_port [srv 0 port]
- set slave_log [srv 0 stdout]
- start_server {} {
- set master [srv 0 client]
- set master_host [srv 0 host]
- set master_port [srv 0 port]
- # Configure the master in order to hang waiting for the BGSAVE
- # operation, so that the slave remains in the handshake state.
- $master config set repl-diskless-sync yes
- $master config set repl-diskless-sync-delay 1000
- # Use a short replication timeout on the slave, so that if there
- # are no bugs the timeout is triggered in a reasonable amount
- # of time.
- $slave config set repl-timeout 5
- # Start the replication process...
- $slave slaveof $master_host $master_port
- test {Slave enters handshake} {
- wait_for_condition 50 1000 {
- [string match *handshake* [$slave role]]
- } else {
- fail "Slave does not enter handshake state"
- }
- }
- # But make the master unable to send
- # the periodic newlines to refresh the connection. The slave
- # should detect the timeout.
- $master debug sleep 10
- test {Slave is able to detect timeout during handshake} {
- wait_for_condition 50 1000 {
- [log_file_matches $slave_log "*Timeout connecting to the MASTER*"]
- } else {
- fail "Slave is not able to detect timeout"
- }
- }
- }
- }
- start_server {tags {"repl"}} {
- set A [srv 0 client]
- set A_host [srv 0 host]
- set A_port [srv 0 port]
- start_server {} {
- set B [srv 0 client]
- set B_host [srv 0 host]
- set B_port [srv 0 port]
- test {Set instance A as slave of B} {
- $A slaveof $B_host $B_port
- wait_for_condition 50 100 {
- [lindex [$A role] 0] eq {slave} &&
- [string match {*master_link_status:up*} [$A info replication]]
- } else {
- fail "Can't turn the instance into a slave"
- }
- }
- test {BRPOPLPUSH replication, when blocking against empty list} {
- set rd [redis_deferring_client]
- $rd brpoplpush a b 5
- r lpush a foo
- wait_for_condition 50 100 {
- [$A debug digest] eq [$B debug digest]
- } else {
- fail "Master and slave have different digest: [$A debug digest] VS [$B debug digest]"
- }
- }
- test {BRPOPLPUSH replication, list exists} {
- set rd [redis_deferring_client]
- r lpush c 1
- r lpush c 2
- r lpush c 3
- $rd brpoplpush c d 5
- after 1000
- assert_equal [$A debug digest] [$B debug digest]
- }
- test {BLPOP followed by role change, issue #2473} {
- set rd [redis_deferring_client]
- $rd blpop foo 0 ; # Block while B is a master
- # Turn B into master of A
- $A slaveof no one
- $B slaveof $A_host $A_port
- wait_for_condition 50 100 {
- [lindex [$B role] 0] eq {slave} &&
- [string match {*master_link_status:up*} [$B info replication]]
- } else {
- fail "Can't turn the instance into a slave"
- }
- # Push elements into the "foo" list of the new slave.
- # If the client is still attached to the instance, we'll get
- # a desync between the two instances.
- $A rpush foo a b c
- after 100
- wait_for_condition 50 100 {
- [$A debug digest] eq [$B debug digest] &&
- [$A lrange foo 0 -1] eq {a b c} &&
- [$B lrange foo 0 -1] eq {a b c}
- } else {
- fail "Master and slave have different digest: [$A debug digest] VS [$B debug digest]"
- }
- }
- }
- }
- start_server {tags {"repl"}} {
- r set mykey foo
- start_server {} {
- test {Second server should have role master at first} {
- s role
- } {master}
- test {SLAVEOF should start with link status "down"} {
- r slaveof [srv -1 host] [srv -1 port]
- s master_link_status
- } {down}
- test {The role should immediately be changed to "slave"} {
- s role
- } {slave}
- wait_for_sync r
- test {Sync should have transferred keys from master} {
- r get mykey
- } {foo}
- test {The link status should be up} {
- s master_link_status
- } {up}
- test {SET on the master should immediately propagate} {
- r -1 set mykey bar
- wait_for_condition 500 100 {
- [r 0 get mykey] eq {bar}
- } else {
- fail "SET on master did not propagated on slave"
- }
- }
- test {FLUSHALL should replicate} {
- r -1 flushall
- if {$::valgrind} {after 2000}
- list [r -1 dbsize] [r 0 dbsize]
- } {0 0}
- test {ROLE in master reports master with a slave} {
- set res [r -1 role]
- lassign $res role offset slaves
- assert {$role eq {master}}
- assert {$offset > 0}
- assert {[llength $slaves] == 1}
- lassign [lindex $slaves 0] master_host master_port slave_offset
- assert {$slave_offset <= $offset}
- }
- test {ROLE in slave reports slave in connected state} {
- set res [r role]
- lassign $res role master_host master_port slave_state slave_offset
- assert {$role eq {slave}}
- assert {$slave_state eq {connected}}
- }
- }
- }
- foreach dl {no yes} {
- start_server {tags {"repl"}} {
- set master [srv 0 client]
- $master config set repl-diskless-sync $dl
- set master_host [srv 0 host]
- set master_port [srv 0 port]
- set slaves {}
- set load_handle0 [start_write_load $master_host $master_port 3]
- set load_handle1 [start_write_load $master_host $master_port 5]
- set load_handle2 [start_write_load $master_host $master_port 20]
- set load_handle3 [start_write_load $master_host $master_port 8]
- set load_handle4 [start_write_load $master_host $master_port 4]
- start_server {} {
- lappend slaves [srv 0 client]
- start_server {} {
- lappend slaves [srv 0 client]
- start_server {} {
- lappend slaves [srv 0 client]
- test "Connect multiple slaves at the same time (issue #141), diskless=$dl" {
- # Send SLAVEOF commands to slaves
- [lindex $slaves 0] slaveof $master_host $master_port
- [lindex $slaves 1] slaveof $master_host $master_port
- [lindex $slaves 2] slaveof $master_host $master_port
- # Wait for all the three slaves to reach the "online"
- # state from the POV of the master.
- set retry 500
- while {$retry} {
- set info [r -3 info]
- if {[string match {*slave0:*state=online*slave1:*state=online*slave2:*state=online*} $info]} {
- break
- } else {
- incr retry -1
- after 100
- }
- }
- if {$retry == 0} {
- error "assertion:Slaves not correctly synchronized"
- }
- # Wait that slaves acknowledge they are online so
- # we are sure that DBSIZE and DEBUG DIGEST will not
- # fail because of timing issues.
- wait_for_condition 500 100 {
- [lindex [[lindex $slaves 0] role] 3] eq {connected} &&
- [lindex [[lindex $slaves 1] role] 3] eq {connected} &&
- [lindex [[lindex $slaves 2] role] 3] eq {connected}
- } else {
- fail "Slaves still not connected after some time"
- }
- # Stop the write load
- stop_write_load $load_handle0
- stop_write_load $load_handle1
- stop_write_load $load_handle2
- stop_write_load $load_handle3
- stop_write_load $load_handle4
- # Make sure that slaves and master have same
- # number of keys
- wait_for_condition 500 100 {
- [$master dbsize] == [[lindex $slaves 0] dbsize] &&
- [$master dbsize] == [[lindex $slaves 1] dbsize] &&
- [$master dbsize] == [[lindex $slaves 2] dbsize]
- } else {
- fail "Different number of keys between masted and slave after too long time."
- }
- # 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}
- assert {$digest eq $digest0}
- assert {$digest eq $digest1}
- assert {$digest eq $digest2}
- }
- }
- }
- }
- }
- }
|