Source Code Cross Referenced for B2IRowLocking3.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » store » access » btree » index » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.store.access.btree.index 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.store.access.btree.index.B2IRowLocking3
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.index;
023:
024:        import org.apache.derby.iapi.services.sanity.SanityManager;
025:
026:        import org.apache.derby.iapi.error.StandardException;
027:
028:        import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
029:
030:        import org.apache.derby.iapi.store.access.ConglomerateController;
031:
032:        import org.apache.derby.iapi.store.access.RowUtil;
033:        import org.apache.derby.iapi.store.access.TransactionController;
034:
035:        import org.apache.derby.iapi.store.raw.FetchDescriptor;
036:        import org.apache.derby.iapi.store.raw.LockingPolicy;
037:        import org.apache.derby.iapi.store.raw.Page;
038:        import org.apache.derby.iapi.store.raw.RecordHandle;
039:        import org.apache.derby.iapi.store.raw.Transaction;
040:
041:        import org.apache.derby.iapi.types.DataValueDescriptor;
042:
043:        import org.apache.derby.iapi.types.RowLocation;
044:
045:        import org.apache.derby.impl.store.access.btree.BTree;
046:        import org.apache.derby.impl.store.access.btree.BTreeLockingPolicy;
047:        import org.apache.derby.impl.store.access.btree.ControlRow;
048:        import org.apache.derby.impl.store.access.btree.LeafControlRow;
049:        import org.apache.derby.impl.store.access.btree.OpenBTree;
050:        import org.apache.derby.impl.store.access.btree.BTreeRowPosition;
051:        import org.apache.derby.impl.store.access.btree.WaitError;
052:
053:        /**
054:
055:         Implements the jdbc serializable isolation level using row locks.
056:         <p>
057:         Holds read and write locks until end of transaction.
058:         Obtains previous key locks to protect from phantom reads.
059:
060:         **/
061:        class B2IRowLocking3 implements  BTreeLockingPolicy {
062:
063:            /**************************************************************************
064:             * Private/Protected fields of This class:
065:             **************************************************************************
066:             */
067:
068:            /**
069:             * The container id of the base container for this index.  Used to build
070:             * record handles to make lock calls on.
071:             **/
072:            protected ConglomerateController base_cc;
073:
074:            /**
075:             * The OpenBtree to use if we have to lock anything in the btree vs.
076:             * base row locking.
077:             **/
078:            protected OpenBTree open_btree;
079:
080:            /**
081:             * The locking policy to use to get and release the scan locks.  We could
082:             * cache this somewhere better.
083:             **/
084:            private LockingPolicy scan_locking_policy;
085:
086:            /**
087:             * The transaction to associate lock requests with.
088:             **/
089:            private Transaction rawtran;
090:
091:            /**************************************************************************
092:             * Constructors for This class:
093:             **************************************************************************
094:             */
095:            B2IRowLocking3(Transaction rawtran, int lock_level,
096:                    LockingPolicy locking_policy,
097:                    ConglomerateController base_cc, OpenBTree open_btree) {
098:                this .rawtran = rawtran;
099:                this .base_cc = base_cc;
100:                this .open_btree = open_btree;
101:                this .scan_locking_policy = rawtran.newLockingPolicy(
102:                        LockingPolicy.MODE_RECORD,
103:                        TransactionController.ISOLATION_READ_COMMITTED, true);
104:            }
105:
106:            /**************************************************************************
107:             * Private methods of This class:
108:             **************************************************************************
109:             */
110:
111:            private boolean _lockScan(RecordHandle rh, boolean forUpdate,
112:                    boolean wait) throws StandardException {
113:                boolean ret_val = true;
114:
115:                // only get the scan lock if we are record locking.
116:
117:                if (!forUpdate) {
118:                    ret_val = scan_locking_policy.lockRecordForRead(rawtran,
119:                            open_btree.getContainerHandle(), rh, wait, false);
120:                } else {
121:                    ret_val = scan_locking_policy.lockRecordForWrite(rawtran,
122:                            rh, false, wait);
123:                }
124:
125:                return (ret_val);
126:            }
127:
128:            /**
129:             * Lock key previous to first key in btree.
130:             * <p>
131:             * In the previous key locking protocol repeatable read and phantom 
132:             * protection is guaranteed by locking a range of keys in the btree.
133:             * The range is defined by the key previous to the first key you look
134:             * at and all subsequent keys you look at.  The first key in the index
135:             * is a special case, as there are no keys previous to it.  In that
136:             * case a special key is declared the "previous key" to the first key
137:             * in the btree and is locked instead.
138:             * <p>
139:             * In this implementation that first key is defined to be in the base
140:             * container, page ContainerHandle.FIRST_PAGE_NUMBER, record id 
141:             * PREVIOUS_KEY_HANDLE.
142:             * <p>
143:             * Note that the previous key is the same for all indexes on a given
144:             * conglomerate.  It seemed better for all locks on a base table to have
145:             * the same containerid, rather than having some locks generated from 
146:             * a btree have a containerid from base table and some having a containerid
147:             * from the btree.  If this turns out to be a problem we could either
148:             * have 2 different containerid's, be more creative with the record id, or
149:             * even add more to the lock key.
150:             *
151:             * @param aux_leaf          If non-null, this leaf is unlatched if the 
152:             *                          routine has to wait on the lock.
153:             * @param lock_operation    Whether to lock exclusive or share.
154:             * @param lock_duration     For what duration should the lock be held,
155:             *                          if INSTANT_DURATION, then the routine will
156:             *                          guarantee that lock was acquired while holding
157:             *                          the latch, but then immediately release the
158:             *                          lock.  If COMMIT_DURATION or MANUAL_DURATION
159:             *                          then the lock be held when routine returns
160:             *                          successfully.
161:             *
162:             * @exception  StandardException  Standard exception policy.
163:             **/
164:            private boolean lockPreviousToFirstKey(LeafControlRow current_leaf,
165:                    LeafControlRow aux_leaf, int lock_operation,
166:                    int lock_duration) throws StandardException {
167:                // This is first row in table, lock the special key that 
168:                // represents the key previous to the first key of the table.
169:
170:                // First try to get the lock NOWAIT, while latch is held.
171:                boolean ret_status = base_cc.lockRow(BTree.ROOTPAGEID,
172:                        RecordHandle.PREVIOUS_KEY_HANDLE, lock_operation,
173:                        false /* NOWAIT */, lock_duration);
174:
175:                if (!ret_status) {
176:                    current_leaf.release();
177:                    current_leaf = null;
178:
179:                    if (aux_leaf != null) {
180:                        aux_leaf.release();
181:                        aux_leaf = null;
182:                    }
183:
184:                    // Couldn't get the lock NOWAIT, release latch and wait for lock.
185:                    base_cc.lockRow(BTree.ROOTPAGEID,
186:                            RecordHandle.PREVIOUS_KEY_HANDLE, lock_operation,
187:                            true /* WAIT */, lock_duration);
188:                }
189:
190:                return (ret_status);
191:            }
192:
193:            /**
194:             * Lock a btree row (row is at given slot in page).
195:             * <p>
196:             * Lock the row at the given slot in the page.  Meant to be used if caller 
197:             * only has the slot on the page to be locked, and has not read the row
198:             * yet.  This routine fetches the row location field from the page, and then
199:             * locks that rowlocation in the base container.
200:             * <p>
201:             * Lock a btree row, enforcing the standard lock/latch protocol.  
202:             * On return the row is locked.  Return status indicates if the lock
203:             * was waited for, which will mean a latch was dropped while waiting.
204:             * In general a false status means that the caller will either have 
205:             * to research the tree unless some protocol has been implemented that
206:             * insures that the row will not have moved while the latch was dropped.
207:             * <p>
208:             * This routine request a row lock NOWAIT on the in-memory row 
209:             * "current_row.".  If the lock is granted the routine will return true.
210:             * If the lock cannot be granted NOWAIT, then the routine will release
211:             * the latch on "current_leaf" and "aux_leaf" (if aux_leaf is non-null),
212:             * and then it will request a WAIT lock on the row.  
213:             * <p>
214:             *
215:             * @param btree             The conglomerate we are locking.
216:             * @param current_leaf      Latched current leaf where "current" key is.
217:             * @param aux_leaf          If non-null, this leaf is unlatched if the 
218:             *                          routine has to wait on the lock.
219:             * @param current_slot      Slot of row to lock.
220:             * @param lock_fetch_desc   Descriptor for fetching just the RowLocation,
221:             *                          used for locking.
222:             * @param check_changed_rowloc
223:             *                          whether to check for the changed rowloc or not.
224:             * @param lock_operation    Whether lock is for key prev to insert or not.
225:             * @param lock_duration     For what duration should the lock be held,
226:             *                          if INSTANT_DURATION, then the routine will
227:             *                          guarantee that lock was acquired while holding
228:             *                          the latch, but then immediately release the
229:             *                          lock.  If COMMIT_DURATION or MANUAL_DURATION
230:             *                          then the lock be held when routine returns
231:             *                          successfully.
232:             *
233:             * @exception  StandardException  Standard exception policy.
234:             **/
235:            private boolean lockRowOnPage(BTree btree,
236:                    LeafControlRow current_leaf, LeafControlRow aux_leaf,
237:                    int current_slot, boolean check_changed_rowloc,
238:                    FetchDescriptor lock_fetch_desc,
239:                    DataValueDescriptor[] lock_template,
240:                    RowLocation lock_row_loc, int lock_operation,
241:                    int lock_duration) throws StandardException {
242:                if (SanityManager.DEBUG) {
243:                    SanityManager.ASSERT(current_leaf != null);
244:
245:                    if (current_slot <= 0
246:                            || current_slot >= current_leaf.getPage()
247:                                    .recordCount()) {
248:                        SanityManager.THROWASSERT("current_slot = "
249:                                + current_slot
250:                                + "; current_leaf.getPage().recordCount() = "
251:                                + current_leaf.getPage().recordCount());
252:                    }
253:
254:                    if (!(btree instanceof  B2I)) {
255:                        SanityManager
256:                                .THROWASSERT("btree not instance of B2I, it is "
257:                                        + btree.getClass().getName());
258:                    }
259:
260:                    SanityManager.ASSERT(lock_template != null,
261:                            "template is null");
262:
263:                    // For now the RowLocation is expected to be the object located in
264:                    // the last column of the lock_template, this may change if we
265:                    // ever support rows with RowLocations somewhere else.
266:                    SanityManager
267:                            .ASSERT(
268:                                    lock_row_loc == lock_template[lock_template.length - 1],
269:                                    "row_loc is not the object in last column of lock_template.");
270:                }
271:
272:                // Fetch the row location to lock.
273:                RecordHandle rec_handle = current_leaf.getPage().fetchFromSlot(
274:                        (RecordHandle) null, current_slot, lock_template,
275:                        lock_fetch_desc, true);
276:
277:                // First try to get the lock NOWAIT, while latch is held.
278:                boolean ret_status = base_cc.lockRow(lock_row_loc,
279:                        lock_operation, false /* NOWAIT */, lock_duration);
280:
281:                if (!ret_status) {
282:                    // Could not get the lock NOWAIT, release latch and wait for lock.
283:
284:                    if (current_leaf != null) {
285:                        current_leaf.release();
286:                        current_leaf = null;
287:                    }
288:                    if (aux_leaf != null) {
289:                        aux_leaf.release();
290:                        aux_leaf = null;
291:                    }
292:
293:                    base_cc.lockRow(lock_row_loc, lock_operation,
294:                            true /* WAIT */, lock_duration);
295:                }
296:
297:                return (ret_status);
298:            }
299:
300:            private boolean searchLeftAndLockPreviousKey(B2I b2i,
301:                    LeafControlRow current_leaf, int current_slot,
302:                    FetchDescriptor lock_fetch_desc,
303:                    DataValueDescriptor[] lock_template,
304:                    RowLocation lock_row_loc, OpenBTree open_btree,
305:                    int lock_operation, int lock_duration)
306:                    throws StandardException {
307:                boolean latches_released = false;
308:                LeafControlRow prev_leaf;
309:                LeafControlRow prev_prev_leaf;
310:
311:                try {
312:                    // Move left in tree, page latch will be requested nowait, 
313:                    // and WaitError will be thrown if latch not granted.
314:
315:                    prev_leaf = (LeafControlRow) current_leaf
316:                            .getLeftSibling(open_btree);
317:
318:                } catch (WaitError e) {
319:                    long previous_pageno = current_leaf
320:                            .getleftSiblingPageNumber();
321:
322:                    // error going from mainpage to first left page.  Release 
323:                    // current page latch and continue the search.
324:                    current_leaf.release();
325:                    current_leaf = null;
326:
327:                    // wait on the left page, which we could not get before. 
328:                    prev_leaf = (LeafControlRow) ControlRow.Get(open_btree,
329:                            previous_pageno);
330:
331:                    latches_released = true;
332:                }
333:
334:                while (true) {
335:                    try {
336:                        // loop searching left in the btree until you either find 
337:                        // a record to lock, or you reach the leftmost empty leaf.
338:
339:                        if (prev_leaf.getPage().recordCount() > 1) {
340:                            // lock the last row on the page, which is the previous 
341:                            // record to the first row on the next page.
342:
343:                            boolean ret_status = lockRowOnPage(b2i, prev_leaf,
344:                                    current_leaf, prev_leaf.getPage()
345:                                            .recordCount() - 1, false,
346:                                    lock_fetch_desc, lock_template,
347:                                    lock_row_loc, lock_operation, lock_duration);
348:
349:                            if (!ret_status) {
350:                                prev_leaf = null;
351:                                current_leaf = null;
352:                                latches_released = true;
353:                            }
354:
355:                            break;
356:                        } else if (prev_leaf.isLeftmostLeaf()) {
357:                            // Table's first row, lock the key that represents the 
358:                            // key previous to first key of the table.
359:                            boolean ret_status = lockPreviousToFirstKey(
360:                                    prev_leaf, current_leaf, lock_operation,
361:                                    lock_duration);
362:
363:                            if (!ret_status) {
364:                                prev_leaf = null;
365:                                current_leaf = null;
366:                                latches_released = true;
367:                            }
368:
369:                            break;
370:                        }
371:
372:                        // Move left in tree, page latch will be requested nowait, 
373:                        // and WaitError will be thrown if latch not granted.
374:                        // Release latches on pages between "current_leaf" and 
375:                        // where the search leads, so that at most 3 latched pages
376:                        // (current_leaf, prev_leaf, prev_prev_leaf) are held during 
377:                        // the search.  Do left ladder locking as you walk left, 
378:                        // but be ready to release l
379:
380:                        prev_prev_leaf = (LeafControlRow) prev_leaf
381:                                .getLeftSibling(open_btree);
382:                        prev_leaf.release();
383:                        prev_leaf = prev_prev_leaf;
384:                        prev_prev_leaf = null;
385:                    } catch (WaitError e) {
386:                        long previous_pageno = prev_leaf
387:                                .getleftSiblingPageNumber();
388:
389:                        // error going left.  Release current page latch and 
390:                        // original page latch continue the search.
391:                        current_leaf.release();
392:                        current_leaf = null;
393:                        prev_leaf.release();
394:                        prev_leaf = null;
395:
396:                        // wait on the left page, which we could not get before. 
397:                        prev_leaf = (LeafControlRow) ControlRow.Get(open_btree,
398:                                previous_pageno);
399:
400:                        latches_released = true;
401:                    }
402:                }
403:                if (prev_leaf != null)
404:                    prev_leaf.release();
405:
406:                return (!latches_released);
407:
408:            }
409:
410:            /**************************************************************************
411:             * Protected methods of This class:
412:             **************************************************************************
413:             */
414:
415:            /**
416:             * Lock a row as part of doing the scan.
417:             * <p>
418:             * Lock the row at the given slot (or the previous row if slot is 0).
419:             * Get the scan lock on the page if "request_scan_lock" is true.
420:             * <p>
421:             * If this routine returns true all locks were acquired while maintaining
422:             * the latch on leaf.  If this routine returns false, locks may or may
423:             * not have been acquired, and the routine should be called again after
424:             * the client has researched the tree to reget the latch on the 
425:             * appropriate page.
426:             * (p>
427:             * As a sided effect stores the value of the record handle of the current
428:             * scan lock.
429:             *
430:             * @return Whether locks were acquired without releasing latch on leaf.
431:             *
432:             * @param open_btree        The open_btree to associate latches with - 
433:             *                          used if routine has to scan backward.
434:             * @param btree             the conglomerate info.
435:             * @param pos               The position of the row to lock.
436:             * @param request_row_lock  Whether to request the row lock, should
437:             *                          only be requested once per page in the scan.
438:             * @param request_scan_lock Whether to request the page scan lock, should
439:             *                          only be requested once per page in the scan.
440:             * @param lock_fetch_desc   The fetch descriptor to use to fetch the
441:             *                          row location for the lock request.
442:             * @param lock_template     A scratch area to use to read in rows.
443:             * @param previous_key_lock Is this a previous key lock call?
444:             * @param forUpdate         Is the scan for update or for read only.
445:             *
446:             * @exception  StandardException  Standard exception policy.
447:             **/
448:            protected boolean _lockScanRow(OpenBTree open_btree, BTree btree,
449:                    BTreeRowPosition pos, boolean request_row_lock,
450:                    boolean request_scan_lock, FetchDescriptor lock_fetch_desc,
451:                    DataValueDescriptor[] lock_template,
452:                    RowLocation lock_row_loc, boolean previous_key_lock,
453:                    boolean forUpdate, int lock_operation)
454:                    throws StandardException {
455:                boolean latch_released = false;
456:                B2I b2i = (B2I) btree;
457:
458:                if (request_row_lock) {
459:                    // In order to implement a serialized scan based on previous
460:                    // key locking, this method acquires a row lock on
461:                    // the base table's row from the index row at [startpage/startslot].
462:                    // This will be the 'previous key'.
463:
464:                    if (pos.current_slot == 0) {
465:                        // this call will take care of searching left in the btree
466:                        // to find the previous row to lock, 0 is the control row and
467:                        // not a valid thing to lock as a previous key.
468:
469:                        // it is ok to call the non-scan as this is just a special
470:                        // case of a previous key lock call.  The only scan code that
471:                        // will call this routine with slot == 0 will retry if this
472:                        // routine returns that a latch was released.
473:
474:                        latch_released = !lockNonScanPreviousRow(btree,
475:                                pos.current_leaf,
476:                                1 /* lock row previous to row at slot 1 */,
477:                                lock_fetch_desc, lock_template, lock_row_loc,
478:                                open_btree, lock_operation,
479:                                TransactionManager.LOCK_COMMIT_DURATION);
480:
481:                        // special test to see if latch release code works
482:                        if (SanityManager.DEBUG) {
483:                            latch_released = OpenBTree.test_errors(open_btree,
484:                                    "B2iRowLocking3_1_lockScanRow", false,
485:                                    this , pos.current_leaf, latch_released);
486:                        }
487:                    } else {
488:                        // Just lock the row at "slot"
489:
490:                        latch_released = !lockRowOnPage(
491:                                btree,
492:                                pos.current_leaf,
493:                                (LeafControlRow) null /* no other latch currently */,
494:                                pos.current_slot, true, lock_fetch_desc,
495:                                lock_template, lock_row_loc, lock_operation,
496:                                TransactionManager.LOCK_COMMIT_DURATION);
497:
498:                        // special test to see if latch release code works
499:                        if (SanityManager.DEBUG) {
500:                            latch_released = OpenBTree.test_errors(open_btree,
501:                                    "B2iRowLocking3_2_lockScanRow", false,
502:                                    this , pos.current_leaf, latch_released);
503:                        }
504:                    }
505:                }
506:
507:                if (request_scan_lock && !latch_released) {
508:                    // Get the scan lock on the start page.
509:
510:                    // Get shared RECORD_ID_PROTECTION_HANDLE lock to make sure that
511:                    // we wait for scans in other transactions to move off of this page
512:                    // before we split.
513:
514:                    latch_released = !lockScan(pos.current_leaf,
515:                            (LeafControlRow) null, // no other latch currently
516:                            false, ConglomerateController.LOCK_READ);// read scan lock position
517:
518:                    // special test to see if latch release code works
519:                    if (SanityManager.DEBUG) {
520:                        /* RESOLVE - need to get a container here */
521:                        latch_released = OpenBTree.test_errors(open_btree,
522:                                "B2iRowLocking3_3_lockScanRow", true, this ,
523:                                pos.current_leaf, latch_released);
524:                    }
525:                }
526:
527:                return (!latch_released);
528:            }
529:
530:            /**************************************************************************
531:             * Public Methods of This class:
532:             **************************************************************************
533:             */
534:
535:            /**************************************************************************
536:             * Abstract Protected lockScan*() locking methods of BTree:
537:             *     lockScan                 - lock the scan page
538:             *     lockScanForReclaimSpace  - lock page for reclaiming deleted rows.
539:             *     lockScanRow              - lock row and possibly the scan page
540:             *     unlockScan               - unlock the scan page
541:             *     unlockScanRecordAfterRead- unlock the scan record
542:             **************************************************************************
543:             */
544:
545:            /**
546:             * Lock a control row page for scan.
547:             * <p>
548:             * Scanners get shared lock on the page while positioned on a row within
549:             * the page, splitter/purgers/mergers get exclusive lock on the page.
550:             *
551:             * See BTree.lockScan() for more info.
552:             *
553:             * @exception  StandardException  Standard exception policy.
554:             **/
555:            public boolean lockScan(LeafControlRow current_leaf,
556:                    ControlRow aux_control_row, boolean forUpdate,
557:                    int lock_operation) throws StandardException {
558:                // The scan page lock is implemented as a row lock on the reserved
559:                // row id on the page (RecordHandle.RECORD_ID_PROTECTION_HANDLE).
560:                RecordHandle scan_lock_rh = current_leaf.getPage()
561:                        .makeRecordHandle(
562:                                RecordHandle.RECORD_ID_PROTECTION_HANDLE);
563:
564:                // First try to get the lock NOWAIT, while latch is held.
565:                boolean ret_status = _lockScan(scan_lock_rh, forUpdate, false /* NOWAIT */);
566:
567:                if (!ret_status) {
568:                    current_leaf.release();
569:                    current_leaf = null;
570:
571:                    if (aux_control_row != null) {
572:                        aux_control_row.release();
573:                        aux_control_row = null;
574:                    }
575:
576:                    // Could not get the lock NOWAIT, release latch and wait
577:                    // for the lock.
578:                    _lockScan(scan_lock_rh, forUpdate, true /* WAIT */);
579:
580:                    // once we get the lock, give it up as we need to get the lock
581:                    // while we have the latch.  When the lock manager gives us the
582:                    // ability to do instantaneous locks do that.  We just wait on the
583:                    // lock to give the split a chance to finish before we interfere.
584:
585:                    if (!forUpdate) {
586:                        scan_locking_policy.unlockRecordAfterRead(rawtran,
587:                                open_btree.getContainerHandle(), scan_lock_rh,
588:                                false, true);
589:                    } else {
590:                        // RESOLVE - need instantaneous locks as there is no way 
591:                        // currently to release a write lock.  This lock will only
592:                        // be requested by split, and will be released by internal
593:                        // transaction.
594:                    }
595:                }
596:
597:                return (ret_status);
598:            }
599:
600:            /**
601:             * Lock a control row page for reclaiming deleted rows.
602:             * <p>
603:             * When reclaiming deleted rows during split need to get an exclusive
604:             * scan lock on the page, which will mean there are no other scans 
605:             * positioned on the page.  If there are other scans positioned, just
606:             * give up on reclaiming space now.
607:             *
608:             * @return true if lock was granted nowait, else false and not lock was
609:             *         granted.
610:             *
611:             * @exception  StandardException  Standard exception policy.
612:             **/
613:            public boolean lockScanForReclaimSpace(LeafControlRow current_leaf)
614:                    throws StandardException {
615:                // The scan page lock is implemented as a row lock on the reserved
616:                // row id on the page (RecordHandle.RECORD_ID_PROTECTION_HANDLE).
617:                RecordHandle scan_lock_rh = current_leaf.getPage()
618:                        .makeRecordHandle(
619:                                RecordHandle.RECORD_ID_PROTECTION_HANDLE);
620:
621:                // First try to get the lock NOWAIT, while latch is held.
622:                return (_lockScan(scan_lock_rh, true /* update */, false /* NOWAIT */));
623:            }
624:
625:            /**
626:             * Lock a btree row to determine if it is a committed deleted row.
627:             * <p>
628:             * @see BTreeLockingPolicy#lockScanCommittedDeletedRow
629:             *
630:             * @exception  StandardException  Standard exception policy.
631:             **/
632:            public boolean lockScanCommittedDeletedRow(OpenBTree open_btree,
633:                    LeafControlRow leaf, DataValueDescriptor[] template,
634:                    FetchDescriptor lock_fetch_desc, int slot_no)
635:                    throws StandardException {
636:                if (SanityManager.DEBUG) {
637:                    SanityManager.ASSERT(leaf != null);
638:
639:                    if (slot_no <= 0 || slot_no >= leaf.getPage().recordCount()) {
640:                        SanityManager.THROWASSERT("slot_no = " + slot_no
641:                                + "; leaf.getPage().recordCount() = "
642:                                + leaf.getPage().recordCount());
643:                    }
644:
645:                    SanityManager.ASSERT(template != null, "template is null");
646:                }
647:
648:                RowLocation row_loc = (RowLocation) template[((B2I) open_btree
649:                        .getConglomerate()).rowLocationColumn];
650:
651:                // Fetch the row location to lock.
652:                leaf.getPage().fetchFromSlot((RecordHandle) null, slot_no,
653:                        template, lock_fetch_desc, true);
654:
655:                // Request the lock NOWAIT, return status
656:                return (base_cc.lockRow(row_loc,
657:                        ConglomerateController.LOCK_UPD, false /* NOWAIT */,
658:                        TransactionManager.LOCK_COMMIT_DURATION));
659:            }
660:
661:            /**
662:             * Lock a row as part of doing the scan.
663:             * <p>
664:             * Lock the row at the given slot (or the previous row if slot is 0).
665:             * Get the scan lock on the page if "request_scan_lock" is true.
666:             * <p>
667:             * If this routine returns true all locks were acquired while maintaining
668:             * the latch on leaf.  If this routine returns false, locks may or may
669:             * not have been acquired, and the routine should be called again after
670:             * the client has researched the tree to reget the latch on the 
671:             * appropriate page.
672:             * (p>
673:             * As a sided effect stores the value of the record handle of the current
674:             * scan lock.
675:             *
676:             * @return Whether locks were acquired without releasing latch on leaf.
677:             *
678:             * @param open_btree        The open_btree to associate latches with - 
679:             *                          used if routine has to scan backward.
680:             * @param btree             the conglomerate info.
681:             * @param pos               The position of the row to lock.
682:             * @param request_scan_lock Whether to request the page scan lock, should
683:             *                          only be requested once per page in the scan.
684:             * @param lock_template     A scratch area to use to read in rows.
685:             * @param previous_key_lock Is this a previous key lock call?
686:             * @param forUpdate         Is the scan for update or for read only.
687:             *
688:             * @exception  StandardException  Standard exception policy.
689:             **/
690:            public boolean lockScanRow(OpenBTree open_btree, BTree btree,
691:                    BTreeRowPosition pos, boolean request_scan_lock,
692:                    FetchDescriptor lock_fetch_desc,
693:                    DataValueDescriptor[] lock_template,
694:                    RowLocation lock_row_loc, boolean previous_key_lock,
695:                    boolean forUpdate, int lock_operation)
696:                    throws StandardException {
697:                return (_lockScanRow(open_btree, btree,
698:                        pos,
699:                        true, // request the row lock (always true for iso 3 )
700:                        request_scan_lock, lock_fetch_desc, lock_template,
701:                        lock_row_loc, previous_key_lock, forUpdate,
702:                        lock_operation));
703:            }
704:
705:            /**
706:             * Release read lock on a row.
707:             *
708:             * For serializable, there is no work to do.
709:             *
710:             *
711:             **/
712:            public void unlockScanRecordAfterRead(BTreeRowPosition pos,
713:                    boolean forUpdate) throws StandardException {
714:                return;
715:            }
716:
717:            /**
718:             * Release the lock gotten by calling lockScan.  This call can only be
719:             * made to release read scan locks, write scan locks must be held until
720:             * end of transaction.
721:             * <p>
722:             * See BTree.unlockScan() for more info.
723:             *
724:             **/
725:            public void unlockScan(long page_number) {
726:                // This is first row in table, lock the special key that 
727:                // represents the key previous to the first key of the table.
728:                try {
729:                    RecordHandle scan_lock_rh = open_btree.makeRecordHandle(
730:                            page_number,
731:                            RecordHandle.RECORD_ID_PROTECTION_HANDLE);
732:
733:                    scan_locking_policy.unlockRecordAfterRead(rawtran,
734:                            open_btree.getContainerHandle(), scan_lock_rh,
735:                            false, true);
736:                } catch (StandardException se) {
737:                    if (SanityManager.DEBUG)
738:                        SanityManager
739:                                .THROWASSERT("error from make RecordHandle.");
740:                }
741:
742:            }
743:
744:            /**************************************************************************
745:             * Abstract Protected lockNonScan*() locking methods of BTree:
746:             *
747:             *     lockNonScanPreviousRow   - lock the row previous to the current
748:             *     lockNonScanRow           - lock the input row
749:             **************************************************************************
750:             */
751:
752:            /**
753:             * Lock the row previous to the input row.
754:             * <p>
755:             * See BTree.lockPreviousRow() for more info.
756:             *
757:             * @exception  StandardException  Standard exception policy.
758:             **/
759:            public boolean lockNonScanPreviousRow(BTree btree,
760:                    LeafControlRow current_leaf, int current_slot,
761:                    FetchDescriptor lock_fetch_desc,
762:                    DataValueDescriptor[] lock_template,
763:                    RowLocation lock_row_loc, OpenBTree open_btree,
764:                    int lock_operation, int lock_duration)
765:                    throws StandardException {
766:                boolean ret_status;
767:
768:                if (SanityManager.DEBUG) {
769:                    SanityManager.ASSERT(btree instanceof  B2I);
770:                }
771:
772:                if (current_slot > 1) {
773:                    // Easy case, just lock the key previous to the current one.
774:
775:                    // Lock (current_slot - 1)
776:
777:                    ret_status = lockRowOnPage(btree, current_leaf,
778:                            (LeafControlRow) null, current_slot - 1, false,
779:                            lock_fetch_desc, lock_template, lock_row_loc,
780:                            lock_operation, lock_duration);
781:                } else {
782:                    // Should only be called while pointing at a valid location, 0 
783:                    // is not a valid key slot - it is the control row.
784:                    if (SanityManager.DEBUG)
785:                        SanityManager.ASSERT(current_slot == 1);
786:
787:                    if (current_leaf.isLeftmostLeaf()) {
788:                        // This is first row in table, lock the special key that 
789:                        // represents the key previous to the first key of the table.
790:                        ret_status = lockPreviousToFirstKey(current_leaf,
791:                                (LeafControlRow) null, lock_operation,
792:                                lock_duration);
793:                    } else {
794:                        // The previous key is on a previous page, search left 
795:                        // through the pages to find the key to latch.
796:
797:                        // RESOLVE RLL (mikem) - do I need to do the 
798:                        // RECORD_ID_PROTECTION_HANDLE lock.
799:                        // First guarantee that record id's will not move off this
800:                        // current page while searching for previous key, by getting
801:                        // the RECORD_ID_PROTECTION_HANDLE lock on the current page.
802:                        // Since we have a latch on the cur
803:
804:                        // RESOLVE RLL (mikem) - NO RECORD_ID PROTECTION IN EFFECT.
805:                        // caller must research, get new locks if this routine 
806:                        // releases latches.
807:                        ret_status = this .searchLeftAndLockPreviousKey(
808:                                (B2I) btree, current_leaf, current_slot,
809:                                lock_fetch_desc, lock_template, lock_row_loc,
810:                                open_btree, lock_operation, lock_duration);
811:                    }
812:                }
813:
814:                return (ret_status);
815:            }
816:
817:            /**
818:             * Lock the in memory row.
819:             * <p>
820:             * See BTree.lockRow() for more info.
821:             *
822:             * @exception  StandardException  Standard exception policy.
823:             **/
824:            public boolean lockNonScanRow(BTree btree,
825:                    LeafControlRow current_leaf, LeafControlRow aux_leaf,
826:                    DataValueDescriptor[] current_row, int lock_operation)
827:                    throws StandardException {
828:                if (SanityManager.DEBUG) {
829:                    SanityManager.ASSERT(btree instanceof  B2I);
830:                }
831:                B2I b2i = (B2I) btree;
832:
833:                // First try to get the lock NOWAIT, while latch is held.
834:                boolean ret_status = base_cc.lockRow(
835:                        (RowLocation) current_row[b2i.rowLocationColumn],
836:                        lock_operation, false /* NOWAIT */,
837:                        TransactionManager.LOCK_COMMIT_DURATION);
838:
839:                if (!ret_status) {
840:                    // Could not get the lock NOWAIT, release latch and wait for lock.
841:
842:                    if (current_leaf != null) {
843:                        current_leaf.release();
844:                        current_leaf = null;
845:                    }
846:                    if (aux_leaf != null) {
847:                        aux_leaf.release();
848:                        aux_leaf = null;
849:                    }
850:
851:                    base_cc.lockRow(
852:                            (RowLocation) current_row[b2i.rowLocationColumn],
853:                            lock_operation, true /* WAIT */,
854:                            TransactionManager.LOCK_COMMIT_DURATION);
855:                }
856:
857:                return (ret_status);
858:            }
859:
860:            public boolean lockNonScanRowOnPage(BTree btree,
861:                    LeafControlRow current_leaf, int current_slot,
862:                    FetchDescriptor lock_fetch_desc,
863:                    DataValueDescriptor[] lock_template,
864:                    RowLocation lock_row_loc, int lock_operation)
865:                    throws StandardException {
866:                return (lockRowOnPage(btree, current_leaf, null, current_slot,
867:                        false, lock_fetch_desc, lock_template, lock_row_loc,
868:                        lock_operation, TransactionManager.LOCK_COMMIT_DURATION));
869:            }
870:        }
www___.__jav__a_2__s___.___c_o__m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.