~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to db/test/recd012.tcl

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# See the file LICENSE for redistribution information.
 
2
#
 
3
# Copyright (c) 2000-2001
 
4
#       Sleepycat Software.  All rights reserved.
 
5
#
 
6
# $Id: recd012.tcl,v 11.17 2001/05/17 20:37:05 bostic Exp $
 
7
#
 
8
# Recovery Test 12.
 
9
# Test recovery handling of file opens and closes.
 
10
proc recd012 { method {start 0} \
 
11
    {niter 49} {noutiter 25} {niniter 100} {ndbs 5} args } {
 
12
        source ./include.tcl
 
13
 
 
14
        set tnum 12
 
15
        set pagesize 512
 
16
 
 
17
        if { $is_qnx_test } {
 
18
                set niter 40
 
19
        }
 
20
 
 
21
        puts "Recd0$tnum $method ($args): Test recovery file management."
 
22
        set pgindex [lsearch -exact $args "-pagesize"]
 
23
        if { $pgindex != -1 } {
 
24
                puts "Recd012: skipping for specific pagesizes"
 
25
                return
 
26
        }
 
27
 
 
28
        for { set i $start } { $i <= $niter } { incr i } {
 
29
 
 
30
                env_cleanup $testdir
 
31
 
 
32
                # For repeatability, we pass in the iteration number
 
33
                # as a parameter and use that in recd012_body to seed
 
34
                # the random number generator to randomize our operations.
 
35
                # This lets us re-run a potentially failing iteration
 
36
                # without having to start from the beginning and work
 
37
                # our way to it.
 
38
                #
 
39
                # The number of databases ranges from 4 to 8 and is
 
40
                # a function of $niter
 
41
#               set ndbs [expr ($i % 5) + 4]
 
42
 
 
43
                recd012_body \
 
44
                    $method $ndbs $i $noutiter $niniter $pagesize $tnum $args
 
45
        }
 
46
}
 
