summaryrefslogtreecommitdiff
path: root/storage/bdb/test/test044.tcl
blob: 67cf3ea24b8fa433e9531853a17920a2745aa268 (plain)
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
# See the file LICENSE for redistribution information.
#
# Copyright (c) 1996-2002
#	Sleepycat Software.  All rights reserved.
#
# $Id: test044.tcl,v 11.32 2002/07/16 20:53:04 bostic Exp $
#
# TEST	test044
# TEST	Small system integration tests
# TEST		Test proper functioning of the checkpoint daemon,
# TEST		recovery, transactions, etc.
# TEST
# TEST	System integration DB test: verify that locking, recovery, checkpoint,
# TEST	and all the other utilities basically work.
# TEST
# TEST	The test consists of $nprocs processes operating on $nfiles files.  A
# TEST	transaction consists of adding the same key/data pair to some random
# TEST	number of these files.  We generate a bimodal distribution in key size
# TEST	with 70% of the keys being small (1-10 characters) and the remaining
# TEST	30% of the keys being large (uniform distribution about mean $key_avg).
# TEST	If we generate a key, we first check to make sure that the key is not
# TEST	already in the dataset.  If it is, we do a lookup.
#
# XXX
# This test uses grow-only files currently!
proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
	source ./include.tcl
	global encrypt
	global rand_init

	set args [convert_args $method $args]
	set omethod [convert_method $method]

	berkdb srand $rand_init

	# If we are using an env, then skip this test.  It needs its own.
	set eindex [lsearch -exact $args "-env"]
	if { $eindex != -1 } {
		incr eindex
		set env [lindex $args $eindex]
		puts "Test044 skipping for env $env"
		return
	}
	if { $encrypt != 0 } {
		puts "Test044 skipping for security"
		return
	}

	puts "Test044: system integration test db $method $nprocs processes \
	    on $nfiles files"

	# Parse options
	set otherargs ""
	set key_avg 10
	set data_avg 20
	set do_exit 0
	for { set i 0 } { $i < [llength $args] } {incr i} {
		switch -regexp -- [lindex $args $i] {
			-key_avg { incr i; set key_avg [lindex $args $i] }
			-data_avg { incr i; set data_avg [lindex $args $i] }
			-testdir { incr i; set testdir [lindex $args $i] }
			-x.* { set do_exit 1 }
			default {
				lappend otherargs [lindex $args $i]
			}
		}
	}

	if { $cont == 0 } {
		# Create the database and open the dictionary
		env_cleanup $testdir

		# Create an environment
		puts "\tTest044.a: creating environment and $nfiles files"
		set dbenv [berkdb_env -create -txn -home $testdir]
		error_check_good env_open [is_valid_env $dbenv] TRUE

		# Create a bunch of files
		set m $method

		for { set i 0 } { $i < $nfiles } { incr i } {
			if { $method == "all" } {
				switch [berkdb random_int 1 2] {
				1 { set m -btree }
				2 { set m -hash }
				}
			} else {
				set m $omethod
			}

			set db [eval {berkdb_open -env $dbenv -create \
			    -mode 0644 $m} $otherargs {test044.$i.db}]
			error_check_good dbopen [is_valid_db $db] TRUE
			error_check_good db_close [$db close] 0
		}
	}

	# Close the environment
	$dbenv close

	if { $do_exit == 1 } {
		return
	}

	# Database is created, now fork off the kids.
	puts "\tTest044.b: forking off $nprocs processes and utilities"
	set cycle 1
	set ncycles 3
	while { $cycle <= $ncycles } {
		set dbenv [berkdb_env -create -txn -home $testdir]
		error_check_good env_open [is_valid_env $dbenv] TRUE

		# Fire off deadlock detector and checkpointer
		puts "Beginning cycle $cycle"
		set ddpid [exec $util_path/db_deadlock -h $testdir -t 5 &]
		set cppid [exec $util_path/db_checkpoint -h $testdir -p 2 &]
		puts "Deadlock detector: $ddpid Checkpoint daemon $cppid"

		set pidlist {}
		for { set i 0 } {$i < $nprocs} {incr i} {
			set p [exec $tclsh_path \
			    $test_path/sysscript.tcl $testdir \
			    $nfiles $key_avg $data_avg $omethod \
			    >& $testdir/test044.$i.log &]
			lappend pidlist $p
		}
		set sleep [berkdb random_int 300 600]
		puts \
"[timestamp] $nprocs processes running $pidlist for $sleep seconds"
		tclsleep $sleep

		# Now simulate a crash
		puts "[timestamp] Crashing"

		#
		# The environment must remain open until this point to get
		# proper sharing (using the paging file) on Win/9X.  [#2342]
		#
		error_check_good env_close [$dbenv close] 0

		tclkill $ddpid
		tclkill $cppid

		foreach p $pidlist {
			tclkill $p
		}

		# Check for test failure
		set e [eval findfail [glob $testdir/test044.*.log]]
		error_check_good "FAIL: error message(s) in log files" $e 0

		# Now run recovery
		test044_verify $testdir $nfiles
		incr cycle
	}
}

