1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2005,2008 Oracle.  All rights reserved.
4#
5# $Id: rep045script.tcl,v 12.11 2008/01/08 20:58:53 bostic Exp $
6#
7# Rep045 script - replication with version dbs.
8#
9# Usage: rep045script clientdir vfile
10# clientdir: client env directory
11# vfile: name of version file
12#
13source ./include.tcl
14source $test_path/test.tcl
15source $test_path/testutils.tcl
16source $test_path/reputils.tcl
17
18set usage "repscript clientdir vfile"
19
20# Verify usage
21if { $argc != 2 } {
22	puts stderr "FAIL:[timestamp] Usage: $usage"
23	exit
24}
25
26# Initialize arguments
27set clientdir [ lindex $argv 0 ]
28set vfile [ lindex $argv 1 ]
29set niter 50
30
31# Join the queue env.  We assume the rep test convention of
32# placing the messages in $testdir/MSGQUEUEDIR.
33set queueenv [eval berkdb_env -home $testdir/MSGQUEUEDIR]
34error_check_good script_qenv_open [is_valid_env $queueenv] TRUE
35
36# We need to set up our own machids.
37repladd 3
38
39# Join the client env.
40set cl_cmd "berkdb_env_noerr -home $clientdir \
41	-txn -rep_client -rep_transport \[list 3 replsend\]"
42# set cl_cmd "berkdb_env_noerr -home $clientdir \
43# 	-verbose {rep on} -errfile /dev/stderr \
44# 	-txn -rep_client -rep_transport \[list 3 replsend\]"
45set clientenv [eval $cl_cmd]
46error_check_good script_cenv_open [is_valid_env $clientenv] TRUE
47
48# Start up deadlock detector.
49set dpid [exec $util_path/db_deadlock \
50    -a o -v -t 5 -h $clientdir >& $testdir/dd.out &]
51
52# Initialize version number.  Don't try to open the first
53# version database until the master has completed setting it up.
54set version 0
55while {[catch {berkdb_open_noerr -env $clientenv -rdonly $vfile} vdb]} {
56	puts "FAIL: vdb open failed: $vdb"
57	tclsleep 1
58}
59
60while { $version == 0 } {
61	tclsleep 1
62	if { [catch {$vdb get VERSION} res] } {
63		# If we encounter an error, check what kind of
64		# error it is.
65		if { [is_substr $res DB_LOCK_DEADLOCK] == 1 } {
66			# We're deadlocked.  Just wait for the
67			# deadlock detector to break the deadlock.
68		} elseif { [is_substr $res DB_REP_HANDLE_DEAD] == 1 } {
69			# Handle is dead.  Get a new handle.
70			error_check_good vdb_close [$vdb close] 0
71			set vdb [eval berkdb_open -env $clientenv\
72			    -rdonly $vfile]
73		} else {
74			# We got something we didn't expect.
75			puts "FAIL: Trying to get version, got $res"
76			break
77		}
78	} else {
79		# No error was encountered.
80		set version [lindex [lindex $res 0] 1]
81	}
82}
83error_check_good close_vdb [$vdb close] 0
84set dbfile db.$version
85
86# Open completed database version $version.
87if {[catch {berkdb_open -rdonly -env $clientenv $dbfile} db]} {
88	puts "FAIL: db open failed: $db"
89}
90error_check_good db_open [is_valid_db $db] TRUE
91
92# While parent process is not done, read from current database.
93# Periodically check version and update current database when
94# necessary.
95while { 1 } {
96	set dbc [$db cursor]
97	set i 0
98	error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
99	for { set dbt [$dbc get -first] } { $i < $niter } \
100	    { set dbt [$dbc get -next] } {
101		incr i
102	}
103	error_check_good cursor_close [$dbc close] 0
104
105	while {[catch {berkdb_open -env $clientenv -rdonly $vfile} vdb]} {
106		puts "open failed: vdb is $vdb"
107		tclsleep 1
108	}
109	set ret [$vdb get VERSION]
110
111	set newversion [lindex [lindex $ret 0] 1]
112	error_check_good close_vdb [$vdb close] 0
113	error_check_bad check_newversion $newversion ""
114	if { $newversion != $version } {
115		if { $newversion == "DONE" } {
116			break
117		} elseif { $newversion == 0 } {
118			puts "FAIL: version has reverted to 0"
119			continue
120		} else {
121			error_check_good db_close [$db close] 0
122			set version $newversion
123			set dbfile db.$version
124			while {[catch \
125			    {berkdb_open -env $clientenv -rdonly $dbfile} db]} {
126				puts "db open of new db failed: $db"
127				tclsleep 1
128			}
129			error_check_good db_open [is_valid_db $db] TRUE
130		}
131	}
132
133	# Pause a few seconds to allow the parent to do some work.
134	tclsleep 3
135}
136
137# Clean up.
138error_check_good kill_deadlock_detector [tclkill $dpid] ""
139error_check_good db_close [$db close] 0
140error_check_good script_client_close [$clientenv close] 0
141