47
 
 
48
proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} } {
 
49
        global alphabet rand_init fixed_len recd012_ofkey recd012_ofckptkey
 
50
        source ./include.tcl
 
51
 
 
52
        set largs [convert_args $method $largs]
 
53
        set omethod [convert_method $method]
 
54
 
 
55
        puts "\tRecd0$tnum $method ($largs): Iteration $iter"
 
56
        puts "\t\tRecd0$tnum.a: Create environment and $ndbs databases."
 
57
 
 
58
        set flags "-create -txn -home $testdir"
 
59
        set env_cmd "berkdb env $flags"
 
60
        error_check_good env_remove [berkdb envremove -home $testdir] 0
 
61
        set dbenv [eval $env_cmd]
 
62
        error_check_good dbenv [is_valid_env $dbenv] TRUE
 
63
 
 
64
        # Initialize random number generator based on $iter.
 
65
        berkdb srand [expr $iter + $rand_init]
 
66
 
 
67
        # Initialize database that keeps track of number of open files (so
 
68
        # we don't run out of descriptors).
 
69
        set ofname of.db
 
70
        set ofdb [berkdb_open -env $dbenv\
 
71
            -create -dup -mode 0644 -btree -pagesize 512 $ofname]
 
72
        error_check_good of_open [is_valid_db $ofdb] TRUE
 
73
        set oftxn [$dbenv txn]
 
74
        error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
 
75
        error_check_good of_put [$ofdb put -txn $oftxn $recd012_ofkey 1] 0
 
76
        error_check_good of_put2 [$ofdb put -txn $oftxn $recd012_ofckptkey 0] 0
 
77
        error_check_good of_put3 [$ofdb put -txn $oftxn $recd012_ofckptkey 0] 0
 
78
        error_check_good of_txn_commit [$oftxn commit] 0
 
79
        error_check_good of_close [$ofdb close] 0
 
80
 
 
81
        # Create ndbs databases to work in, and a file listing db names to
 
82
        # pick from.
 
83
        set f [open TESTDIR/dblist w]
 
84
        set oflags \
 
85
            "-env $dbenv -create -mode 0644 -pagesize $psz $largs $omethod"
 
86
        for { set i 0 } { $i < $ndbs } { incr i } {
 
87
                # 50-50 chance of being a subdb, unless we're a queue.
 
88
                if { [berkdb random_int 0 1] || [is_queue $method] } {
 
89
                        # not a subdb
 
90
                        set dbname recd0$tnum-$i.db
 
91
                } else {
 
92
                        # subdb
 
93
                        set dbname "recd0$tnum-subdb.db s$i"
 
94
                }
 
95
                puts $f $dbname
 
96
                set db [eval berkdb_open $oflags $dbname]
 
97
                error_check_good db($i) [is_valid_db $db] TRUE
 
98
                error_check_good db($i)_close [$db close] 0
 
99
        }
 
100
        close $f
 
101
 
 
102
        error_check_good env_close [$dbenv close] 0
 
103
 
 
104
        # Now we get to the meat of things.  Our goal is to do some number
 
105
        # of opens, closes, updates, and shutdowns (simulated here by a
 
106
        # close of all open handles and a close/reopen of the environment,
 
107
        # with or without an envremove), matching the regular expression
 
108
        #
 
109
        #       ((O[OUC]+S)+R+V)
 
110
        #
 
111
        # We'll repeat the inner + a random number up to $niniter times,
 
112
        # and the outer + a random number up to $noutiter times.
 
113
        #
 
114
        # In order to simulate shutdowns, we'll perform the opens, closes,
 
115
        # and updates in a separate process, which we'll exit without closing
 
116
        # all handles properly.  The environment will be left lying around
 
117
        # before we run recovery 50% of the time.
 
118
        set out [berkdb random_int 1 $noutiter]
 
119
        puts "\t\tRecd0$tnum.b: Performing $out recoveries of up to $niniter\
 
120
            ops."
 
121
        for { set i 0 } { $i < $out } { incr i } {
 
122
                set child [open "|$tclsh_path" w]
 
123
 
 
124
                # For performance, don't source everything,
 
125
                # just what we'll need.
 
126
                puts $child "load $tcllib"
 
127
                puts $child "set fixed_len $fixed_len"
 
128
                puts $child "source ../test/testutils.tcl"
 
129
                puts $child "source ../test/recd0$tnum.tcl"
 
130
 
 
131
                set rnd [expr $iter * 10000 + $i * 100 + $rand_init]
 
132
 
 
133
                # Go.
 
134
                # puts "recd012_dochild {$env_cmd} $rnd $i $niniter\
 
135
                #    $ndbs $tnum $method $ofname $largs"
 
136
                puts $child "recd012_dochild {$env_cmd} $rnd $i $niniter\
 
137
                    $ndbs $tnum $method $ofname $largs"
 
138
                close $child
 
139
 
 
140
                # Run recovery 0-3 times.
 
141
                set nrecs [berkdb random_int 0 3]
 
142
                for { set j 0 } { $j < $nrecs } { incr j } {
 
143
                        set ret [catch {exec $util_path/db_recover \
 
144
                            -h $testdir} res]
 
145
                        if { $ret != 0 } {
 
146
                                puts "FAIL: db_recover returned with nonzero\
 
147
                                    exit status, output as follows:"
 
148
                                file mkdir /tmp/12out
 
149
                                set fd [open /tmp/12out/[pid] w]
 
150
                                puts $fd $res
 
151
                                close $fd
 
152
                        }
 
153
                        error_check_good recover($j) $ret 0
 
154
                }
 
155
 
 
156
        }
 
157
 
 
158
        # Run recovery one final time;  it doesn't make sense to
 
159
        # check integrity if we do not.
 
160
        set ret [catch {exec $util_path/db_recover -h $testdir} res]
 
161
        if { $ret != 0 } {
 
162
                puts "FAIL: db_recover returned with nonzero\
 
163
                    exit status, output as follows:"
 
164
                puts $res
 
165
        }
 
166
 
 
167
        # Make sure each datum is the correct filename.
 
168
        puts "\t\tRecd0$tnum.c: Checking data integrity."
 
169
        set dbenv [berkdb env -create -private -home $testdir]
 
170
        error_check_good env_open_integrity [is_valid_env $dbenv] TRUE
 
171
        set f [open TESTDIR/dblist r]
 
172
        set i 0
 
173
        while { [gets $f dbinfo] > 0 } {
 
174
                set db [eval berkdb_open -env $dbenv $dbinfo]
 
175
                error_check_good dbopen($dbinfo) [is_valid_db $db] TRUE
 
176
 
 
177
                set dbc [$db cursor]
 
178
                error_check_good cursor [is_valid_cursor $dbc $db] TRUE
 
179
 
 
180
                for { set dbt [$dbc get -first] } { [llength $dbt] > 0 } \
 
181
                    { set dbt [$dbc get -next] } {
 
182
                        error_check_good integrity [lindex [lindex $dbt 0] 1] \
 
183
                            [pad_data $method $dbinfo]
 
184
                }
 
185
                error_check_good dbc_close [$dbc close] 0
 
186
                error_check_good db_close [$db close] 0
 
187
        }
 
188
        close $f
 
189
        error_check_good env_close_integrity [$dbenv close] 0
 
190
 
 
191
        # Verify
 
192
        error_check_good verify \
 
193
            [verify_dir $testdir "\t\tRecd0$tnum.d: " 0 0 1] 0
 
194
}
 
