Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / test / tcl / lock005.tcl
1 # See the file LICENSE for redistribution information.
2 #
3 # Copyright (c) 1996, 2012 Oracle and/or its affiliates.  All rights reserved.
4 #
5 # $Id$
6 #
7 # TEST lock005
8 # TEST Check that page locks are being released properly.
9
10 proc 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
67 proc 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
161 proc 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 }