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 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
|
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
#
# $Id$
#
# TEST test142
# TEST Tests exclusive database handles.
# TEST 1. Test that exclusive database handles return an error in incompatible
# TEST environments.
# TEST 2. Test that an exclusive subdatabase handle does not block opening a
# TEST handle on another database in the same file.
# TEST 3. Run script tests on a subdatabase with both wait and no wait
# TEST configuration.
# TEST 4. Run script tests on a database with both wait and no wait
# TEST configuration.
proc test142 {method {tnum "142"} args } {
source ./include.tcl
source $tcl_utils/multi_proc_utils.tcl
# Skip this test if threads are not enabled
if [catch {package require Thread}] {
puts "Skipping test$tnum: requires Tcl Thread package."
return 0
}
set script1 [test142_script1]
set script2 [test142_script2]
set nowaits {0 1}
set omethod [convert_method $method]
set args [convert_args $method $args]
set testfile test$tnum.db
set exclfile excl.db
set cryargs {}
set homedir $testdir
puts "Test$tnum: Exclusive database handles ($method $args)"
# Check if we are using a transactional environment.
set eindex [lsearch $args "-env"]
set txnenv 1
set threaded 0
set opened 0
set env 0
set args2 $args
set noerr_env 0
if { $eindex != -1 } {
set env [lindex $args $eindex+1]
set args2 [lreplace $args $eindex $eindex+1]
set txnenv [is_txnenv $env]
set sys [$env get_open_flags]
if { [lsearch $sys -thread] != -1 } {
set threaded 1
}
set homedir [$env get_home]
} else {
set eindex [lsearch $args "-encryptaes"]
if { $eindex != -1 } {
set cryargs [lrange $args $eindex $eindex+1]
set args [lreplace $args $eindex $eindex+1]
set eindex [lsearch $args2 "-encryptaes"]
set args2 [lreplace $args2 $eindex $eindex+1]
lappend args -encrypt
lappend args2 -encrypt
}
set opened 1
set env [eval {berkdb_env_noerr -create -txn \
-cachesize { 0 1048576 1 }} $cryargs -home $homedir]
error_check_good envopen [is_valid_env $env] TRUE
lappend args -env
lappend args $env
set noerr_env 1
}
cleanup $homedir $env
# Check that opening the database exclusively fails
# on threaded or non-transactional environments
if { $txnenv == 0 || $threaded == 1 } {
puts "\tTest$tnum.a: Exclusive open fails with threaded or non-txn env."
foreach nowait $nowaits {
set ret [catch {eval {berkdb_open_noerr -create \
-mode 0644 $omethod -lk_exclusive $nowait} $args \
{$testfile}} db]
error_check_bad dbopen $ret 0
}
return
}
if { $noerr_env } {
puts "\t Test$tnum.b: Exclusive databases can have only 1 active txn."
set db [eval {berkdb_open_noerr -create -mode 0644 \
-auto_commit $omethod -lk_exclusive 0} $args \
./multitxn.db ]
error_check_good dbopen [is_valid_db $db] TRUE
set txn1 [$env txn]
set txn2 [$env txn]
set did [open $dict]
set key ""
gets $did str
if { [is_record_based $omethod] == 1 } {
set key 1
} else {
set key $str
}
set ret [eval {$db put} -txn $txn1 \
{$key [chop_data $omethod $str]}]
error_check_good multi_txn $ret 0
catch { eval {$db put} -txn $txn2 \
{$key [chop_data $omethod $str]}} ret
error_check_bad multi_txn $ret 0
$txn2 abort
$txn1 commit
$db close
}
# Queue and heap databases do not support multiple databases
# in a single file.
if { ![is_queue $omethod] && ![is_heap $omethod] &&
![is_partitioned $args]} {
# Create a database with sub databases.
puts "\tTest$tnum.c: Open a database with subdbs."
set ret [catch {eval {berkdb_open} -create -auto_commit \
-mode 0644 $omethod $args $exclfile one} db1]
error_check_good db1open $ret 0
set ret [catch {eval {berkdb_open} -create -auto_commit \
-mode 0644 $omethod $args $exclfile two} db2]
error_check_good db2open $ret 0
$db1 close
$db2 close
# Check that and exclusive subdatabase handle does not
# interfere with opening another subdatabase in the same file
foreach nowait $nowaits {
puts "\tTest$tnum.d: Open one subdb exclusively, another not, for nowait value $nowait."
set ret [catch {eval {berkdb_open $omethod \
-lk_exclusive $nowait} \
$args -auto_commit $exclfile one} db1]
error_check_good db1exclopen$nowait $ret 0
set ret [catch {eval {berkdb_open $omethod} \
$args -auto_commit $exclfile two} db2]
error_check_good db2exclopen$nowait $ret 0
$db1 close
$db2 close
}
if { [is_repenv $env] } {
puts "\tTest$tnum.e Skipping scripts in replication environment."
return;
}
# Run the scripts with the sub databases
foreach nowait $nowaits {
puts "\tTest$tnum.f: Test scripts with subdatabases, for nowait value $nowait."
set myports [available_ports 2]
set myPort1 [lindex $myports 0]
set myPort2 [lindex $myports 1]
set arg_list1 [list $omethod $nowait $args2 \
$exclfile $cryargs $myPort1 $myPort2 \
$homedir one]
set arg_list2 [list $omethod $nowait $args2 \
$exclfile $cryargs $myPort2 $myPort1 \
$homedir one]
do_multi_proc_test test${tnum}excl1_$nowait \
[list $script1 $script2] \
[list $arg_list1 $arg_list2]
}
}
if { [is_repenv $env] } {
puts "\tTest$tnum.g Skipping scripts in replication environment."
return;
}
# Run the scripts with the passed in database files
foreach nowait $nowaits {
puts "\tTest$tnum.h: Test scripts with passed-in db files, for nowait value $nowait."
set myports [available_ports 2]
set myPort1 [lindex $myports 0]
set myPort2 [lindex $myports 1]
set arg_list1 [list $omethod $nowait $args2 $testfile \
$cryargs $myPort1 $myPort2 $homedir]
set arg_list2 [list $omethod $nowait $args2 $testfile \
$cryargs $myPort2 $myPort1 $homedir]
do_multi_proc_test test${tnum}excl2_$nowait \
[list $script1 $script2] [list $arg_list1 $arg_list2]
}
if { $opened } {
$env close
}
}
# Script 1
# 1. Opens an exclusive database handle
# 2. Populates the database.
# 3. Confirms that Script 2 is blocked trying to open a handle on
# the same database.
# 4. Close the exclusive handle.
# 5. Try reopening the exclusive handle, which will fail if nowait is
# true, and will succeed after blocking if it is false.
proc test142_script1 {} {
set script1 {
source ./include.tcl
source $test_path/test.tcl
source $test_path/testutils.tcl
source $tcl_utils/multi_proc_utils.tcl
set usage \
"script omethod nowait args testfile cyrargs myPort clientPort homedir databaseName"
# Verify usage
set cmd_args [lindex $argv 0]
if { [llength $cmd_args] < 8 } {
puts stderr "FAIL:[timestamp] Usage: $usage"
exit
}
set omethod [lindex $cmd_args 0]
set nowait [lindex $cmd_args 1]
set args [lindex $cmd_args 2]
set testfile [lindex $cmd_args 3]
set cryargs [lindex $cmd_args 4]
set myPort [lindex $cmd_args 5]
set clientPort [lindex $cmd_args 6]
set homedir [lindex $cmd_args 7]
set databasename ""
if { [llength $cmd_args] > 8 } {
set databasename [lindex $cmd_args 8]
}
set timeout 10
# Join the environment
puts "Joining the environment in $homedir."
set dbenv [eval {berkdb_env -txn} $cryargs -home $homedir]
error_check_good envopen [is_valid_env $dbenv] TRUE
# open the exclusive database handle.
puts "Opening the exclusive database handle."
set db [eval berkdb_open -create -mode 0644 -auto_commit \
$omethod -lk_exclusive $nowait -env $dbenv $args \
$testfile $databasename]
error_check_good dbopen [is_valid_db $db] TRUE
set ret [do_sync $myPort $clientPort $timeout]
if { $ret != 0 } {
puts stderr "FAIL: Synchronization failed."
$db close
$dbenv close
exit -1
}
# Check that inserting works.
puts "Populating the database."
set t [$dbenv txn]
populate $db $omethod $t 10 0 0
# close the database handle, this will not release
# the handle lock, because the transaction is holding it
puts "Closing the exclusive database handle."
$db close
# This sync will fail because script2 is blocked trying
# to open a handle on the exclusive database.
puts "Confirming script 2 is blocked."
set ret [do_sync $myPort $clientPort $timeout]
if { $ret == 0 } {
puts stderr \
"FAIL: Synchronization succeeded where it should have failed."
$db close
$dbenv close
exit -1
}
# Now commit the transaction, releaseing the handle lock and
# allowing the script 2 to proceed.
error_check_good commit [eval {$t commit}] 0
set ret [do_sync $myPort $clientPort $timeout]
if { $ret != 0 } {
puts stderr "FAIL: Synchronization failed."
$dbenv close
exit -1
}
puts "Opening another exclusive database handle."
set ret [catch {eval berkdb_open_noerr -auto_commit \
-lk_exclusive $nowait $omethod -env $dbenv $args \
$testfile $databasename} db]
if { $nowait == 1 } {
error_check_bad dbopenwait $ret 0
# wakeup script2
set ret [do_sync $myPort $clientPort $timeout]
if { $ret != 0 } {
puts stderr "FAIL: Synchronization failed."
$dbenv close
exit -1
}
} else {
error_check_good dbopennowait $ret 0
$db close
set ret [do_sync $myPort $clientPort $timeout]
if { $ret == 0 } {
puts stderr \
"FAIL: Synchronization succeeded where it should have failed."
$dbenv close
exit -1
}
}
$dbenv close
}
# Do not put anything here, this proc depends on the
# return of set script1
}
# Script 2
# 1. Lets Script 1 open an exclusive handle on the database.
# 2. Opens a handle on the database, this blocks until Script 1 closes
# its exclusive handle.
# 3. Populates the database.
# 4. Tries to synchronize with Script 1, which will fail if nowait is
# false because Script 1 is blocked trying to open an exclusive handle
# on the database, and will succeed if nowait is true the exclusive
# handle in Script 1 would have returned an error immediately.
proc test142_script2 {} {
set script2 {
source ./include.tcl
source $test_path/test.tcl
source $test_path/testutils.tcl
source $tcl_utils/multi_proc_utils.tcl
set usage \
"script omethod nowait args testfile myPort clientPort homedir databaseName"
# Verify usage
set cmd_args [lindex $argv 0]
if { [llength $cmd_args] < 8 } {
puts stderr "FAIL:[timestamp] Usage: $usage"
exit
}
set omethod [lindex $cmd_args 0]
set nowait [lindex $cmd_args 1]
set args [lindex $cmd_args 2]
set testfile [lindex $cmd_args 3]
set cryargs [lindex $cmd_args 4]
set myPort [lindex $cmd_args 5]
set clientPort [lindex $cmd_args 6]
set homedir [lindex $cmd_args 7]
set databasename ""
if { [llength $cmd_args] > 8 } {
set databasename [lindex $cmd_args 8]
}
set timeout 10
# Wait for script1 to open the exlusive database
puts "Waiting for script 1 to open the exclusive database."
set ret [do_sync $myPort $clientPort $timeout]
if { $ret != 0 } {
puts stderr "FAIL: Synchronization failed."
exit
}
# Join the environment
puts "Opening the environment in $homedir."
set dbenv [eval {berkdb_env -txn} $cryargs -home $homedir]
error_check_good envopen [is_valid_env $dbenv] TRUE
# This will block until script 1 closes the exclusive database
puts "Opening the database."
set db [eval berkdb_open -auto_commit $omethod -env $dbenv \
$args $testfile $databasename]
error_check_good dbopen [is_valid_db $db] TRUE
set db [eval berkdb_open -auto_commit \
$omethod -env $dbenv $args $testfile $databasename]
error_check_good dbopen [is_valid_db $db] TRUE
# Wakeup script1
set ret [do_sync $myPort $clientPort $timeout]
if { $ret != 0 } {
puts stderr "FAIL: Synchronization failed."
$db close
$dbenv close
exit -1
}
# Check that inserting works.
puts "Populating the database."
set t [$dbenv txn]
populate $db $omethod $t 10 0 0
error_check_good commit [eval {$t commit}] 0
# This will succeed if nowait == 1, and fail otherwise
set ret [do_sync $myPort $clientPort $timeout]
if { $nowait == 1 } {
if { $ret != 0 } {
puts stderr "FAIL: Synchronization failed."
$db close
$dbenv close
exit -1
}
} elseif { $ret == 0 } {
puts stderr \
"FAIL: Synchronization succeeded when it should have failed."
$db close
$dbenv close
exit -1
}
$db close
$dbenv close
}
# Do not put anything here, this proc depends on the
# return of set script2
}
|