195
 
 
196
proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
 
197
    ofname args } {
 
198
        global recd012_ofkey
 
199
        if { [is_record_based $method] } {
 
200
                set keybase ""
 
201
        } else {
 
202
                set keybase .[repeat abcdefghijklmnopqrstuvwxyz 4]
 
203
        }
 
204
 
 
205
        # Initialize our random number generator, repeatably based on an arg.
 
206
        berkdb srand $rnd
 
207
 
 
208
        # Open our env.
 
209
        set dbenv [eval $env_cmd]
 
210
        error_check_good env_open [is_valid_env $dbenv] TRUE
 
211
 
 
212
        # Find out how many databases appear to be open in the log--we
 
213
        # don't want recovery to run out of filehandles.
 
214
        set ofdb [berkdb_open -env $dbenv $ofname]
 
215
        set oftxn [$dbenv txn]
 
216
        error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
 
217
        set dbt [$ofdb get -txn $oftxn $recd012_ofkey]
 
218
        error_check_good of_get [lindex [lindex $dbt 0] 0] $recd012_ofkey
 
219
        set nopenfiles [lindex [lindex $dbt 0] 1]
 
220
 
 
221
        error_check_good of_commit [$oftxn commit] 0
 
222
 
 
223
        # Read our dbnames
 
224
        set f [open TESTDIR/dblist r]
 
225
        set i 0
 
226
        while { [gets $f dbname($i)] > 0 } {
 
227
                incr i
 
228
        }
 
229
        close $f
 
230
 
 
231
        # We now have $ndbs extant databases.
 
232
        # Open one of them, just to get us started.
 
233
        set opendbs {}
 
234
        set oflags "-env $dbenv $args"
 
235
 
 
236
        # Start a transaction, just to get us started.
 
237
        set curtxn [$dbenv txn]
 
238
        error_check_good txn [is_valid_txn $curtxn $dbenv] TRUE
 
239
 
 
240
        # Inner loop.  Do $in iterations of a random open, close, or
 
241
        # update, where $in is between 1 and $niniter.
 
242
        set in [berkdb random_int 1 $niniter]
 
243
        for { set j 0 } { $j < $in } { incr j } {
 
244
                set op [berkdb random_int 0 2]
 
245
                switch $op {
 
246
                0 {
 
247
                        # Open.
 
248
                        recd012_open
 
249
                }
 
250
                1 {
 
251
                        # Update.  Put random-number$keybase as key,
 
252
                        # filename as data, into random database.
 
253
                        set num_open [llength $opendbs]
 
254
                        if { $num_open == 0 } {
 
255
                                # If none are open, do an open first.
 
256
 
 
257
                                recd012_open
 
258
                        }
 
259
                        set n [berkdb random_int 0 [expr $num_open - 1]]
 
260
                        set pair [lindex $opendbs $n]
 
261
                        set udb [lindex $pair 0]
 
262
                        set uname [lindex $pair 1]
 
263
 
 
264
                        set key [berkdb random_int 1000 1999]$keybase
 
265
                        set data [chop_data $method $uname]
 
266
                        error_check_good put($uname,$udb,$key,$data) \
 
267
                            [$udb put -txn $curtxn $key $data] 0
 
268
 
 
269
                        # One time in four, commit the transaction.
 
270
                        if { [berkdb random_int 0 3] == 0 && 0 } {
 
271
                                error_check_good txn_recommit \
 
272
                                    [$curtxn commit] 0
 
273
                                set curtxn [$dbenv txn]
 
274
                                error_check_good txn_reopen \
 
275
                                    [is_valid_txn $curtxn $dbenv] TRUE
 
276
                        }
 
277
                }
 
278
                2 {
 
279
                        # Close.
 
280
 
 
281
                        if { [llength $opendbs] == 0 } {
 
282
                                # If none are open, open instead of closing.
 
283
                                recd012_open
 
284
                                continue
 
285
                        }
 
286
 
 
287
                        # Commit curtxn first, lest we self-deadlock.
 
288
                        error_check_good txn_recommit \
 
289
                            [$curtxn commit] 0
 
290
 
 
291
                        # Do it.
 
292
                        set which [berkdb random_int 0 \
 
293
                            [expr [llength $opendbs] - 1]]
 
294
 
 
295
                        set db [lindex [lindex $opendbs $which] 0]
 
296
                        error_check_good db_choice [is_valid_db $db] TRUE
 
297
                        global errorCode errorInfo
 
298
 
 
299
                        error_check_good db_close \
 
300
                            [[lindex [lindex $opendbs $which] 0] close] 0
 
301
                        set opendbs [lreplace $opendbs $which $which]
 
302
                        incr nopenfiles -1
 
303
 
 
304
                        # Reopen txn.
 
305
                        set curtxn [$dbenv txn]
 
306
                        error_check_good txn_reopen \
 
307
                            [is_valid_txn $curtxn $dbenv] TRUE
 
308
 
 
309
                }
 
310
                }
 
311
 
 
312
                # One time in two hundred, checkpoint.
 
313
                if { [berkdb random_int 0 199] == 0 } {
 
314
                        puts "\t\t\tRecd0$tnum:\
 
315
                            Random checkpoint after operation $outiter.$j."
 
316
                        error_check_good txn_ckpt \
 
317
                            [$dbenv txn_checkpoint] 0
 
318
                        set nopenfiles \
 
319
                            [recd012_nopenfiles_ckpt $dbenv $ofdb $nopenfiles]
 
320
                }
 
321
        }
 
322
 
 
323
        # We have to commit curtxn.  It'd be kind of nice not to, but
 
324
        # if we start in again without running recovery, we may block
 
325
        # ourselves.
 
326
        error_check_good curtxn_commit [$curtxn commit] 0
 
327
 
 
328
        # Put back the new number of open files.
 
329
        set oftxn [$dbenv txn]
 
330
        error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
 
331
        error_check_good of_del [$ofdb del -txn $oftxn $recd012_ofkey] 0
 
332
        error_check_good of_put \
 
333
            [$ofdb put -txn $oftxn $recd012_ofkey $nopenfiles] 0
 
334
        error_check_good of_commit [$oftxn commit] 0
 
335
        error_check_good ofdb_close [$ofdb close] 0
 
336
}
 
