1
# See the file LICENSE for redistribution information.
3
# Copyright (c) 1999-2002
4
# Sleepycat Software. All rights reserved.
9
# TEST Test of cursor stability when converting to and modifying
10
# TEST off-page duplicate pages with subtransaction aborts. [#2373]
12
# TEST Does the following:
13
# TEST a. Initialize things by DB->putting ndups dups and
14
# TEST setting a reference cursor to point to each. Do each put twice,
15
# TEST first aborting, then committing, so we're sure to abort the move
16
# TEST to off-page dups at some point.
17
# TEST b. c_put ndups dups (and correspondingly expanding
18
# TEST the set of reference cursors) after the last one, making sure
19
# TEST after each step that all the reference cursors still point to
20
# TEST the right item.
21
# TEST c. Ditto, but before the first one.
22
# TEST d. Ditto, but after each one in sequence first to last.
23
# TEST e. Ditto, but after each one in sequence from last to first.
24
# TEST occur relative to the new datum)
25
# TEST f. Ditto for the two sequence tests, only doing a
26
# TEST DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
28
proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
32
set args [convert_args $method $args]
34
set args [split_encargs $args encargs]
35
set omethod [convert_method $method]
37
puts "Test0$tnum $omethod ($args): "
38
set eindex [lsearch -exact $args "-env"]
40
# If we are using an env, then return
41
if { $eindex != -1 } {
42
puts "Environment specified; skipping."
45
set pgindex [lsearch -exact $args "-pagesize"]
46
if { $pgindex != -1 } {
47
puts "Test087: skipping for specific pagesizes"
51
set testfile test0$tnum.db
53
append args " -pagesize $pagesize -dup"
55
if { [is_record_based $method] || [is_rbtree $method] } {
56
puts "Skipping for method $method."
59
puts "Cursor stability on dup. pages w/ aborts."
62
set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
63
error_check_good env_create [is_valid_env $env] TRUE
65
set db [eval {berkdb_open -auto_commit \
66
-create -env $env -mode 0644} $omethod $args $testfile]
67
error_check_good "db open" [is_valid_db $db] TRUE
69
# Number of outstanding keys.
72
puts "\tTest0$tnum.a: put/abort/put/commit loop;\
73
$ndups dups, short data."
75
error_check_good txn [is_valid_txn $txn $env] TRUE
76
for { set i 0 } { $i < $ndups } { incr i } {
77
set datum [makedatum_t73 $i 0]
79
set ctxn [$env txn -parent $txn]
80
error_check_good ctxn(abort,$i) [is_valid_txn $ctxn $env] TRUE
81
error_check_good "db put/abort ($i)" \
82
[$db put -txn $ctxn $key $datum] 0
83
error_check_good ctxn_abort($i) [$ctxn abort] 0
85
verify_t73 is_long dbc [expr $i - 1] $key
87
set ctxn [$env txn -parent $txn]
88
error_check_good ctxn(commit,$i) [is_valid_txn $ctxn $env] TRUE
89
error_check_good "db put/commit ($i)" \
90
[$db put -txn $ctxn $key $datum] 0
91
error_check_good ctxn_commit($i) [$ctxn commit] 0
95
set dbc($i) [$db cursor -txn $txn]
96
error_check_good "db cursor ($i)"\
97
[is_valid_cursor $dbc($i) $db] TRUE
98
error_check_good "dbc get -get_both ($i)"\
99
[$dbc($i) get -get_both $key $datum]\
100
[list [list $key $datum]]
102
verify_t73 is_long dbc $i $key
105
puts "\tTest0$tnum.b: Cursor put (DB_KEYLAST); $ndups new dups,\
108
set ctxn [$env txn -parent $txn]
109
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
110
for { set i 0 } { $i < $ndups } { incr i } {
111
# !!! keys contains the number of the next dup
112
# to be added (since they start from zero)
113
set datum [makedatum_t73 $keys 0]
114
set curs [$db cursor -txn $ctxn]
115
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
117
error_check_good "c_put(DB_KEYLAST, $keys)"\
118
[$curs put -keylast $key $datum] 0
120
# We can't do a verification while a child txn is active,
121
# or we'll run into trouble when DEBUG_ROP is enabled.
122
# If this test has trouble, though, uncommenting this
123
# might be illuminating--it makes things a bit more rigorous
124
# and works fine when DEBUG_ROP is not enabled.
125
# verify_t73 is_long dbc $keys $key
126
error_check_good curs_close [$curs close] 0
128
error_check_good ctxn_abort [$ctxn abort] 0
129
verify_t73 is_long dbc $keys $key
131
puts "\tTest0$tnum.c: Cursor put (DB_KEYFIRST); $ndups new dups,\
134
set ctxn [$env txn -parent $txn]
135
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
136
for { set i 0 } { $i < $ndups } { incr i } {
137
# !!! keys contains the number of the next dup
138
# to be added (since they start from zero)
140
set datum [makedatum_t73 $keys 0]
141
set curs [$db cursor -txn $ctxn]
142
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
144
error_check_good "c_put(DB_KEYFIRST, $keys)"\
145
[$curs put -keyfirst $key $datum] 0
147
# verify_t73 is_long dbc $keys $key
148
error_check_good curs_close [$curs close] 0
150
# verify_t73 is_long dbc $keys $key
151
# verify_t73 is_long dbc $keys $key
152
error_check_good ctxn_abort [$ctxn abort] 0
153
verify_t73 is_long dbc $keys $key
155
puts "\tTest0$tnum.d: Cursor put (DB_AFTER) first to last;\
156
$keys new dups, short data"
157
# We want to add a datum after each key from 0 to the current
158
# value of $keys, which we thus need to save.
159
set ctxn [$env txn -parent $txn]
160
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
162
for { set i 0 } { $i < $keysnow } { incr i } {
163
set datum [makedatum_t73 $keys 0]
164
set curs [$db cursor -txn $ctxn]
165
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
168
# Which datum to insert this guy after.
169
set curdatum [makedatum_t73 $i 0]
170
error_check_good "c_get(DB_GET_BOTH, $i)"\
171
[$curs get -get_both $key $curdatum]\
172
[list [list $key $curdatum]]
173
error_check_good "c_put(DB_AFTER, $i)"\
174
[$curs put -after $datum] 0
176
# verify_t73 is_long dbc $keys $key
177
error_check_good curs_close [$curs close] 0
179
error_check_good ctxn_abort [$ctxn abort] 0
180
verify_t73 is_long dbc $keys $key
182
puts "\tTest0$tnum.e: Cursor put (DB_BEFORE) last to first;\
183
$keys new dups, short data"
184
set ctxn [$env txn -parent $txn]
185
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
186
for { set i [expr $keys - 1] } { $i >= 0 } { incr i -1 } {
187
set datum [makedatum_t73 $keys 0]
188
set curs [$db cursor -txn $ctxn]
189
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
192
# Which datum to insert this guy before.
193
set curdatum [makedatum_t73 $i 0]
194
error_check_good "c_get(DB_GET_BOTH, $i)"\
195
[$curs get -get_both $key $curdatum]\
196
[list [list $key $curdatum]]
197
error_check_good "c_put(DB_BEFORE, $i)"\
198
[$curs put -before $datum] 0
200
# verify_t73 is_long dbc $keys $key
201
error_check_good curs_close [$curs close] 0
203
error_check_good ctxn_abort [$ctxn abort] 0
204
verify_t73 is_long dbc $keys $key
206
puts "\tTest0$tnum.f: Cursor put (DB_CURRENT), first to last,\
208
set ctxn [$env txn -parent $txn]
209
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
210
for { set i 0 } { $i < $keysnow } { incr i } {
211
set olddatum [makedatum_t73 $i 0]
212
set newdatum [makedatum_t73 $i 1]
213
set curs [$db cursor -txn $ctxn]
214
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
217
error_check_good "c_get(DB_GET_BOTH, $i)"\
218
[$curs get -get_both $key $olddatum]\
219
[list [list $key $olddatum]]
220
error_check_good "c_put(DB_CURRENT, $i)"\
221
[$curs put -current $newdatum] 0
225
# verify_t73 is_long dbc $keys $key
226
error_check_good curs_close [$curs close] 0
228
error_check_good ctxn_abort [$ctxn abort] 0
229
for { set i 0 } { $i < $keysnow } { incr i } {
232
verify_t73 is_long dbc $keys $key
234
# Now delete the first item, abort the deletion, and make sure
236
puts "\tTest0$tnum.g: Cursor delete first item, then abort delete."
237
set ctxn [$env txn -parent $txn]
238
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
239
set curs [$db cursor -txn $ctxn]
240
error_check_good "db cursor create" [is_valid_cursor $curs $db] TRUE
241
set datum [makedatum_t73 0 0]
242
error_check_good "c_get(DB_GET_BOTH, 0)"\
243
[$curs get -get_both $key $datum] [list [list $key $datum]]
244
error_check_good "c_del(0)" [$curs del] 0
245
error_check_good curs_close [$curs close] 0
246
error_check_good ctxn_abort [$ctxn abort] 0
247
verify_t73 is_long dbc $keys $key
249
# Ditto, for the last item.
250
puts "\tTest0$tnum.h: Cursor delete last item, then abort delete."
251
set ctxn [$env txn -parent $txn]
252
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
253
set curs [$db cursor -txn $ctxn]
254
error_check_good "db cursor create" [is_valid_cursor $curs $db] TRUE
255
set datum [makedatum_t73 [expr $keys - 1] 0]
256
error_check_good "c_get(DB_GET_BOTH, [expr $keys - 1])"\
257
[$curs get -get_both $key $datum] [list [list $key $datum]]
258
error_check_good "c_del(0)" [$curs del] 0
259
error_check_good curs_close [$curs close] 0
260
error_check_good ctxn_abort [$ctxn abort] 0
261
verify_t73 is_long dbc $keys $key
263
# Ditto, for all the items.
264
puts "\tTest0$tnum.i: Cursor delete all items, then abort delete."
265
set ctxn [$env txn -parent $txn]
266
error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
267
set curs [$db cursor -txn $ctxn]
268
error_check_good "db cursor create" [is_valid_cursor $curs $db] TRUE
269
set datum [makedatum_t73 0 0]
270
error_check_good "c_get(DB_GET_BOTH, 0)"\
271
[$curs get -get_both $key $datum] [list [list $key $datum]]
272
error_check_good "c_del(0)" [$curs del] 0
273
for { set i 1 } { $i < $keys } { incr i } {
274
error_check_good "c_get(DB_NEXT, $i)"\
275
[$curs get -next] [list [list $key [makedatum_t73 $i 0]]]
276
error_check_good "c_del($i)" [$curs del] 0
278
error_check_good curs_close [$curs close] 0
279
error_check_good ctxn_abort [$ctxn abort] 0
280
verify_t73 is_long dbc $keys $key
283
puts "\tTest0$tnum.j: Closing cursors."
284
for { set i 0 } { $i < $keys } { incr i } {
285
error_check_good "dbc close ($i)" [$dbc($i) close] 0
287
error_check_good "db close" [$db close] 0
288
error_check_good txn_commit [$txn commit] 0
289
error_check_good "env close" [$env close] 0