2011-09-13 17:48:33 +00:00
|
|
|
# See the file LICENSE for redistribution information.
|
|
|
|
#
|
2012-11-14 20:13:24 +00:00
|
|
|
# Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved.
|
2011-09-13 17:48:33 +00:00
|
|
|
#
|
|
|
|
# $Id$
|
|
|
|
#
|
|
|
|
# Rep045 script - replication with version dbs.
|
|
|
|
#
|
|
|
|
# Usage: rep045script clientdir vfile
|
|
|
|
# clientdir: client env directory
|
|
|
|
# vfile: name of version file
|
|
|
|
#
|
|
|
|
source ./include.tcl
|
|
|
|
source $test_path/test.tcl
|
|
|
|
source $test_path/testutils.tcl
|
|
|
|
source $test_path/reputils.tcl
|
|
|
|
|
|
|
|
set usage "repscript clientdir vfile"
|
|
|
|
|
|
|
|
# Verify usage
|
|
|
|
if { $argc != 3 } {
|
|
|
|
puts stderr "FAIL:[timestamp] Usage: $usage"
|
|
|
|
exit
|
|
|
|
}
|
|
|
|
|
|
|
|
# Initialize arguments
|
|
|
|
set clientdir [ lindex $argv 0 ]
|
|
|
|
set vfile [ lindex $argv 1 ]
|
|
|
|
global databases_in_memory
|
|
|
|
set databases_in_memory [ lindex $argv 2 ]
|
|
|
|
set niter 50
|
|
|
|
|
|
|
|
# Join the queue env. We assume the rep test convention of
|
|
|
|
# placing the messages in $testdir/MSGQUEUEDIR.
|
|
|
|
set queueenv [eval berkdb_env -home $testdir/MSGQUEUEDIR]
|
|
|
|
error_check_good script_qenv_open [is_valid_env $queueenv] TRUE
|
|
|
|
|
|
|
|
# We need to set up our own machids.
|
|
|
|
repladd 3
|
|
|
|
|
|
|
|
# Join the client env.
|
|
|
|
set cl_cmd "berkdb_env_noerr -home $clientdir \
|
|
|
|
-txn -rep_client -rep_transport \[list 3 replsend\]"
|
|
|
|
# set cl_cmd "berkdb_env_noerr -home $clientdir \
|
|
|
|
# -verbose {rep on} -errfile /dev/stderr \
|
|
|
|
# -txn -rep_client -rep_transport \[list 3 replsend\]"
|
|
|
|
set clientenv [eval $cl_cmd]
|
|
|
|
error_check_good script_cenv_open [is_valid_env $clientenv] TRUE
|
|
|
|
|
|
|
|
# Start up deadlock detector.
|
|
|
|
set dpid [exec $util_path/db_deadlock \
|
|
|
|
-a o -v -t 5 -h $clientdir >& $testdir/dd.out &]
|
|
|
|
|
|
|
|
# Initialize version number. Don't try to open the first
|
|
|
|
# version database until the master has completed setting it up.
|
|
|
|
set version 0
|
|
|
|
while {[catch {eval {berkdb_open_noerr} -env $clientenv -rdonly $vfile} vdb]} {
|
|
|
|
if { [is_substr $vdb DB_LOCK_DEADLOCK] == 1 } {
|
|
|
|
# We're deadlocked. Just wait for the
|
|
|
|
# deadlock detector to break the deadlock.
|
|
|
|
tclsleep 1
|
|
|
|
} else {
|
|
|
|
puts "FAIL: vdb open failed: $vdb"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while { $version == 0 } {
|
|
|
|
tclsleep 1
|
|
|
|
if { [catch {$vdb get VERSION} res] } {
|
|
|
|
# If we encounter an error, check what kind of
|
|
|
|
# error it is.
|
|
|
|
if { [is_substr $res DB_LOCK_DEADLOCK] == 1 } {
|
|
|
|
# We're deadlocked. Just wait for the
|
|
|
|
# deadlock detector to break the deadlock.
|
|
|
|
} elseif { [is_substr $res DB_REP_HANDLE_DEAD] == 1 } {
|
|
|
|
# Handle is dead. Get a new handle.
|
|
|
|
error_check_good vdb_close [$vdb close] 0
|
|
|
|
set vdb [eval {berkdb_open} -env $clientenv\
|
|
|
|
-rdonly $vfile]
|
|
|
|
} else {
|
|
|
|
# We got something we didn't expect.
|
|
|
|
puts "FAIL: Trying to get version, got $res"
|
|
|
|
break
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
# No error was encountered.
|
|
|
|
set version [lindex [lindex $res 0] 1]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
error_check_good close_vdb [$vdb close] 0
|
|
|
|
|
|
|
|
# If the parent has gotten really far ahead, it may be done.
|
|
|
|
# Clean up and exit.
|
|
|
|
if { $version == "DONE" } {
|
|
|
|
error_check_good kill_deadlock_detector [tclkill $dpid] ""
|
|
|
|
error_check_good script_client_close [$clientenv close] 0
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if { $databases_in_memory } {
|
|
|
|
set dbfile [concat \"\" db.$version]
|
|
|
|
} else {
|
|
|
|
set dbfile db.$version
|
|
|
|
}
|
|
|
|
|
|
|
|
# Open completed database version $version.
|
|
|
|
if {[catch {eval {berkdb_open} -rdonly -env $clientenv $dbfile} db]} {
|
|
|
|
puts "FAIL: db open failed: $db"
|
|
|
|
}
|
|
|
|
error_check_good db_open [is_valid_db $db] TRUE
|
|
|
|
|
|
|
|
# While parent process is not done, read from current database.
|
|
|
|
# Periodically check version and update current database when
|
|
|
|
# necessary.
|
|
|
|
while { 1 } {
|
|
|
|
set dbc [$db cursor]
|
|
|
|
set i 0
|
|
|
|
error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
|
|
|
|
for { set dbt [$dbc get -first] } { $i < $niter } \
|
|
|
|
{ set dbt [$dbc get -next] } {
|
|
|
|
incr i
|
|
|
|
}
|
|
|
|
error_check_good cursor_close [$dbc close] 0
|
|
|
|
|
|
|
|
while {[catch {eval {berkdb_open} -env $clientenv -rdonly $vfile} vdb]} {
|
|
|
|
puts "open failed: vdb is $vdb"
|
|
|
|
tclsleep 1
|
|
|
|
}
|
|
|
|
set ret [$vdb get VERSION]
|
|
|
|
|
|
|
|
set newversion [lindex [lindex $ret 0] 1]
|
|
|
|
error_check_good close_vdb [$vdb close] 0
|
|
|
|
error_check_bad check_newversion $newversion ""
|
|
|
|
if { $newversion != $version } {
|
|
|
|
if { $newversion == "DONE" } {
|
|
|
|
break
|
|
|
|
} elseif { $newversion == 0 } {
|
|
|
|
puts "FAIL: version has reverted to 0"
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
error_check_good db_close [$db close] 0
|
|
|
|
set version $newversion
|
|
|
|
if { $databases_in_memory } {
|
|
|
|
set dbfile [concat \"\" db.$version]
|
|
|
|
} else {
|
|
|
|
set dbfile db.$version
|
|
|
|
}
|
|
|
|
while {[catch {eval \
|
|
|
|
{berkdb_open} -env $clientenv -rdonly $dbfile} db]} {
|
|
|
|
puts "db open of new db failed: $db"
|
|
|
|
tclsleep 1
|
|
|
|
}
|
|
|
|
error_check_good db_open [is_valid_db $db] TRUE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Pause a few seconds to allow the parent to do some work.
|
|
|
|
tclsleep 3
|
|
|
|
}
|
|
|
|
|
|
|
|
# Clean up.
|
|
|
|
error_check_good kill_deadlock_detector [tclkill $dpid] ""
|
|
|
|
error_check_good db_close [$db close] 0
|
|
|
|
error_check_good script_client_close [$clientenv close] 0
|