337
 
 
338
proc recd012_open { } {
 
339
        # This is basically an inline and has to modify curtxn,
 
340
        # so use upvars.
 
341
        upvar curtxn curtxn
 
342
        upvar ndbs ndbs
 
343
        upvar dbname dbname
 
344
        upvar dbenv dbenv
 
345
        upvar oflags oflags
 
346
        upvar opendbs opendbs
 
347
        upvar nopenfiles nopenfiles
 
348
 
 
349
        # Return without an open if we've already opened too many files--
 
350
        # we don't want to make recovery run out of filehandles.
 
351
        if { $nopenfiles > 30 } {
 
352
                #puts "skipping--too many open files"
 
353
                return -code break
 
354
        }
 
355
 
 
356
        # Commit curtxn first, lest we self-deadlock.
 
357
        error_check_good txn_recommit \
 
358
            [$curtxn commit] 0
 
359
 
 
360
        # Do it.
 
361
        set which [berkdb random_int 0 [expr $ndbs - 1]]
 
362
        set db [eval berkdb_open \
 
363
            $oflags $dbname($which)]
 
364
        lappend opendbs [list $db $dbname($which)]
 
365
 
 
366
        # Reopen txn.
 
367
        set curtxn [$dbenv txn]
 
368
        error_check_good txn_reopen \
 
369
            [is_valid_txn $curtxn $dbenv] TRUE
 
370
 
 
371
        incr nopenfiles
 
372
}
 
