001: /*
002:
003: Derby - Class org.apache.derby.impl.store.access.btree.BTreeLockingPolicy
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.store.access.btree;
023:
024: import org.apache.derby.iapi.error.StandardException;
025:
026: import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
027:
028: import org.apache.derby.iapi.store.access.ConglomerateController;
029:
030: import org.apache.derby.iapi.store.raw.FetchDescriptor;
031: import org.apache.derby.iapi.store.raw.Page;
032: import org.apache.derby.iapi.store.raw.RecordHandle;
033:
034: import org.apache.derby.iapi.types.DataValueDescriptor;
035:
036: import org.apache.derby.iapi.types.RowLocation;
037:
038: /**
039:
040: The generic.BTree directory wants to know as little about locking as possible,
041: in order to make the code usuable by multiple implementations. But the
042: generic code will make calls to abstract lock calls implemented by concrete
043: btree implementations. Concrete implementations like B2I understand locking,
044: and needs informatation specific to the implementation to make the lock calls.
045: <p>
046: This class is created and owned by the concrete application, but is passed
047: into and returned from the generic code when lock calls are made.
048: Concrete implementations which do not need lock calls can just pass a null
049: pointer where a BTreeLockingPolicy is requested.
050: <p>
051: There are 2 types of lock interfaces, lockScan*() and lockNonScan*().
052: <p>
053: The lockScan*() interfaces assume that the caller gets a "scan lock" on the
054: page before requesting any row locks on the page. This is either done by
055: makeing a lockScan() call followed by row lock requests, or it can be done
056: in one operation by calling lockScanRow() and requesting the scan lock be
057: obtained before getting the row lock. Upon return from these interfaces
058: the row lock requested is guaranteed to have been obtained on the correct
059: key for the row requested. These interfaces handle the special case of
060: unique indexes where the RowLocation can change while waiting on the lock
061: (see implementation for details), basically the lock is retryed after waiting
062: if the RowLocation has changed.
063: <p>
064: The lockNonScan*() interfaces assume that no "scan lock" exists. If these
065: routines return that the latch was released while waiting to obtain the
066: lock, then the caller must requeue the lock request after taking appropriate
067: action. This action usually involves researching the tree to make sure
068: that the correct key is locked with latches held. Because no scan lock is
069: held the original row could have disappeared from the table. These interfaces
070: do not handle the special case of unique indexes where the RowLocation can
071: change while waiting on the lock, as the row may disappear when the latch
072: is released to wait on the lock - thus it is necessary that the caller retry
073: the lock if the interface returns that the latch was released.
074:
075:
076: **/
077:
078: public interface BTreeLockingPolicy {
079: /**************************************************************************
080: * Abstract Protected lockScan*() locking methods of BTree:
081: * lockScan - lock the scan page
082: * lockScanForReclaimSpace - lock page for reclaiming deleted rows.
083: * lockScanRow - lock row and possibly the scan page
084: * unlockScan - unlock the scan page
085: * unlockScanRecordAfterRead- unlock the scan record
086: **************************************************************************
087: */
088:
089: /**
090: * Lock the current leaf page.
091: * <p>
092: * Logically lock the record id's on a leaf page. This protocol is used
093: * by splits/row purgers and scans to coordinate between themselves.
094: * <p>
095: * Anyone who wants to either move rows off of a btree page or, purge
096: * them from existence must first call this routine with "forUpdate"
097: * true. This will result in a lock request which will block on other
098: * processes which cannot work if rows move off the page or disappear.
099: * It is expected that the this routine will only be called for update
100: * by very short term internal transactions which will commit immediately
101: * after doing their work and give up the exclusive lock quickly.
102: * <p>
103: * Currently scans can position themselves in one of 2 ways, either by
104: * saving the record handle of a record when they give up the latch on
105: * the page, or by saving the entire row. If they save the record handle
106: * then they must call this routine with "forUpdate" false, to get a
107: * lock which will protect the record handle they are using from moving
108: * off the page or disapearing. This is also why aborts of inserts must
109: * be done by marking the rows deleted, rather than purging them.
110: * It is expected that scanner's will release this lock once they move
111: * off the page they are looking at. They do this by calling
112: * unlockScan().
113: * <p>
114: * This lock enforces the same lock/latch protocol as btree row locks.
115: * On return the lock has been obtained. Return status indicates if the
116: * lock was waited for, which will mean a latch(s) were dropped while
117: * waiting.
118: * In general a false status means that the caller will either have
119: * to research the tree unless some protocol has been implemented that
120: * insures that the row will not have moved while the latch was dropped.
121: * <p>
122: * This routine requests a special row on the RECORD_ID_PROTECTION_HANDLE
123: * row id. If the lock is granted the routine will return true.
124: * If the lock cannot be granted NOWAIT, then the routine will release
125: * the latch on "current_leaf" and "aux_control_row" (if
126: * aux_control_row is non-null), and then it will request a WAIT lock on
127: * the row.
128: *
129: * @param current_leaf The lock is associated with this page in the
130: * btree. This control row is unlatched if the
131: * routine has to wait on the lock.
132: * @param aux_control_row If non-null, this control row is unlatched
133: * if the routine has to wait on the lock.
134: * @param forUpdate Whether to wait for lock.
135: * @param lock_operation For what operation are we requesting the lock,
136: * this should be one of the following 4 options:
137: * LOCK_READ [read lock],
138: * (LOCK_INS | LOCK_UPD) [ lock for insert],
139: * (LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
140: * previous key to insert],
141: * (LOCK_UPD) [lock for delete or replace]
142: *
143: * @exception StandardException Standard exception policy.
144: **/
145: abstract public boolean lockScan(LeafControlRow current_leaf,
146: ControlRow aux_control_row, boolean forUpdate,
147: int lock_operation) throws StandardException;
148:
149: /**
150: * Lock a control row page for reclaiming deleted rows.
151: * <p>
152: * When reclaiming deleted rows during split need to get an exclusive
153: * scan lock on the page, which will mean there are no other scans
154: * positioned on the page. If there are other scans positioned, just
155: * give up on reclaiming space now.
156: *
157: * @return true if lock was granted nowait, else false and not lock was
158: * granted.
159: *
160: * @exception StandardException Standard exception policy.
161: **/
162: abstract public boolean lockScanForReclaimSpace(
163: LeafControlRow current_leaf) throws StandardException;
164:
165: /**
166: * Lock a btree row to determine if it is a committed deleted row.
167: * <p>
168: * Request an exclusive lock on the row located at the given slot, NOWAIT.
169: * Return true if the lock is granted, otherwise false.
170: * <p>
171: *
172: * @param open_btree The conglomerate we are locking.
173: * @param leaf The leaf page with the row to lock.
174: * @param template Empty full template row, to read row into.
175: * @param slot_no The slot of row on "current_leaf"
176: *
177: * @exception StandardException Standard exception policy.
178: **/
179: abstract public boolean lockScanCommittedDeletedRow(
180: OpenBTree open_btree, LeafControlRow leaf,
181: DataValueDescriptor[] template,
182: FetchDescriptor lock_fetch_desc, int slot_no)
183: throws StandardException;
184:
185: /**
186: * Lock a row as part of doing the scan.
187: * <p>
188: * Lock the row at the given slot (or the previous row if slot is 0).
189: * Get the scan lock on the page if "request_scan_lock" is true.
190: * <p>
191: * If this routine returns true all locks were acquired while maintaining
192: * the latch on leaf. If this routine returns false, locks may or may
193: * not have been acquired, and the routine should be called again after
194: * the client has researched the tree to reget the latch on the
195: * appropriate page.
196: * (p>
197: * As a side effect stores the value of the record handle of the current
198: * scan lock.
199: *
200: * @return Whether locks were acquired without releasing latch on leaf.
201: *
202: * @param open_btree The open_btree to associate latches with -
203: * used if routine has to scan backward.
204: * @param btree the conglomerate info.
205: * @param pos Description of position of row to lock.
206: * @param request_scan_lock Whether to request the page scan lock, should
207: * only be requested once per page in the scan.
208: * @param lock_template A scratch area to use to read in rows.
209: * @param previous_key_lock Is this a previous key lock call?
210: * @param forUpdate Is the scan for update or for read only.
211: * @param lock_operation For what operation are we requesting the lock,
212: * this should be one of the following 4 options:
213: * LOCK_READ [read lock],
214: * (LOCK_INS | LOCK_UPD) [ lock for insert],
215: * (LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
216: * previous key to insert],
217: * (LOCK_UPD) [lock for delete or replace]
218: *
219: * @exception StandardException Standard exception policy.
220: **/
221: abstract public boolean lockScanRow(OpenBTree open_btree,
222: BTree btree, BTreeRowPosition pos,
223: boolean request_scan_lock, FetchDescriptor lock_fetch_desc,
224: DataValueDescriptor[] lock_template,
225: RowLocation lock_row_loc, boolean previous_key_lock,
226: boolean forUpdate, int lock_operation)
227: throws StandardException;
228:
229: /**
230: * Release read lock on a row.
231: *
232: * @param pos Data structure that defines the current position
233: * in the scan to be unlocked.
234: *
235: * @param forUpdate Is the scan for update or for read only.
236: *
237: * @exception StandardException Standard exception policy.
238: **/
239: abstract public void unlockScanRecordAfterRead(
240: BTreeRowPosition pos, boolean forUpdate)
241: throws StandardException;
242:
243: /**
244: * Release the lock gotten by calling lockScan. This call can only be
245: * made to release read scan locks, write scan locks must be held until
246: * end of transaction.
247: * <p>
248: *
249: * @param page_number page number of page that lockScan was called on.
250: *
251: **/
252: abstract public void unlockScan(long page_number);
253:
254: /**************************************************************************
255: * Abstract Protected lockNonScan*() locking methods of BTree:
256: *
257: * lockNonScanPreviousRow - lock the row previous to the current
258: * lockNonScanRow - lock the input row
259: * lockNonScanRowOnPage - lock the given row on the page.
260: **************************************************************************
261: */
262:
263: /**
264: * Lock the previous key.
265: * <p>
266: * Given the current latched page and slot number, lock the logically
267: * previous key in the table. There are 3 cases:
268: * <p>
269: * slotnumber > 1 - just lock (slotnumber - 1)
270: * (slotnumber == 1) && (leftmost leaf) - this is the first key in the
271: * table, so lock a "magic" FIRSTKEY.
272: * (slotnumber == 1) && !(leftmost leaf)- traverse left in the tree looking
273: * for a previous key.
274: * <p>
275: * On successful return from this routine appropriate locking will have
276: * been done. All locks and latches are requested nowait, if any
277: * lock/latch cannot be granted this routine releases the current_leaf
278: * latch and any latches it may have acquired and returns "false."
279: * <p>
280: * All extra latches that may have been gotten will have been released.
281: * <p>
282: * This routine will find the "previous row" to the (current_leaf,
283: * current_slot), walking left in the tree as necessary, and first request
284: * the lock on that row NOWAIT. If that lock can not be granted,
285: * then it will release all latches that it has acquired up to that point
286: * including the latched current_leaf passed into the routine, and request
287: * the lock WAIT. Once the lock has been granted the routine will return
288: * and it is up to the caller to research the tree to find where the
289: * row may have ended up.
290: * <p>
291: * If routine returns true, lock was granted NOWAIT, current leaf
292: * remains latched, and was never unlatched. If routine returns false,
293: * lock was granted WAIT, current leaf is not latched, row may have
294: * moved in the btree so caller must research to find the row.
295: *
296: *
297: * @param btree The conglomerate we are locking.
298: * @param current_leaf Latched current leaf where "current" key is.
299: * @param current_slot The slot of row on "current_leaf"
300: * @param lock_template Empty full template row, to read row into.
301: * @param open_btree The open_btree to associate latches with -
302: * used if routine has to scan backward.
303: * @param lock_operation For what operation are we requesting the lock,
304: * this should be one of the following 4 options:
305: * LOCK_READ [read lock],
306: * (LOCK_INS | LOCK_UPD) [ lock for insert],
307: * (LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
308: * previous key to insert],
309: * (LOCK_UPD) [lock for delete or replace]
310: * @param lock_duration For what duration should the lock be held,
311: * if INSTANT_DURATION, then the routine will
312: * guarantee that lock was acquired while holding
313: * the latch, but then immediately release the
314: * lock. If COMMIT_DURATION or MANUAL_DURATION
315: * then the lock be held when routine returns
316: * successfully.
317: *
318: * @exception StandardException Standard exception policy.
319: **/
320: abstract public boolean lockNonScanPreviousRow(BTree btree,
321: LeafControlRow current_leaf, int current_slot,
322: FetchDescriptor lock_fetch_desc,
323: DataValueDescriptor[] lock_template,
324: RowLocation lock_row_loc, OpenBTree open_btree,
325: int lock_operation, int lock_duration)
326: throws StandardException;
327:
328: /**
329: * Lock a btree row (row in memory). Meant to be used if caller
330: * has the entire row objectified.
331: * <p>
332: * Lock a btree row, enforcing the standard lock/latch protocol.
333: * On return the row is locked. Return status indicates if the lock
334: * was waited for, which will mean a latch was dropped while waiting.
335: * In general a false status means that the caller will either have
336: * to research the tree unless some protocol has been implemented that
337: * insures that the row will not have moved while the latch was dropped.
338: * <p>
339: * This routine request a row lock NOWAIT on the in-memory row
340: * "current_row.". If the lock is granted the routine will return true.
341: * If the lock cannot be granted NOWAIT, then the routine will release
342: * the latch on "current_leaf" (if current_leaf is non-null) and
343: * "aux_leaf" (if aux_leaf is non-null), and then it will request a WAIT
344: * lock on the row.
345: *
346: *
347: * @param btree The conglomerate we are locking.
348: * @param current_leaf If non-null, this leaf is unlatched if the
349: * routine has to wait on the lock.
350: * @param aux_leaf If non-null, this leaf is unlatched if the
351: * routine has to wait on the lock.
352: * @param current_row In memory, objectified "current" row.
353: * @param lock_operation For what operation are we requesting the lock,
354: * this should be one of the following 4 options:
355: * LOCK_READ [read lock],
356: * (LOCK_INS | LOCK_UPD) [ lock for insert],
357: * (LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
358: * previous key to insert],
359: * (LOCK_UPD) [lock for delete or replace]
360: *
361: * @exception StandardException Standard exception policy.
362: **/
363: abstract public boolean lockNonScanRow(BTree btree,
364: LeafControlRow current_leaf, LeafControlRow aux_leaf,
365: DataValueDescriptor[] current_row, int lock_operation)
366: throws StandardException;
367:
368: /**
369: * Lock the row at the given slot.
370: * <p>
371: * If this routine returns true all locks were acquired while maintaining
372: * the latch on leaf. If this routine returns false, locks may or may
373: * not have been acquired, and the routine should be called again after
374: * the client has researched the tree to reget the latch on the
375: * appropriate page.
376: *
377: * @return Whether locks were acquired without releasing latch on leaf.
378: *
379: * @param btree the conglomerate info.
380: * @param leaf The control row of the current leaf to lock.
381: * @param slot The slot position of the row to lock.
382: * @param lock_template A scratch area to use to read in rows.
383: * @param lock_operation For what operation are we requesting the lock,
384: * this should be one of the following 4 options:
385: * LOCK_READ [read lock],
386: * (LOCK_INS | LOCK_UPD) [ lock for insert],
387: * (LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
388: * previous key to insert],
389: * (LOCK_UPD) [lock for delete or replace]
390: *
391: * @exception StandardException Standard exception policy.
392: **/
393: abstract public boolean lockNonScanRowOnPage(BTree btree,
394: LeafControlRow leaf, int slot,
395: FetchDescriptor lock_fetch_desc,
396: DataValueDescriptor[] lock_template,
397: RowLocation lock_row_loc, int lock_operation)
398: throws StandardException;
399: }
|