proc test044_usage { } {
	puts -nonewline "test044 method nentries [-d directory] [-i iterations]"
	puts " [-p procs] -x"
}

proc test044_verify { dir nfiles } {
	source ./include.tcl

	# Save everything away in case something breaks
#	for { set f 0 } { $f < $nfiles } {incr f} {
#		file copy -force $dir/test044.$f.db $dir/test044.$f.save1
#	}
#	foreach f [glob $dir/log.*] {
#		if { [is_substr $f save] == 0 } {
#			file copy -force $f $f.save1
#		}
#	}

	# Run recovery and then read through all the database files to make
	# sure that they all look good.

	puts "\tTest044.verify: Running recovery and verifying file contents"
	set stat [catch {exec $util_path/db_recover -h $dir} result]
	if { $stat == 1 } {
		error "FAIL: Recovery error: $result."
	}

	# Save everything away in case something breaks
#	for { set f 0 } { $f < $nfiles } {incr f} {
#		file copy -force $dir/test044.$f.db $dir/test044.$f.save2
#	}
#	foreach f [glob $dir/log.*] {
#		if { [is_substr $f save] == 0 } {
#			file copy -force $f $f.save2
#		}
#	}

	for { set f 0 } { $f < $nfiles } { incr f } {
		set db($f) [berkdb_open $dir/test044.$f.db]
		error_check_good $f:dbopen [is_valid_db $db($f)] TRUE

		set cursors($f) [$db($f) cursor]
		error_check_bad $f:cursor_open $cursors($f) NULL
		error_check_good \
		    $f:cursor_open [is_substr $cursors($f) $db($f)] 1
	}

	for { set f 0 } { $f < $nfiles } { incr f } {
		for {set d [$cursors($f) get -first] } \
		    { [string length $d] != 0 } \
		    { set d [$cursors($f) get -next] } {

			set k [lindex [lindex $d 0] 0]
			set d [lindex [lindex $d 0] 1]

			set flist [zero_list $nfiles]
			set r $d
			while { [set ndx [string first : $r]] != -1 } {
				set fnum [string range $r 0 [expr $ndx - 1]]
				if { [lindex $flist $fnum] == 0 } {
					set fl "-set"
				} else {
					set fl "-next"
				}

				if { $fl != "-set" || $fnum != $f } {
					if { [string compare $fl "-set"] == 0} {
						set full [$cursors($fnum) \
						    get -set $k]
					} else  {
						set full [$cursors($fnum) \
						    get -next]
					}
					set key [lindex [lindex $full 0] 0]
					set rec [lindex [lindex $full 0] 1]
					error_check_good \
					    $f:dbget_$fnum:key $key $k
					error_check_good \
					    $f:dbget_$fnum:data $rec $d
				}

				set flist [lreplace $flist $fnum $fnum 1]
				incr ndx
				set r [string range $r $ndx end]
			}
		}
	}

	for { set f 0 } { $f < $nfiles } { incr f } {
		error_check_good $cursors($f) [$cursors($f) close] 0
		error_check_good db_close:$f [$db($f) close] 0
	}
}