libdb/test/tcl/test133.tcl
2011-09-13 13:44:24 -04:00

183 lines
5.4 KiB
Tcl

# See the file LICENSE for redistribution information.
#
# Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
#
# $Id$
#
# TEST test133
# TEST Test Cursor Cleanup.
# TEST Open a primary database and a secondary database,
# TEST then open 3 cursors on the secondary database, and
# TEST point them at the first item.
# TEST Do the following operations in loops:
# TEST * The 1st cursor will delete the current item.
# TEST * The 2nd cursor will also try to delete the current item.
# TEST * Move all the 3 cursors to get the next item and check the returns.
# TEST Finally, move the 3rd cursor once.
proc test133 {method {nentries 1000} {tnum "133"} {subdb 0} args} {
source ./include.tcl
# For rrecno, when keys are deleted, the ones after will move forward,
# and the keys change, which is not good to verify after delete.
# Therefore we skip rrecno method.
if {[is_rrecno $method]} {
puts "Skipping test$tnum for $method test."
return
}
set sub_msg ""
# Check if we use sub database.
if { $subdb } {
if {[is_queue $method]} {
puts "Skipping test$tnum with sub database for $method."
return
}
if {[is_partitioned $args]} {
puts "Skipping test$tnum with sub database\
for partitioned $method test."
return
}
if {[is_heap $method]} {
puts "Skipping test$tnum with sub database\
for $method."
return
}
set sub_msg "using sub databases"
}
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
set eindex [lsearch -exact $args "-env"]
set txnenv 0
if { $eindex == -1 } {
if {$subdb} {
puts "Skipping test$tnum $sub_msg for non-env test."
return
}
set basename $testdir/test$tnum
set env NULL
} else {
set basename test$tnum
incr eindex
set env [lindex $args $eindex]
set txnenv [is_txnenv $env]
if { $txnenv == 1 } {
append args " -auto_commit "
}
set testdir [get_home $env]
}
cleanup $testdir $env
set sec_args $args
set args [convert_args $method $args]
puts "Test$tnum: $method ($args)\
Cursor Cleanup Test $sub_msg."
set secdb_types {"-btree" "-hash"}
set i 0
foreach sec_method $secdb_types {
test133_sub "\tTest$tnum.$i" $basename $subdb $method $args \
$sec_method $sec_args $i
incr i
}
}
proc test133_sub { prefix basename use_subdb pri_method pri_args
sec_method sec_args indx } {
global alphabet
upvar txnenv txnenv
upvar env env
upvar nentries nentries
# We can not set partition keys to hash.
if {[is_partitioned $sec_args] && ![is_partition_callback $sec_args] \
&& [is_hash $sec_method]} {
puts "Skipping for $sec_method with $sec_args."
return
}
if { $use_subdb } {
set pri_testfile $basename.$indx.db
set pri_subname "primary"
set sec_testfile $basename.$indx.db
set sec_subname "secondary"
} else {
set pri_testfile $basename.$indx-primary.db
set pri_subname ""
set sec_testfile $basename.$indx-secondary.db
set sec_subname ""
}
puts "$prefix.a: Open the primary database."
set pri_omethod [convert_method $pri_method]
set db [eval {berkdb_open_noerr -create -mode 0644} \
$pri_args $pri_omethod $pri_testfile $pri_subname]
error_check_good dbopen [is_valid_db $db] TRUE
# Open a simple dupsort database.
# In order to be consistent, we need to use all the passed-in
# am-unrelated flags.
puts "$prefix.b: Open the secondary ($sec_method) database."
set sec_db [eval {berkdb_open_noerr -create -mode 0644} $sec_args \
-dup -dupsort $sec_method $sec_testfile $sec_subname]
error_check_good secdb_open [is_valid_db $sec_db] TRUE
set ret [$db associate -create [callback_n 1] $sec_db]
error_check_good db_associate $ret 0
set txn ""
if { $txnenv == 1 } {
set t [$env txn]
error_check_good txn [is_valid_txn $t $env] TRUE
set txn "-txn $t"
}
puts "$prefix.c: Putting data into the primary database."
for {set i 1} {$i <= $nentries} {incr i} {
error_check_good "put_$i" [eval $db put $txn \
$i [make_fixed_length $pri_method $i.$alphabet]] 0
}
puts "$prefix.d: Opening three cursors on secondary database."
set cursor1 [eval $sec_db cursor $txn]
set cursor2 [eval $sec_db cursor $txn]
set cursor3 [eval $sec_db cursor $txn]
puts "$prefix.e: Deleting records using the 1st cursor."
set delcnt [expr $nentries / 2]
for {set i 0} {$i < $delcnt} {incr i} {
set ret1 [$cursor1 get -next]
set ret2 [$cursor2 get -next]
set ret3 [$cursor3 get -next]
error_check_good cmp_1_2 $ret1 $ret2
error_check_good cmp_1_3 $ret1 $ret3
error_check_good cursor1_del [eval $cursor1 del] 0
set ret [catch {eval $cursor2 del} res]
error_check_good {Check DB_NOTFOUND/DB_KEYEMPTY} \
[expr [is_substr $res DB_NOTFOUND] || \
[is_substr $res DB_KEYEMPTY]] 1
}
error_check_good cursor1_close [$cursor1 close] 0
error_check_good cursor2_close [$cursor2 close] 0
# The 3rd cursor is the final cursor pointing to the deleted item.
# Usually, when the last cursor moves after all the deleted items,
# these deleted items will be deleted physically. So here, we move
# to next(it is after all the deleted items), then close the cursor.
puts "$prefix.f: Moving the 3rd cursor."
set ret3 [$cursor3 get -next]
error_check_bad cursor3_get [llength $ret3] 0
error_check_good cursor3_close [$cursor3 close] 0
if { $txnenv == 1 } {
error_check_good txn_commit [$t commit] 0
}
error_check_good secdb_close [$sec_db close] 0
error_check_good db_close [$db close] 0
}