373
 
 
374
# Update the database containing the number of files that db_recover has
 
375
# to contend with--we want to avoid letting it run out of file descriptors.
 
376
# We do this by keeping track of the number of unclosed opens since the
 
377
# checkpoint before last.
 
378
# $recd012_ofkey stores this current value;  the two dups available
 
379
# at $recd012_ofckptkey store the number of opens since the last checkpoint
 
380
# previous.
 
381
# Thus, if the current value is 17 when we do a checkpoint, and the
 
382
# stored values are 3 and 8, the new current value (which we return)
 
383
# is 14, and the new stored values are 8 and 6.
 
384
proc recd012_nopenfiles_ckpt { env db nopenfiles } {
 
385
        global recd012_ofckptkey
 
386
        set txn [$env txn]
 
387
        error_check_good nopenfiles_ckpt_txn [is_valid_txn $txn $env] TRUE
 
388
 
 
389
        set dbc [$db cursor -txn $txn]
 
390
        error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
 
391
 
 
392
        # Get the first ckpt value and delete it.
 
393
        set dbt [$dbc get -set $recd012_ofckptkey]
 
394
        error_check_good set [llength $dbt] 1
 
395
 
 
396
        set discard [lindex [lindex $dbt 0] 1]
 
397
        error_check_good del [$dbc del] 0
 
398
 
 
399
        set nopenfiles [expr $nopenfiles - $discard]
 
400
 
 
401
        # Get the next ckpt value
 
402
        set dbt [$dbc get -nextdup]
 
403
        error_check_good set2 [llength $dbt] 1
 
404
 
 
405
        # Calculate how many opens we've had since this checkpoint before last.
 
406
        set onlast [lindex [lindex $dbt 0] 1]
 
407
        set sincelast [expr $nopenfiles - $onlast]
 
408
 
 
409
        # Put this new number at the end of the dup set.
 
410
        error_check_good put [$dbc put -keylast $recd012_ofckptkey $sincelast] 0
 
411
 
 
412
        # We should never deadlock since we're the only one in this db.
 
413
        error_check_good dbc_close [$dbc close] 0
 
414
        error_check_good txn_commit [$txn commit] 0
 
415
 
 
416
        return $nopenfiles
 
417
}
 
418
 
 
419
# globals -- it's not worth passing these around, as they're constants
 
420
set recd012_ofkey OPENFILES
 
421
set recd012_ofckptkey CKPTS