diff options
Diffstat (limited to 'db-4.8.30/test/rep082.tcl')
| -rw-r--r-- | db-4.8.30/test/rep082.tcl | 209 | 
1 files changed, 209 insertions, 0 deletions
diff --git a/db-4.8.30/test/rep082.tcl b/db-4.8.30/test/rep082.tcl new file mode 100644 index 0000000..71fc58d --- /dev/null +++ b/db-4.8.30/test/rep082.tcl @@ -0,0 +1,209 @@ +# See the file LICENSE for redistribution information. +# +# Copyright (c)-2009 Oracle.  All rights reserved. +# +# TEST	rep082 +# TEST  Sending replication requests to correct master site. +# TEST +# TEST  Regression test for a bug [#16592] where a client could send an +# TEST  UPDATE_REQ to another client instead of the master. +# +proc rep082 { method { niter 200 } { tnum "082" } args } { +	source ./include.tcl +	global repfiles_in_memory + +	if { $is_windows9x_test == 1 } { +		puts "Skipping replication test on Win9x platform." +		return +	} + +	if { $checking_valid_methods } { +		return "ALL" +	} + +	set args [convert_args $method $args] + +	set msg2 "and on-disk replication files" +	if { $repfiles_in_memory } { +		set msg2 "and in-memory replication files" +	} + +	puts "Rep$tnum: ($method) Test that\ +	    client doesn't send UPDATE_REQ to another client $msg2." + +	rep082_sub $method $niter $tnum $args +} + +proc rep082_sub { method niter tnum  largs } { +	global testdir +	global util_path +	global repfiles_in_memory +	global rep_verbose +	global verbose_type + +	set verbargs "" +	if { $rep_verbose == 1 } { +		set verbargs " -verbose {$verbose_type on} " +	} + +	set repmemargs "" +	if { $repfiles_in_memory } { +		set repmemargs "-rep_inmem_files " +	} + +	env_cleanup $testdir +	replsetup $testdir/MSGQUEUEDIR + +	file mkdir [set dirA $testdir/A] +	file mkdir [set dirB $testdir/B] +	file mkdir [set dirC $testdir/C] + +	set pagesize 4096 +	append largs " -pagesize $pagesize " +	set log_buf [expr $pagesize * 2] +	set log_max [expr $log_buf * 4] + +	repladd 1 +	set env_A_cmd "berkdb_env_noerr -create -txn $verbargs $repmemargs \ +	    -log_buffer $log_buf -log_max $log_max -errpfx SITE_A \ +	    -home $dirA -rep_transport \[list 1 replsend\]" +	set envs(A) [eval $env_A_cmd -rep_master] + +	# Open a client +	repladd 2 +	set env_B_cmd "berkdb_env_noerr -create -txn $verbargs $repmemargs \ +	    -log_buffer $log_buf -log_max $log_max -errpfx SITE_B \ +	    -home $dirB -rep_transport \[list 2 replsend\]" +	set envs(B) [eval $env_B_cmd -rep_client] + +	# Open 2nd client +	repladd 3 +	set env_C_cmd "berkdb_env_noerr -create -txn $verbargs $repmemargs \ +	    -log_buffer $log_buf -log_max $log_max -errpfx SITE_C \ +	    -home $dirC -rep_transport \[list 3 replsend\]" +	set envs(C) [eval $env_C_cmd -rep_client] + +	# Bring the clients online by processing the startup messages. +	set envlist "{$envs(A) 1} {$envs(B) 2} {$envs(C) 3}" +	process_msgs $envlist + +	# Run rep_test in the master (and update clients). +	puts "\tRep$tnum.a: populate initial portion of log." +	eval rep_test $method $envs(A) NULL $niter 0 0 0 $largs +	process_msgs $envlist + +	$envs(A) close +	$envs(B) close +	$envs(C) close + +	# At this point, we have a first section of the log history that was +	# produced at master site A, and is replicated to both other sites.  Now +	# let's produce a second section of history, also produced at master +	# site A, but only replicated to site C; make sure this second section +	# spans a log file boundary.  Archive log files at site C, so that we +	# make sure that site C has only a fraction of this second section. +	# +	set res [eval exec $util_path/db_archive -l -h $dirC] +	set last_client_log [lindex [lsort $res] end] + +	set envs(A) [eval $env_A_cmd -recover -rep_master] +	set envs(C) [eval $env_C_cmd -recover -rep_client] +	replclear 2 +	process_msgs "{$envs(A) 1} {$envs(C) 3}" + +	set stop 0 +	set start 0 +	set count 0 +	while { $stop == 0 } { +		incr count +		# Run rep_test in the master (don't update client). +		puts "\tRep$tnum.b: Fill log until next log file." +		incr start $niter +		eval rep_test $method $envs(A) NULL $niter $start $start 0 $largs + +		replclear 2 +		process_msgs "{$envs(A) 1} {$envs(C) 3}" + +		puts "\tRep$tnum.c: Run db_archive on client C." +		exec $util_path/db_archive -d -h $dirC +		set res [eval exec $util_path/db_archive -l -h $dirC] +		if { [lsearch -exact $res $last_client_log] == -1} { +			set stop 1 +		} +	} + +	# Now make site B become the master.  Since site B was not running +	# during the last phase, it does not have any of the "second section of +	# log history" that we produced in that phase.  So site A will have to +	# throw away those transactions in order to sync up with B.  HOWEVER, +	# site B will now generate yet another new section of log history, which +	# is identical to the set of transactions generated a moment ago at site +	# A.  In other words, although this is the third section of history to +	# be generated, we have arranged to have it completely replace the +	# second section, and to have it exactly match!  Note that we leave site +	# C out of the picture during this phase. +	#  +	$envs(A) close +	$envs(C) close +	set envs(B) [eval $env_B_cmd -recover -rep_master] +	set envs(A) [eval $env_A_cmd -recover -rep_client] + +	set start 0 +	while {$count > 0} { +		puts "\tRep$tnum.d: Running rep_test in replicated env." +		incr start $niter +		eval rep_test $method $envs(B) NULL $niter $start $start 0 $largs + +		replclear 3 +		process_msgs "{$envs(A) 1} {$envs(B) 2}" + +		incr count -1 +	} + +	# Now start up site C again, but configure it to rely on site A for +	# client-to-client synchronization.  Recall the known contents of site +	# C's transaction log: it has a partial copy of the "second section" of +	# log history (it has the end of that section, but not the beginning). +	# The transactions in this log will have the same LSN's as are currently +	# in place at sites A and B (which, remember, were produced by the +	# identical "third section" of history), but the commit record contents +	# won't exactly match, because the third section was produced by master +	# site B. +	# +	# During the verify dance, client C will continue to walk back the log, +	# finding commit records which find matching LSNs at A/B, but no +	# matching contents.  When it hits the archived log file boundary it +	# will have to give up without having found a match.  Thus we have +	# produced a situation where an incoming VERIFY message from another +	# client (site A) results in client C sending an UPDATE_REQ.  We want to +	# make sure that client C sends the UPDATE_REQ to the master, rather +	# than blindly sending to the same site that produced the VERIFY +	# message. +	#  +	puts "\tRep$tnum.e: start client C, with A as peer." +	set env_C_cmd "berkdb_env_noerr -create -txn $verbargs \ +	    -log_buffer $log_buf -log_max $log_max -errpfx SITE_C \ +	    -home $dirC -rep_transport \[list 3 rep082_send\]" +	set envs(C) [eval $env_C_cmd -recover -rep_client] +	process_msgs "{$envs(A) 1} {$envs(B) 2} {$envs(C) 3}" + +	$envs(C) close +	$envs(A) close +	$envs(B) close + +	replclose $testdir/MSGQUEUEDIR +} + +# We use this special-purpose wrapper send function only in the very last phase +# of the test, and only at site C.  Before that we just use the normal send +# function as usual.  Since we know exactly what sites are in what roles, we can +# simply hard-code the EID numbers: site B (2) is the master, and site A (1) is +# the desired target site for c2c synchronization. +#  +proc rep082_send { control rec fromid toid flags lsn } { +	if {$toid == 2 && [lsearch $flags "rerequest"] == -1 \ +	    && [lsearch $flags "any"] != -1} { +		set toid 1 +	} +	replsend $control $rec $fromid $toid $flags $lsn +}  | 
