summaryrefslogtreecommitdiff
path: root/db-4.8.30/test/recd013.tcl
blob: 7d40cd88fdd06570c9377db2d43fcc3c5927e546 (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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2000-2009 Oracle.  All rights reserved.
#
# $Id$
#
# TEST	recd013
# TEST	Test of cursor adjustment on child transaction aborts. [#2373]
#
# XXX
# Other tests that cover more specific variants of the same issue
# are in the access method tests for now.  This is probably wrong;  we
# put this one here because they're closely based on and intertwined
# with other, non-transactional cursor stability tests that are among
# the access method tests, and because we need at least one test to
# fit under recd and keep logtrack from complaining.  We'll sort out the mess
# later;  the important thing, for now, is that everything that needs to gets
# tested.  (This really shouldn't be under recd at all, since it doesn't
# run recovery!)
proc recd013 { method { nitems 100 } args } {
	source ./include.tcl
	global alphabet log_log_record_types

	set args [convert_args $method $args]
	set omethod [convert_method $method]
	set tnum "013"
	set pgsz 512

	if  { [is_partition_callback $args] == 1 } {
		set nodump 1
	} else {
		set nodump 0
	}

	puts "Recd$tnum $method ($args): Test of aborted cursor adjustments."
	set pgindex [lsearch -exact $args "-pagesize"]
	if { $pgindex != -1 } {
		puts "Recd013: skipping for specific pagesizes"
		return
	}

	set testfile recd$tnum.db
	env_cleanup $testdir

	set i 0
	if { [is_record_based $method] == 1 } {
		set keybase ""
	} else {
		set keybase "key"
	}

	puts "\tRecd$tnum.a:\
	    Create environment, database, and parent transaction."
	set flags "-create -txn -home $testdir"

	set env_cmd "berkdb_env $flags"
	set env [eval $env_cmd]
	error_check_good dbenv [is_valid_env $env] TRUE

	set oflags \
    "-auto_commit -env $env -create -mode 0644 -pagesize $pgsz $args $omethod"
	set db [eval {berkdb_open} $oflags $testfile]
	error_check_good dbopen [is_valid_db $db] TRUE

	# Create a database containing $nitems items, numbered with odds.
	# We'll then put the even numbers during the body of the test.
	set txn [$env txn]
	error_check_good init_txn [is_valid_txn $txn $env] TRUE
	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		set key $keybase$i
		set data [chop_data $method $i$alphabet]

		# First, try to put the item in a child transaction,
		# then abort and verify all the cursors we've done up until
		# now.
		set ctxn [$env txn -parent $txn]
		error_check_good child_txn($i) [is_valid_txn $ctxn $env] TRUE
		error_check_good fake_put($i) [$db put -txn $ctxn $key $data] 0
		error_check_good ctxn_abort($i) [$ctxn abort] 0
		for { set j 1 } { $j < $i } { incr j 2 } {
			error_check_good dbc_get($j):1 [$dbc($j) get -current] \
			    [list [list $keybase$j \
			    [pad_data $method $j$alphabet]]]
		}

		# Then put for real.
		error_check_good init_put($i) [$db put -txn $txn $key $data] 0

		# Set a cursor of the parent txn to each item.
		set dbc($i) [$db cursor -txn $txn]
		error_check_good dbc_getset($i) \
		    [$dbc($i) get -set $key] \
		    [list [list $keybase$i [pad_data $method $i$alphabet]]]

		# And verify all the cursors, including the one we just
		# created.
		for { set j 1 } { $j <= $i } { incr j 2 } {
			error_check_good dbc_get($j):2 [$dbc($j) get -current] \
			    [list [list $keybase$j \
			    [pad_data $method $j$alphabet]]]
		}
	}

	puts "\t\tRecd$tnum.a.1: Verify cursor stability after init."
	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		error_check_good dbc_get($i):3 [$dbc($i) get -current] \
		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
	}

	puts "\tRecd$tnum.b: Put test."
	puts "\t\tRecd$tnum.b.1: Put items."
	set ctxn [$env txn -parent $txn]
	error_check_good txn [is_valid_txn $ctxn $env] TRUE
	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
		set key $keybase$i
		set data [chop_data $method $i$alphabet]
		error_check_good child_put($i) [$db put -txn $ctxn $key $data] 0

		# If we're a renumbering recno, this is uninteresting.
		# Stir things up by putting a few additional records at
		# the beginning.
		if { [is_rrecno $method] == 1 } {
			set curs [$db cursor -txn $ctxn]
			error_check_bad llength_get_first \
			    [llength [$curs get -first]] 0
			error_check_good cursor [is_valid_cursor $curs $db] TRUE
			# expect a recno!
			error_check_good rrecno_put($i) \
			    [$curs put -before ADDITIONAL.$i] 1
			error_check_good curs_close [$curs close] 0
		}
	}

	puts "\t\tRecd$tnum.b.2: Verify cursor stability after abort."
	error_check_good ctxn_abort [$ctxn abort] 0

	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		error_check_good dbc_get($i):4 [$dbc($i) get -current] \
		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
	}

	# Clean up cursors.
	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		error_check_good dbc($i)_close [$dbc($i) close] 0
	}

	# Sync and verify.
	error_check_good txn_commit [$txn commit] 0
	set txn [$env txn]
	error_check_good txn [is_valid_txn $txn $env] TRUE

	error_check_good db_sync [$db sync] 0
	error_check_good db_verify \
	    [verify_dir $testdir "\t\tRecd$tnum.b.3: " 0 0 $nodump] 0

	# Now put back all the even records, this time in the parent.
	# Commit and re-begin the transaction so we can abort and
	# get back to a nice full database.
	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
		set key $keybase$i
		set data [chop_data $method $i$alphabet]
		error_check_good child_put($i) [$db put -txn $txn $key $data] 0
	}
	error_check_good txn_commit [$txn commit] 0
	set txn [$env txn]
	error_check_good txn [is_valid_txn $txn $env] TRUE

	# Delete test.  Set a cursor to each record.  Delete the even ones
	# in the parent and check cursor stability.  Then open a child
	# transaction, and delete the odd ones.  Verify that the database
	# is empty.
	puts "\tRecd$tnum.c: Delete test."
	unset dbc

	# Create cursors pointing at each item.
	for { set i 1 } { $i <= 2 * $nitems } { incr i } {
		set dbc($i) [$db cursor -txn $txn]
		error_check_good dbc($i)_create [is_valid_cursor $dbc($i) $db] \
		    TRUE
		error_check_good dbc_getset($i) [$dbc($i) get -set $keybase$i] \
		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
	}

	puts "\t\tRecd$tnum.c.1: Delete even items in child txn and abort."

	if { [is_rrecno $method] != 1 } {
		set init 2
		set bound [expr 2 * $nitems]
		set step 2
	} else {
		# In rrecno, deletes will renumber the items, so we have
		# to take that into account when we delete by recno.
		set init 2
		set bound [expr $nitems + 1]
		set step 1
	}

	set ctxn [$env txn -parent $txn]
	for { set i $init } { $i <= $bound } { incr i $step } {
		error_check_good del($i) [$db del -txn $ctxn $keybase$i] 0
	}
	error_check_good ctxn_abort [$ctxn abort] 0

	# Verify that no items are deleted.
	for { set i 1 } { $i <= 2 * $nitems } { incr i } {
		error_check_good dbc_get($i):5 [$dbc($i) get -current] \
		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
	}

	puts "\t\tRecd$tnum.c.2: Delete even items in child txn and commit."
	set ctxn [$env txn -parent $txn]
	for { set i $init } { $i <= $bound } { incr i $step } {
		error_check_good del($i) [$db del -txn $ctxn $keybase$i] 0
	}
	error_check_good ctxn_commit [$ctxn commit] 0

	# Verify that even items are deleted and odd items are not.
	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		if { [is_rrecno $method] != 1 } {
			set j $i
		} else {
			set j [expr ($i - 1) / 2 + 1]
		}
		error_check_good dbc_get($i):6 [$dbc($i) get -current] \
		    [list [list $keybase$j [pad_data $method $i$alphabet]]]
	}
	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
		error_check_good dbc_get($i):7 [$dbc($i) get -current] ""
	}

	puts "\t\tRecd$tnum.c.3: Delete odd items in child txn."

	set ctxn [$env txn -parent $txn]

	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		if { [is_rrecno $method] != 1 } {
			set j $i
		} else {
			# If this is an rrecno, just delete the first
			# item repeatedly--the renumbering will make
			# that delete everything.
			set j 1
		}
		error_check_good del($i) [$db del -txn $ctxn $keybase$j] 0
	}

	# Verify that everyone's deleted.
	for { set i 1 } { $i <= 2 * $nitems } { incr i } {
		error_check_good get_deleted($i) \
		    [llength [$db get -txn $ctxn $keybase$i]] 0
	}

	puts "\t\tRecd$tnum.c.4: Verify cursor stability after abort."
	error_check_good ctxn_abort [$ctxn abort] 0

	# Verify that even items are deleted and odd items are not.
	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
		if { [is_rrecno $method] != 1 } {
			set j $i
		} else {
			set j [expr ($i - 1) / 2 + 1]
		}
		error_check_good dbc_get($i):8 [$dbc($i) get -current] \
		    [list [list $keybase$j [pad_data $method $i$alphabet]]]
	}
	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
		error_check_good dbc_get($i):9 [$dbc($i) get -current] ""
	}

	# Clean up cursors.
	for { set i 1 } { $i <= 2 * $nitems } { incr i } {
		error_check_good dbc($i)_close [$dbc($i) close] 0
	}

	# Sync and verify.
	error_check_good db_sync [$db sync] 0
	error_check_good db_verify \
	    [verify_dir $testdir "\t\tRecd$tnum.c.5: " 0 0 $nodump] 0

	puts "\tRecd$tnum.d: Clean up."
	error_check_good txn_commit [$txn commit] 0
	error_check_good db_close [$db close] 0
	error_check_good log_flush [$env log_flush] 0
	error_check_good env_close [$env close] 0
	error_check_good verify_dir \
	    [verify_dir $testdir "\t\tRecd$tnum.d.1: " 0 0 $nodump] 0

	if { $log_log_record_types == 1 } {
		logtrack_read $testdir
	}
}