1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: lock005.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST lock005 8# TEST Check that page locks are being released properly. 9 10proc lock005 { } { 11 source ./include.tcl 12 13 puts "Lock005: Page lock release test" 14 15 # Clean up after previous runs 16 env_cleanup $testdir 17 18 # Open/create the lock region 19 set e [berkdb_env -create -lock -home $testdir -txn -log] 20 error_check_good env_open [is_valid_env $e] TRUE 21 22 # Open/create the database 23 set db [berkdb open -create -auto_commit -env $e -len 10 -queue q.db] 24 error_check_good dbopen [is_valid_db $db] TRUE 25 26 # Check that records are locking by trying to 27 # fetch a record on the wrong transaction. 28 puts "\tLock005.a: Verify that we are locking" 29 30 # Start the first transaction 31 set txn1 [$e txn -nowait] 32 error_check_good txn_begin [is_valid_txn $txn1 $e] TRUE 33 set ret [catch {$db put -txn $txn1 -append record1} recno1] 34 error_check_good dbput_txn1 $ret 0 35 36 # Start second txn while the first is still running ... 37 set txn2 [$e txn -nowait] 38 error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE 39 40 # ... and try to get a record from the first txn (should fail) 41 set ret [catch {$db get -txn $txn2 $recno1} res] 42 error_check_good dbget_wrong_record \ 43 [is_substr $res "deadlock"] 1 44 45 # End transactions 46 error_check_good txn1commit [$txn1 commit] 0 47 how_many_locks 1 $e 48 error_check_good txn2commit [$txn2 commit] 0 49 # The number of locks stays the same here because the first 50 # lock is released and the second lock was never granted. 51 how_many_locks 1 $e 52 53 # Test lock behavior for both abort and commit 54 puts "\tLock005.b: Verify locks after abort or commit" 55 foreach endorder {forward reverse} { 56 end_order_test $db $e commit abort $endorder 57 end_order_test $db $e abort commit $endorder 58 end_order_test $db $e commit commit $endorder 59 end_order_test $db $e abort abort $endorder 60 } 61 62 # Clean up 63 error_check_good db_close [$db close] 0 64 error_check_good env_close [$e close] 0 65} 66 67proc end_order_test { db e txn1end txn2end endorder } { 68 # Start one transaction 69 set txn1 [$e txn -nowait] 70 error_check_good txn_begin [is_valid_txn $txn1 $e] TRUE 71 set ret [catch {$db put -txn $txn1 -append record1} recno1] 72 error_check_good dbput_txn1 $ret 0 73 74 # Check number of locks 75 how_many_locks 2 $e 76 77 # Start a second transaction while first is still running 78 set txn2 [$e txn -nowait] 79 error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE 80 set ret [catch {$db put -txn $txn2 -append record2} recno2] 81 error_check_good dbput_txn2 $ret 0 82 how_many_locks 3 $e 83 84 # Now commit or abort one txn and make sure the other is okay 85 if {$endorder == "forward"} { 86 # End transaction 1 first 87 puts "\tLock005.b.1: $txn1end txn1 then $txn2end txn2" 88 error_check_good txn_$txn1end [$txn1 $txn1end] 0 89 how_many_locks 2 $e 90 91 # txn1 is now ended, but txn2 is still running 92 set ret1 [catch {$db get -txn $txn2 $recno1} res1] 93 set ret2 [catch {$db get -txn $txn2 $recno2} res2] 94 if { $txn1end == "commit" } { 95 error_check_good txn2_sees_txn1 $ret1 0 96 error_check_good txn2_sees_txn2 $ret2 0 97 } else { 98 # transaction 1 was aborted 99 error_check_good txn2_cantsee_txn1 [llength $res1] 0 100 } 101 102 # End transaction 2 second 103 error_check_good txn_$txn2end [$txn2 $txn2end] 0 104 how_many_locks 1 $e 105 106 # txn1 and txn2 should both now be invalid 107 # The get no longer needs to be transactional 108 set ret3 [catch {$db get $recno1} res3] 109 set ret4 [catch {$db get $recno2} res4] 110 111 if { $txn2end == "commit" } { 112 error_check_good txn2_sees_txn1 $ret3 0 113 error_check_good txn2_sees_txn2 $ret4 0 114 error_check_good txn2_has_record2 \ 115 [is_substr $res4 "record2"] 1 116 } else { 117 # transaction 2 was aborted 118 error_check_good txn2_cantsee_txn1 $ret3 0 119 error_check_good txn2_aborted [llength $res4] 0 120 } 121 122 } elseif { $endorder == "reverse" } { 123 # End transaction 2 first 124 puts "\tLock005.b.2: $txn2end txn2 then $txn1end txn1" 125 error_check_good txn_$txn2end [$txn2 $txn2end] 0 126 how_many_locks 2 $e 127 128 # txn2 is ended, but txn1 is still running 129 set ret1 [catch {$db get -txn $txn1 $recno1} res1] 130 set ret2 [catch {$db get -txn $txn1 $recno2} res2] 131 if { $txn2end == "commit" } { 132 error_check_good txn1_sees_txn1 $ret1 0 133 error_check_good txn1_sees_txn2 $ret2 0 134 } else { 135 # transaction 2 was aborted 136 error_check_good txn1_cantsee_txn2 [llength $res2] 0 137 } 138 139 # End transaction 1 second 140 error_check_good txn_$txn1end [$txn1 $txn1end] 0 141 how_many_locks 1 $e 142 143 # txn1 and txn2 should both now be invalid 144 # The get no longer needs to be transactional 145 set ret3 [catch {$db get $recno1} res3] 146 set ret4 [catch {$db get $recno2} res4] 147 148 if { $txn1end == "commit" } { 149 error_check_good txn1_sees_txn1 $ret3 0 150 error_check_good txn1_sees_txn2 $ret4 0 151 error_check_good txn1_has_record1 \ 152 [is_substr $res3 "record1"] 1 153 } else { 154 # transaction 1 was aborted 155 error_check_good txn1_cantsee_txn2 $ret4 0 156 error_check_good txn1_aborted [llength $res3] 0 157 } 158 } 159} 160 161proc how_many_locks { expected env } { 162 set stat [$env lock_stat] 163 set str "Current number of locks" 164 set checked 0 165 foreach statpair $stat { 166 if { $checked == 1 } { 167 break 168 } 169 if { [is_substr [lindex $statpair 0] $str] != 0} { 170 set checked 1 171 set nlocks [lindex $statpair 1] 172 error_check_good expected_nlocks $nlocks $expected 173 } 174 } 175 error_check_good checked $checked 1 176} 177