1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
|
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2006, 2013 Oracle and/or its affiliates. All rights reserved.
#
# $Id$
#
# TEST rep065
# TEST Tests replication running with different versions.
# TEST This capability is introduced with 4.5.
# TEST
# TEST Start a replication group of 1 master and N sites, all
# TEST running some historical version greater than or equal to 4.4.
# TEST Take down a client and bring it up again running current.
# TEST Run some upgrades, make sure everything works.
# TEST
# TEST Each site runs the tcllib of its own version, but uses
# TEST the current tcl code (e.g. test.tcl).
proc rep065 { method { nsites 3 } args } {
source ./include.tcl
global repfiles_in_memory
global noenv_messaging
set noenv_messaging 1
#
# Skip all methods but btree - we don't use the method, as we
# run over all of them with varying versions.
#
if { $checking_valid_methods } {
set test_methods { btree }
return $test_methods
}
if { [is_btree $method] == 0 } {
puts "Rep065: Skipping for method $method."
return
}
set msg2 "and on-disk replication files"
if { $repfiles_in_memory } {
set msg2 "and in-memory replication files"
}
# Make the list of {method version} pairs to test.
#
set mvlist [method_version]
set mvlen [llength $mvlist]
puts "Rep065: Testing the following $mvlen method/version pairs:"
puts "Rep065: $mvlist"
puts "Rep065: $msg2"
set count 1
set total [llength $mvlist]
set slist [setup_sites $nsites]
foreach i $mvlist {
puts "Rep065: Test iteration $count of $total: $i"
rep065_sub $count $i $nsites $slist
incr count
}
set noenv_messaging 0
}
proc rep065_sub { iter mv nsites slist } {
source ./include.tcl
global machids
global util_path
set machids {}
set method [lindex $mv 0]
set vers [lindex $mv 1]
puts "\tRep065.$iter.a: Set up."
# Whatever directory we started this process from is referred
# to as the controlling directory. It will contain the message
# queue and start all the child processes.
set controldir [pwd]
env_cleanup $controldir/$testdir
replsetup_noenv $controldir/$testdir/MSGQUEUEDIR
# Set up the historical build directory. The master will start
# running with historical code.
#
# This test presumes we are running in the current build
# directory and that the expected historical builds are
# set up in a similar fashion. If they are not, quit gracefully.
set pwd [pwd]
set homedir [file dirname [file dirname $pwd]]
#
# Cannot use test_path because that is relative to the current
# directory (which will often be the old release directory).
# We need to send in the pathname to the reputils path to the
# current directory and that will be an absolute pathname.
#
set reputils_path $pwd/../test/tcl
set histdir $homedir/$vers/build_unix
if { [file exists $histdir] == 0 } {
puts -nonewline "Skipping iteration $iter: cannot find"
puts " historical version $vers."
return
}
if { [file exists $histdir/db_verify] == 0 } {
puts -nonewline "Skipping iteration $iter: historical version"
puts " $vers is missing some executables. Is it built?"
return
}
set histtestdir $histdir/TESTDIR
env_cleanup $histtestdir
set markerdir $controldir/$testdir/MARKER
file delete -force $markerdir
# Create site directories. They start running in the historical
# directory, too. They will be upgraded to the current version
# first.
set allids { }
for { set i 0 } { $i < $nsites } { incr i } {
set siteid($i) [expr $i + 1]
set sid $siteid($i)
lappend allids $sid
set histdirs($sid) $histtestdir/SITE.$i
set upgdir($sid) $controldir/$testdir/SITE.$i
file mkdir $histdirs($sid)
file mkdir $histdirs($sid)/DATADIR
file mkdir $upgdir($sid)
file mkdir $upgdir($sid)/DATADIR
}
# Open master env running 4.4.
#
# We know that slist has all sites starting in the histdir.
# So if we encounter an upgrade value, we upgrade that client
# from the hist dir.
#
set count 1
foreach sitevers $slist {
puts "\tRep065.b.$iter.$count: Run with sitelist $sitevers."
#
# Delete the marker directory each iteration so that
# we don't find old data in there.
#
file delete -force $markerdir
file mkdir $markerdir
#
# Get the chosen master index from the list of sites.
#
set mindex [get_master $nsites $sitevers]
set meid [expr $mindex + 1]
#
# Kick off the test processes. We need 1 test process
# per site and 1 message process per site.
#
set pids {}
for { set i 0 } { $i < $nsites } { incr i } {
set upg [lindex $sitevers $i]
set sid $siteid($i)
#
# If we are running "old" set up an array
# saying if this site has run old/new yet.
# The reason is that we want to "upgrade"
# only the first time we go from old to new,
# not every iteration through this loop.
#
if { $upg == 0 } {
puts -nonewline "\t\tRep065.b: Test: Old site $i"
set sitedir($i) $histdirs($sid)
set already_upgraded($i) 0
} else {
puts -nonewline "\t\tRep065.b: Test: Upgraded site $i"
set sitedir($i) $upgdir($sid)
if { $already_upgraded($i) == 0 } {
upg_repdir $histdirs($sid) $sitedir($i)
}
set already_upgraded($i) 1
}
if { $sid == $meid } {
set state MASTER
set runtest [list REPTEST $method 15 10]
puts " (MASTER)"
} else {
set state CLIENT
set runtest {REPTEST_GET}
puts " (CLIENT)"
}
lappend pids [exec $tclsh_path $test_path/wrap.tcl \
rep065script.tcl \
$controldir/$testdir/$count.S$i.log \
SKIP \
START $state \
$runtest \
$sid $allids $controldir \
$sitedir($i) $reputils_path &]
lappend pids [exec $tclsh_path $test_path/wrap.tcl \
rep065script.tcl \
$controldir/$testdir/$count.S$i.msg \
SKIP \
PROCMSGS $state \
NULL \
$sid $allids $controldir \
$sitedir($i) $reputils_path &]
}
watch_procs $pids 20
#
# At this point, clean up any message files. The message
# system leads to a significant number of duplicate
# requests. If the master site handled them after the
# client message processes exited, then there can be
# a large number of "dead" message files waiting for
# non-existent clients. Just clean up everyone.
#
for { set i 0 } { $i < $nsites } { incr i } {
replclear_noenv $siteid($i)
}
#
# Kick off the verification processes. These just walk
# their own logs and databases, so we don't need to have
# a message process. We need separate processes because
# old sites need to use old utilities.
#
set pids {}
puts "\tRep065.c.$iter.$count: Verify all sites."
for { set i 0 } { $i < $nsites } { incr i } {
if { $siteid($i) == $meid } {
set state MASTER
} else {
set state CLIENT
}
lappend pids [exec $tclsh_path $test_path/wrap.tcl \
rep065script.tcl \
$controldir/$testdir/$count.S$i.ver \
SKIP \
VERIFY $state \
{LOG DB} \
$siteid($i) $allids $controldir \
$sitedir($i) $reputils_path &]
}
watch_procs $pids 10
#
# Now that each site created its verification files,
# we can now verify everyone.
#
for { set i 0 } { $i < $nsites } { incr i } {
if { $i == $mindex } {
continue
}
puts \
"\t\tRep065.c: Verify: Compare databases master and client $i"
error_check_good db_cmp \
[filecmp $sitedir($mindex)/VERIFY/dbdump \
$sitedir($i)/VERIFY/dbdump] 0
set upg [lindex $sitevers $i]
# !!!
# Although db_printlog works and can read old logs,
# there have been some changes to the output text that
# makes comparing difficult. One possible solution
# is to run db_printlog here, from the current directory
# instead of from the historical directory.
#
if { $upg == 0 } {
puts \
"\t\tRep065.c: Verify: Compare logs master and client $i"
error_check_good log_cmp \
[filecmp $sitedir($mindex)/VERIFY/prlog \
$sitedir($i)/VERIFY/prlog] 0
} else {
puts \
"\t\tRep065.c: Verify: Compare LSNs master and client $i"
error_check_good log_cmp \
[filecmp $sitedir($mindex)/VERIFY/loglsn \
$sitedir($i)/VERIFY/loglsn] 0
}
}
#
# At this point we have a master and sites all up to date
# with each other. Now, one at a time, upgrade the sites
# to the current version and start everyone up again.
incr count
}
}
proc setup_sites { nsites } {
#
# Set up a list that goes from 0 to $nsites running
# upgraded. A 0 represents running old version and 1
# represents running upgraded. So, for 3 sites it will look like:
# { 0 0 0 } { 1 0 0 } { 1 1 0 } { 1 1 1 }
#
set sitelist {}
for { set i 0 } { $i <= $nsites } { incr i } {
set l ""
for { set j 1 } { $j <= $nsites } { incr j } {
if { $i < $j } {
lappend l 0
} else {
lappend l 1
}
}
lappend sitelist $l
}
return $sitelist
}
proc upg_repdir { histdir upgdir } {
global util_path
#
# Upgrade a site to the current version. This entails:
# 1. Removing any old files from the upgrade directory.
# 2. Copy all old version files to upgrade directory.
# 3. Remove any __db files from upgrade directory except __db.rep*gen.
# 4. Force checkpoint in new version.
file delete -force $upgdir
# Recovery was run before as part of upgradescript.
# Archive dir by copying it to upgrade dir.
file copy -force $histdir $upgdir
set dbfiles [glob -nocomplain $upgdir/__db*]
foreach d $dbfiles {
if { $d == "$upgdir/__db.rep.gen" ||
$d == "$upgdir/__db.rep.egen" } {
continue
}
file delete -force $d
}
# Force current version checkpoint
set stat [catch {eval exec $util_path/db_checkpoint -1 -h $upgdir} r]
if { $stat != 0 } {
puts "CHECKPOINT: $upgdir: $r"
}
error_check_good stat_ckp $stat 0
}
proc get_master { nsites verslist } {
error_check_good vlist_chk [llength $verslist] $nsites
#
# When we can, simply run an election to get a new master.
# We then verify we got an old client.
#
# For now, randomly pick among the old sites, or if no old
# sites just randomly pick anyone.
#
set old_count 0
# Pick 1 out of N old sites or 1 out of nsites if all upgraded.
foreach i $verslist {
if { $i == 0 } {
incr old_count
}
}
if { $old_count == 0 } {
set old_count $nsites
}
set master [berkdb random_int 0 [expr $old_count - 1]]
#
# Since the Nth old site may not be at the Nth place in the
# list unless we used the entire list, we need to loop to find
# the right index to return.
if { $old_count == $nsites } {
return $master
}
set ocount 0
set index 0
foreach i $verslist {
if { $i == 1 } {
incr index
continue
}
if { $ocount == $master } {
return $index
}
incr ocount
incr index
}
#
# If we get here there is a problem in the code.
#
error "FAIL: get_master problem"
}
proc method_version { } {
set mv {}
# Set up version 5.2, which adds the method 'heap'. Since
# heap is new, we'd like to test it heavily. Always test a
# 5.2/heap pair, plus one other 5.2 with a random non-heap
# version. Here's the hard-coded one:
set db52 "db-5.2.36"
lappend mv [list heap $db52]
set methods {btree rbtree recno frecno rrecno queue queueext hash}
set methods_len [expr [llength $methods] - 1]
set midx [berkdb random_int 0 $methods_len]
set method [lindex $methods $midx]
lappend mv [list $method $db52]
# Now take care of versions 4.4 though 5.1, which share
# the same list of eight valid methods.
set remaining_methods $methods
set methods_len [expr [llength $remaining_methods] - 1]
set versions {db-5.1.25 db-5.0.32 \
db-4.8.30 db-4.7.25 db-4.6.21 db-4.5.20 db-4.4.20}
set remaining_versions $versions
set versions_len [expr [llength $remaining_versions] - 1]
# Walk through the list of methods and the list of versions and
# pair them at random. Stop when either list is empty.
while { $versions_len >= 0 && $methods_len >= 0 } {
set vidx [berkdb random_int 0 $versions_len]
set midx [berkdb random_int 0 $methods_len]
set version [lindex $remaining_versions $vidx]
set method [lindex $remaining_methods $midx]
set remaining_versions [lreplace $remaining_versions $vidx $vidx]
set remaining_methods [lreplace $remaining_methods $midx $midx]
incr versions_len -1
incr methods_len -1
lappend mv [list $method $version]
}
# If there are remaining versions, randomly assign any of
# the original methods to each one.
while { $versions_len >= 0 } {
set methods_len [expr [llength $methods] - 1]
set midx [berkdb random_int 0 $methods_len]
set version [lindex $remaining_versions 0]
set method [lindex $methods $midx]
set remaining_versions [lreplace $remaining_versions 0 0]
incr versions_len -1
lappend mv [list $method $version]
}
# If there are remaining methods, randomly assign any of
# the original versions to each one.
while { $methods_len >= 0 } {
set versions_len [expr [llength $versions] - 1]
set vidx [berkdb random_int 0 $versions_len]
set version [lindex $versions $vidx]
set method [lindex $remaining_methods 0]
set remaining_methods [lreplace $remaining_methods 0 0]
incr methods_len -1
lappend mv [list $method $version]
}
return $mv
}
|