1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.store.raw.xact.RowLocking3 |
4 | |
5 | Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.impl.store.raw.xact; |
22 | |
23 | import org.apache.derby.iapi.services.locks.LockFactory; |
24 | import org.apache.derby.iapi.services.locks.C_LockFactory; |
25 | import org.apache.derby.iapi.services.locks.Latch; |
26 | |
27 | import org.apache.derby.iapi.services.sanity.SanityManager; |
28 | |
29 | import org.apache.derby.iapi.store.raw.ContainerHandle; |
30 | import org.apache.derby.iapi.store.raw.ContainerLock; |
31 | import org.apache.derby.iapi.store.raw.RecordHandle; |
32 | import org.apache.derby.iapi.store.raw.RowLock; |
33 | import org.apache.derby.iapi.store.raw.Transaction; |
34 | import org.apache.derby.iapi.store.raw.LockingPolicy; |
35 | |
36 | import org.apache.derby.iapi.error.StandardException; |
37 | |
38 | |
39 | /** |
40 | A locking policy that implements row level locking with isolation degree 3. |
41 | |
42 | @see org.apache.derby.iapi.store.raw.LockingPolicy |
43 | */ |
44 | public class RowLocking3 extends NoLocking |
45 | { |
46 | // no locking has no state, so it's safe to hold |
47 | // it as a static |
48 | private static final LockingPolicy NO_LOCK = new NoLocking(); |
49 | |
50 | protected final LockFactory lf; |
51 | |
52 | protected RowLocking3(LockFactory lf) |
53 | { |
54 | this.lf = lf; |
55 | } |
56 | |
57 | /** |
58 | * Get type of lock to get while reading data. |
59 | * <p> |
60 | * This routine is provided so that class's like RowLockingRR can |
61 | * override just this routine to get RS2 locks vs RS3 locks, and still |
62 | * reuse all the other code in this class. |
63 | * <p> |
64 | * |
65 | * @return The lock type of a shared lock for this locking policy. |
66 | **/ |
67 | protected RowLock getReadLockType() |
68 | { |
69 | return(RowLock.RS3); |
70 | } |
71 | |
72 | /** |
73 | * Get type of lock to get while requesting "update" lock. |
74 | * <p> |
75 | * This routine is provided so that class's like RowLockingRR can |
76 | * override just this routine to get RU2 locks vs RU3 locks, and still |
77 | * reuse all the other code in this class. |
78 | * <p> |
79 | * |
80 | * @return The lock type of a shared lock for this locking policy. |
81 | **/ |
82 | protected RowLock getUpdateLockType() |
83 | { |
84 | return(RowLock.RU3); |
85 | } |
86 | |
87 | /** |
88 | * Get type of lock to get while writing data. |
89 | * <p> |
90 | * This routine is provided so that class's like RowLockingRR can |
91 | * override just this routine to get RX2 locks vs RX3 locks, and still |
92 | * reuse all the other code in this class. |
93 | * <p> |
94 | * |
95 | * @return The lock type of a shared lock for this locking policy. |
96 | **/ |
97 | protected RowLock getWriteLockType() |
98 | { |
99 | return(RowLock.RX3); |
100 | } |
101 | |
102 | |
103 | /** |
104 | * Obtain container level intent lock. |
105 | * <p> |
106 | * This implementation of row locking is 2 level, ie. table and row locking. |
107 | * It will interact correctly with tables opened with ContainerLocking3 |
108 | * locking mode. |
109 | * <p> |
110 | * Updater's will get table level IX locks, and X row locks. |
111 | * <p> |
112 | * Reader's will get table level IS locks, and S row locks. |
113 | * |
114 | * @param t Transaction to associate lock with. |
115 | * @param container Container to lock. |
116 | * @param waitForLock Should lock request wait until granted? |
117 | * @param forUpdate Should container be locked for update, or read? |
118 | * |
119 | * @return true if the lock was obtained, false if it wasn't. |
120 | * False should only be returned if the waitForLock policy was set to |
121 | * "false," and the lock was unavailable. |
122 | * |
123 | * @exception StandardException Standard exception policy. |
124 | **/ |
125 | public boolean lockContainer( |
126 | Transaction t, |
127 | ContainerHandle container, |
128 | boolean waitForLock, |
129 | boolean forUpdate) |
130 | throws StandardException |
131 | { |
132 | Object qualifier = forUpdate ? ContainerLock.CIX : ContainerLock.CIS; |
133 | |
134 | boolean gotLock = |
135 | lf.lockObject( |
136 | t.getCompatibilitySpace(), t, container.getId(), qualifier, |
137 | waitForLock ? C_LockFactory.TIMED_WAIT : C_LockFactory.NO_WAIT); |
138 | |
139 | if (gotLock) { |
140 | // look for covering table locks |
141 | // CIS is covered by CX or CS |
142 | // CIX is covered by CX |
143 | |
144 | if (lf.isLockHeld(t.getCompatibilitySpace(), t, container.getId(), ContainerLock.CX) || |
145 | ((!forUpdate) && lf.isLockHeld(t.getCompatibilitySpace(), t, container.getId(), ContainerLock.CS))) { |
146 | |
147 | |
148 | container.setLockingPolicy(NO_LOCK); |
149 | } |
150 | } |
151 | |
152 | return gotLock; |
153 | |
154 | } |
155 | |
156 | |
157 | /** |
158 | * Obtain lock on record being read. |
159 | * <p> |
160 | * Assumes that a table level IS has been acquired. Will acquire a Shared |
161 | * or Update lock on the row, depending on the "forUpdate" parameter. |
162 | * <p> |
163 | * |
164 | * @param t The transaction to associate the lock with. |
165 | * @param record The record to be locked. |
166 | * @param waitForLock Should lock request wait until granted? |
167 | * @param forUpdate Whether to open for read or write access. |
168 | * |
169 | * @return true if the lock was granted, false if waitForLock was false |
170 | * and the lock could not be granted. |
171 | * |
172 | * @exception StandardException Standard exception policy. |
173 | **/ |
174 | public boolean lockRecordForRead( |
175 | Transaction t, |
176 | ContainerHandle container_handle, |
177 | RecordHandle record, |
178 | boolean waitForLock, |
179 | boolean forUpdate) |
180 | throws StandardException |
181 | { |
182 | // RESOLVE - Did I do the right thing with the "forUpdate" variable. |
183 | |
184 | // For now just lock the row in Shared mode. |
185 | Object qualifier = forUpdate ? getUpdateLockType() : getReadLockType(); |
186 | |
187 | return( |
188 | lf.lockObject( |
189 | t.getCompatibilitySpace(), t, record, qualifier, |
190 | waitForLock ? |
191 | C_LockFactory.TIMED_WAIT : C_LockFactory.NO_WAIT)); |
192 | } |
193 | |
194 | /** |
195 | * Obtain lock on record being read while holding a latch. |
196 | * <p> |
197 | * Assumes that a table level IS has been acquired. Will acquire a Shared |
198 | * or Update lock on the row, depending on the "forUpdate" parameter. |
199 | * <p> |
200 | * |
201 | * @param latch The latch being held. |
202 | * @param record The record to be locked. |
203 | * @param forUpdate Whether to open for read or write access. |
204 | * |
205 | * @exception StandardException Standard exception policy. |
206 | **/ |
207 | public void lockRecordForRead( |
208 | Latch latch, |
209 | RecordHandle record, |
210 | boolean forUpdate) |
211 | throws StandardException |
212 | { |
213 | // RESOLVE - Did I do the right thing with the "forUpdate" variable. |
214 | |
215 | // For now just lock the row in Shared mode. |
216 | Object qualifier = forUpdate ? getUpdateLockType() : getReadLockType(); |
217 | |
218 | lf.lockObject( |
219 | latch.getCompatabilitySpace(), record, qualifier, |
220 | C_LockFactory.TIMED_WAIT, latch); |
221 | } |
222 | |
223 | /** |
224 | * Obtain lock on record being written. |
225 | * <p> |
226 | * Assumes that a table level IX has been acquired. Will acquire an |
227 | * Exclusive (X) lock on the row. |
228 | * <p> |
229 | * |
230 | * @param t transaction to associate the lock with. |
231 | * @param record The record to be locked. |
232 | * @param lockForInsertPreviousKey Lock is for a previous key of a insert. |
233 | * @param waitForLock Should lock request wait until granted? |
234 | * |
235 | * @return true if the lock was granted, false if waitForLock was false |
236 | * and the lock could not be granted. |
237 | * |
238 | * @exception StandardException Standard exception policy. |
239 | **/ |
240 | public boolean zeroDurationLockRecordForWrite( |
241 | Transaction t, |
242 | RecordHandle record, |
243 | boolean lockForInsertPreviousKey, |
244 | boolean waitForLock) |
245 | throws StandardException |
246 | { |
247 | return(lf.zeroDurationlockObject( |
248 | t.getCompatibilitySpace(), record, |
249 | (lockForInsertPreviousKey ? RowLock.RIP : getWriteLockType()), |
250 | waitForLock ? C_LockFactory.TIMED_WAIT : C_LockFactory.NO_WAIT)); |
251 | } |
252 | |
253 | /** |
254 | * Obtain lock on record being written. |
255 | * <p> |
256 | * Assumes that a table level IX has been acquired. Will acquire an |
257 | * Exclusive (X) lock on the row. |
258 | * <p> |
259 | * |
260 | * @param t The transaction to associate the lock with. |
261 | * @param record The record to be locked. |
262 | * @param lockForInsert Lock is for an insert. |
263 | * @param waitForLock Should lock request wait until granted? |
264 | * |
265 | * @return true if the lock was granted, false if waitForLock was false |
266 | * and the lock could not be granted. |
267 | * |
268 | * @exception StandardException Standard exception policy. |
269 | **/ |
270 | public boolean lockRecordForWrite( |
271 | Transaction t, |
272 | RecordHandle record, |
273 | boolean lockForInsert, |
274 | boolean waitForLock) |
275 | throws StandardException |
276 | { |
277 | return(lf.lockObject( |
278 | t.getCompatibilitySpace(), t, record, |
279 | lockForInsert ? RowLock.RI : getWriteLockType(), |
280 | waitForLock ? C_LockFactory.TIMED_WAIT : C_LockFactory.NO_WAIT)); |
281 | } |
282 | |
283 | /** |
284 | * Obtain lock on record being written while holding a latch. |
285 | * <p> |
286 | * Assumes that a table level IX has been acquired. Will acquire an |
287 | * Exclusive (X) lock on the row. |
288 | * <p> |
289 | * |
290 | * @param latch The latch being held |
291 | * @param record The record to be locked. |
292 | * |
293 | * @exception StandardException Standard exception policy. |
294 | **/ |
295 | public void lockRecordForWrite( |
296 | Latch latch, |
297 | RecordHandle record) |
298 | throws StandardException |
299 | { |
300 | lf.lockObject( |
301 | latch.getCompatabilitySpace(), |
302 | record, |
303 | getWriteLockType(), |
304 | C_LockFactory.TIMED_WAIT, |
305 | latch); |
306 | } |
307 | |
308 | public int getMode() { |
309 | return MODE_RECORD; |
310 | } |
311 | |
312 | |
313 | /* |
314 | ** We can inherit all the others methods of NoLocking since we hold the |
315 | ** container lock and row locks until the end of transaction. |
316 | */ |
317 | } |