Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / test / tcl / rep100.tcl
1 # See the file LICENSE for redistribution information.
2 #
3 # Copyright (c) 2003, 2012 Oracle and/or its affiliates.  All rights reserved.
4 #
5 # $Id$
6 #
7 # TEST  rep100
8 # TEST  Checkpoints and unresolved txns
9 # TEST
10 proc rep100 { method { niter 10 } { tnum "100" } args } {
11         source ./include.tcl
12         global repfiles_in_memory
13
14         # Run for all access methods.
15         if { $checking_valid_methods } {
16                 return "ALL"
17         }
18
19         set args [convert_args $method $args]
20         set logsets [create_logsets 2]
21
22         set msg2 "and on-disk replication files"
23         if { $repfiles_in_memory } {
24                 set msg2 "and in-memory replication files"
25         }
26
27         # Run the body of the test with and without recovery.
28         foreach r $test_recopts {
29                 foreach l $logsets {
30                         set logindex [lsearch -exact $l "in-memory"]
31                         if { $logindex != -1 } {
32                                 puts "Rep$tnum: Skipping for in-memory logs."
33                                 continue
34                         }
35
36                         puts "Rep$tnum ($method $r):\
37                             Checkpoints and unresolved txns $msg2."
38                         puts "Rep$tnum: Master logs are [lindex $l 0]"
39                         puts "Rep$tnum: Client logs are [lindex $l 1]"
40                         rep100_sub $method $niter $tnum $l $r $args
41                 }
42         }
43 }
44
45 proc rep100_sub { method niter tnum logset recargs largs } {
46         source ./include.tcl
47         global perm_response_list
48         global repfiles_in_memory
49         global rep_verbose
50         global verbose_type
51
52         set verbargs ""
53         if { $rep_verbose == 1 } {
54                 set verbargs " -verbose {$verbose_type on} "
55         }
56
57         set repmemargs ""
58         if { $repfiles_in_memory } {
59                 set repmemargs "-rep_inmem_files "
60         }
61
62         env_cleanup $testdir
63         set omethod [convert_method $method]
64
65         replsetup $testdir/MSGQUEUEDIR
66
67         set masterdir $testdir/MASTERDIR
68         set clientdir $testdir/CLIENTDIR
69
70         file mkdir $masterdir
71         file mkdir $clientdir
72         set m_logtype [lindex $logset 0]
73         set c_logtype [lindex $logset 1]
74
75         # Since we're sure to be using on-disk logs, txnargs will be -txn nosync.
76         set m_logargs [adjust_logargs $m_logtype]
77         set c_logargs [adjust_logargs $c_logtype]
78         set m_txnargs [adjust_txnargs $m_logtype]
79         set c_txnargs [adjust_txnargs $c_logtype]
80
81         # Open a master.
82         repladd 1
83         set ma_cmd "berkdb_env_noerr -create $verbargs \
84             -log_max 1000000 $m_txnargs $m_logargs $repmemargs \
85             -home $masterdir -rep_master -errpfx MASTER \
86             -rep_transport \[list 1 replsend\]"
87         set masterenv [eval $ma_cmd $recargs]
88
89         # Open a client
90         repladd 2
91         set cl_cmd "berkdb_env_noerr -create -home $clientdir $verbargs \
92             $c_txnargs $c_logargs -rep_client -errpfx CLIENT $repmemargs \
93             -rep_transport \[list 2 replsend\]"
94         set clientenv [eval $cl_cmd $recargs]
95
96         # Bring the client online.
97         process_msgs "{$masterenv 1} {$clientenv 2}"
98
99         # Open database in master, make lots of changes so checkpoint
100         # will take a while, and propagate to client.
101         puts "\tRep$tnum.a: Create and populate database."
102         set dbname rep100.db
103         set dbname1 rep100_1.db
104         set db [eval "berkdb_open_noerr -create $omethod -auto_commit \
105             -env $masterenv $largs $dbname"]
106         set db1 [eval "berkdb_open_noerr -create $omethod -auto_commit \
107             -env $masterenv $largs $dbname1"]
108         for { set i 1 } { $i <= $niter } { incr i } {
109                 set t [$masterenv txn]
110                 error_check_good db_put \
111                     [eval $db put -txn $t $i [chop_data $method data$i]] 0
112                 error_check_good db1_put \
113                     [eval $db1 put -txn $t $i [chop_data $method data$i]] 0
114                 error_check_good txn_commit [$t commit] 0
115         }
116         process_msgs "{$masterenv 1} {$clientenv 2}" 1
117
118         # Get the master's last LSN before the checkpoint
119         set pre_ckp_offset \
120                 [stat_field $masterenv log_stat "Current log file offset"]
121
122         puts "\tRep$tnum.b: Checkpoint on master."
123         error_check_good checkpoint [$masterenv txn_checkpoint] 0
124         process_msgs "{$masterenv 1} {$clientenv 2}"
125
126         #
127         # We want to generate a checkpoint that is mid-txn on the master,
128         # but is mid-txn on a different txn on the client because the
129         # client is behind the master.  We want to make sure we don't
130         # get a Log sequence error on recovery.  The sequence of steps is:
131         #
132         # Open a txn T1 on the master.  Made a modification.
133         # Open a 2nd txn T2 on the master and make a modification for that txn.
134         # Replicate all of the above to the client.
135         # Make another modification to T1.
136         # Commit T1 but do not replicate to the client (i.e. lose those records).
137         # Checkpoint on the master and replicate to client.
138         # This should cause the client to sync pages but not the pages that
139         # modify T1 because its commit hasn't appeared yet, even though it
140         # has committed on the master.
141         # Commit T2
142         # Crash client and run recovery.
143         #
144         set start $niter
145         set end [expr $niter * 2]
146
147         # Open txn T1 and make a modification.
148         puts "\tRep$tnum.c: Open txn t1 and do an update."
149         set i $start
150         set t1 [$masterenv txn]
151         error_check_good db_put \
152             [eval $db1 put -txn $t1 $i [chop_data $method data$i]] 0
153
154         # Open a 2nd txn T2 on the master and make a modification in that txn.
155         # Replicate all to the client.
156         puts "\tRep$tnum.d: Open txn T2."
157         set t2 [$masterenv txn]
158
159         error_check_good db_put \
160             [eval $db put -txn $t2 $end [chop_data $method data$end]] 0
161         process_msgs "{$masterenv 1} {$clientenv 2}"
162
163         # Make another modification to T1.
164         # Commit T1 but do not replicate to the client (i.e. lose that record).
165         puts "\tRep$tnum.e: Update and commit T1, clear msgs for client."
166         error_check_good db_put \
167             [eval $db1 put -txn $t1 $i [chop_data $method data$end]] 0
168         error_check_good txn_commit [$t1 commit] 0
169         replclear 2
170
171         # Checkpoint on the master and replicate to client.
172         puts "\tRep$tnum.f: Checkpoint and replicate messages."
173         error_check_good checkpoint [$masterenv txn_checkpoint] 0
174         process_msgs "{$masterenv 1} {$clientenv 2}"
175
176         #
177         # Commit T2.  We have to sleep enough time so that the client
178         # will rerequest and catch up when it receives these records.
179         #
180         puts "\tRep$tnum.g: Sleep, commit T2 and catch client up."
181         tclsleep 2
182         error_check_good txn_commit [$t2 commit] 0
183         process_msgs "{$masterenv 1} {$clientenv 2}"
184
185         #
186         # At this point the client has all outstanding log records that
187         # have been written by the master.  So everything should be okay.
188         #
189         puts "\tRep$tnum.h: Abandon clientenv and reopen with recovery."
190         # "Crash" client (by abandoning its env) and run recovery.
191         set clientenv_new [eval $cl_cmd -recover]
192
193         # Clean up.
194         puts "\tRep$tnum.i: Clean up."
195         error_check_good db_close [$db close] 0
196         error_check_good db_close [$db1 close] 0
197         error_check_good masterenv_close [$masterenv close] 0
198         error_check_good clientenv_close [$clientenv_new close] 0
199         # Clean up abandoned handle.
200         catch {$clientenv close}
201
202         replclose $testdir/MSGQUEUEDIR
203 }