Source Code Cross Referenced for Cursor.java in  » JMX » je » com » sleepycat » je » 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 » JMX » je » com.sleepycat.je 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*-
0002:         * See the file LICENSE for redistribution information.
0003:         *
0004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
0005:         *
0006:         * $Id: Cursor.java,v 1.202.2.4 2008/01/07 15:14:07 cwl Exp $
0007:         */
0008:
0009:        package com.sleepycat.je;
0010:
0011:        import java.util.logging.Level;
0012:        import java.util.logging.Logger;
0013:
0014:        import com.sleepycat.je.dbi.CursorImpl;
0015:        import com.sleepycat.je.dbi.DatabaseImpl;
0016:        import com.sleepycat.je.dbi.GetMode;
0017:        import com.sleepycat.je.dbi.PutMode;
0018:        import com.sleepycat.je.dbi.RangeRestartException;
0019:        import com.sleepycat.je.dbi.CursorImpl.KeyChangeStatus;
0020:        import com.sleepycat.je.dbi.CursorImpl.SearchMode;
0021:        import com.sleepycat.je.latch.LatchSupport;
0022:        import com.sleepycat.je.tree.BIN;
0023:        import com.sleepycat.je.tree.DBIN;
0024:        import com.sleepycat.je.tree.Key;
0025:        import com.sleepycat.je.tree.LN;
0026:        import com.sleepycat.je.tree.Node;
0027:        import com.sleepycat.je.txn.BuddyLocker;
0028:        import com.sleepycat.je.txn.LockType;
0029:        import com.sleepycat.je.txn.Locker;
0030:        import com.sleepycat.je.txn.LockerFactory;
0031:        import com.sleepycat.je.utilint.DatabaseUtil;
0032:        import com.sleepycat.je.utilint.InternalException;
0033:
0034:        /**
0035:         * Javadoc for this public class is generated
0036:         * via the doc templates in the doc_src directory.
0037:         */
0038:        public class Cursor {
0039:
0040:            /**
0041:             * The underlying cursor.
0042:             */
0043:            CursorImpl cursorImpl; // Used by subclasses.
0044:
0045:            /**
0046:             * The CursorConfig used to configure this cursor.
0047:             */
0048:            CursorConfig config;
0049:
0050:            /**
0051:             * True if update operations are prohibited through this cursor.  Update
0052:             * operations are prohibited if the database is read-only or:
0053:             *
0054:             * (1) The database is transactional,
0055:             *
0056:             * and
0057:             *
0058:             * (2) The user did not supply a txn to the cursor ctor (meaning, the
0059:             * locker is non-transactional).
0060:             */
0061:            private boolean updateOperationsProhibited;
0062:
0063:            /**
0064:             * Handle under which this cursor was created; may be null.
0065:             */
0066:            private Database dbHandle;
0067:
0068:            /**
0069:             * Database implementation.
0070:             */
0071:            private DatabaseImpl dbImpl;
0072:
0073:            /* Attributes */
0074:            private boolean readUncommittedDefault;
0075:            private boolean serializableIsolationDefault;
0076:
0077:            private Logger logger;
0078:
0079:            /**
0080:             * Creates a cursor for a given user transaction.
0081:             *
0082:             * <p>If txn is null, a non-transactional cursor will be created that
0083:             * releases locks for the prior operation when the next operation
0084:             * suceeds.</p>
0085:             */
0086:            Cursor(Database dbHandle, Transaction txn, CursorConfig cursorConfig)
0087:                    throws DatabaseException {
0088:
0089:                if (cursorConfig == null) {
0090:                    cursorConfig = CursorConfig.DEFAULT;
0091:                }
0092:
0093:                Locker locker = LockerFactory.getReadableLocker(dbHandle
0094:                        .getEnvironment(), txn, dbHandle.isTransactional(),
0095:                        false, // retainNonTxnLocks
0096:                        cursorConfig.getReadCommitted());
0097:
0098:                init(dbHandle, dbHandle.getDatabaseImpl(), locker, dbHandle
0099:                        .isWritable(), cursorConfig);
0100:            }
0101:
0102:            /**
0103:             * Creates a cursor for a given locker.
0104:             *
0105:             * <p>If locker is null or is non-transactional, a non-transactional cursor
0106:             * will be created that releases locks for the prior operation when the
0107:             * next operation suceeds.</p>
0108:             */
0109:            Cursor(Database dbHandle, Locker locker, CursorConfig cursorConfig)
0110:                    throws DatabaseException {
0111:
0112:                if (cursorConfig == null) {
0113:                    cursorConfig = CursorConfig.DEFAULT;
0114:                }
0115:
0116:                locker = LockerFactory.getReadableLocker(dbHandle
0117:                        .getEnvironment(), dbHandle, locker, false, // retainNonTxnLocks
0118:                        cursorConfig.getReadCommitted());
0119:
0120:                init(dbHandle, dbHandle.getDatabaseImpl(), locker, dbHandle
0121:                        .isWritable(), cursorConfig);
0122:            }
0123:
0124:            /**
0125:             * Creates a cursor for a given locker and no db handle.
0126:             *
0127:             * <p>The locker parameter must be non-null.  With this constructor, we use
0128:             * the given locker without applying any special rules for different
0129:             * isolation levels -- the caller must supply the correct locker.</p>
0130:             */
0131:            Cursor(DatabaseImpl dbImpl, Locker locker, CursorConfig cursorConfig)
0132:                    throws DatabaseException {
0133:
0134:                if (cursorConfig == null) {
0135:                    cursorConfig = CursorConfig.DEFAULT;
0136:                }
0137:
0138:                init(null, dbImpl, locker, true, cursorConfig);
0139:            }
0140:
0141:            private void init(Database dbHandle, DatabaseImpl dbImpl,
0142:                    Locker locker, boolean isWritable, CursorConfig cursorConfig)
0143:                    throws DatabaseException {
0144:
0145:                assert locker != null;
0146:                assert dbImpl != null;
0147:
0148:                cursorImpl = new CursorImpl(dbImpl, locker, false /*retainNonTxnLocks*/);
0149:
0150:                /* Perform eviction for user cursors. */
0151:                cursorImpl.setAllowEviction(true);
0152:
0153:                readUncommittedDefault = cursorConfig.getReadUncommitted()
0154:                        || locker.isReadUncommittedDefault();
0155:
0156:                serializableIsolationDefault = cursorImpl.getLocker()
0157:                        .isSerializableIsolation();
0158:
0159:                updateOperationsProhibited = (dbImpl.isTransactional() && !locker
0160:                        .isTransactional())
0161:                        || !isWritable;
0162:
0163:                this .dbImpl = dbImpl;
0164:                this .dbHandle = dbHandle;
0165:                if (dbHandle != null) {
0166:                    dbHandle.addCursor(this );
0167:                }
0168:                this .config = cursorConfig;
0169:                this .logger = dbImpl.getDbEnvironment().getLogger();
0170:            }
0171:
0172:            /**
0173:             * Copy constructor.
0174:             */
0175:            Cursor(Cursor cursor, boolean samePosition)
0176:                    throws DatabaseException {
0177:
0178:                readUncommittedDefault = cursor.readUncommittedDefault;
0179:                serializableIsolationDefault = cursor.serializableIsolationDefault;
0180:                updateOperationsProhibited = cursor.updateOperationsProhibited;
0181:
0182:                cursorImpl = cursor.cursorImpl.dup(samePosition);
0183:                dbImpl = cursor.dbImpl;
0184:                dbHandle = cursor.dbHandle;
0185:                if (dbHandle != null) {
0186:                    dbHandle.addCursor(this );
0187:                }
0188:                config = cursor.config;
0189:                logger = dbImpl.getDbEnvironment().getLogger();
0190:            }
0191:
0192:            /**
0193:             * Internal entrypoint.
0194:             */
0195:            CursorImpl getCursorImpl() {
0196:                return cursorImpl;
0197:            }
0198:
0199:            /**
0200:             * Javadoc for this public method is generated via
0201:             * the doc templates in the doc_src directory.
0202:             */
0203:            public Database getDatabase() {
0204:                return dbHandle;
0205:            }
0206:
0207:            /**
0208:             * Always returns non-null, while getDatabase() returns null if no handle
0209:             * is associated with this cursor.
0210:             */
0211:            DatabaseImpl getDatabaseImpl() {
0212:                return dbImpl;
0213:            }
0214:
0215:            /**
0216:             * Javadoc for this public method is generated via
0217:             * the doc templates in the doc_src directory.
0218:             */
0219:            public CursorConfig getConfig() {
0220:                try {
0221:                    return config.cloneConfig();
0222:                } catch (Error E) {
0223:                    dbImpl.getDbEnvironment().invalidate(E);
0224:                    throw E;
0225:                }
0226:            }
0227:
0228:            void setNonCloning(boolean nonCloning) {
0229:                cursorImpl.setNonCloning(nonCloning);
0230:            }
0231:
0232:            /**
0233:             * Javadoc for this public method is generated via
0234:             * the doc templates in the doc_src directory.
0235:             */
0236:            public void close() throws DatabaseException {
0237:
0238:                close(true /*releaseNonTxnLocks*/);
0239:            }
0240:
0241:            /**
0242:             * @param releaseNonTxnLocks should normally be true.  See
0243:             * CursorImpl.close(boolean) [#15573]
0244:             */
0245:            synchronized void close(boolean releaseNonTxnLocks)
0246:                    throws DatabaseException {
0247:
0248:                try {
0249:                    checkState(false);
0250:                    cursorImpl.close(releaseNonTxnLocks);
0251:                    if (dbHandle != null) {
0252:                        dbHandle.removeCursor(this );
0253:                    }
0254:                } catch (Error E) {
0255:                    dbImpl.getDbEnvironment().invalidate(E);
0256:                    throw E;
0257:                }
0258:            }
0259:
0260:            /**
0261:             * Javadoc for this public method is generated via
0262:             * the doc templates in the doc_src directory.
0263:             */
0264:            public int count() throws DatabaseException {
0265:
0266:                checkState(true);
0267:                trace(Level.FINEST, "Cursor.count: ", null);
0268:
0269:                /*
0270:                 * Specify a null LockMode to use default locking.  The API doesn't
0271:                 * allow specifying a lock mode, but we should at least honor the
0272:                 * configured default.
0273:                 */
0274:                return countInternal(null);
0275:            }
0276:
0277:            /**
0278:             * Javadoc for this public method is generated via
0279:             * the doc templates in the doc_src directory.
0280:             */
0281:            public Cursor dup(boolean samePosition) throws DatabaseException {
0282:
0283:                try {
0284:                    checkState(false);
0285:                    return new Cursor(this , samePosition);
0286:                } catch (Error E) {
0287:                    dbImpl.getDbEnvironment().invalidate(E);
0288:                    throw E;
0289:                }
0290:            }
0291:
0292:            /**
0293:             * Javadoc for this public method is generated via
0294:             * the doc templates in the doc_src directory.
0295:             */
0296:            public OperationStatus delete() throws DatabaseException {
0297:
0298:                checkState(true);
0299:                checkUpdatesAllowed("delete");
0300:                trace(Level.FINEST, "Cursor.delete: ", null);
0301:
0302:                return deleteInternal();
0303:            }
0304:
0305:            /**
0306:             * Javadoc for this public method is generated via
0307:             * the doc templates in the doc_src directory.
0308:             */
0309:            public OperationStatus put(DatabaseEntry key, DatabaseEntry data)
0310:                    throws DatabaseException {
0311:
0312:                checkState(false);
0313:                DatabaseUtil.checkForNullDbt(key, "key", true);
0314:                DatabaseUtil.checkForNullDbt(data, "data", true);
0315:                DatabaseUtil.checkForPartialKey(key);
0316:                checkUpdatesAllowed("put");
0317:                trace(Level.FINEST, "Cursor.put: ", key, data, null);
0318:
0319:                return putInternal(key, data, PutMode.OVERWRITE);
0320:            }
0321:
0322:            /**
0323:             * Javadoc for this public method is generated via
0324:             * the doc templates in the doc_src directory.
0325:             */
0326:            public OperationStatus putNoOverwrite(DatabaseEntry key,
0327:                    DatabaseEntry data) throws DatabaseException {
0328:
0329:                checkState(false);
0330:                DatabaseUtil.checkForNullDbt(key, "key", true);
0331:                DatabaseUtil.checkForNullDbt(data, "data", true);
0332:                DatabaseUtil.checkForPartialKey(key);
0333:                checkUpdatesAllowed("putNoOverwrite");
0334:                trace(Level.FINEST, "Cursor.putNoOverwrite: ", key, data, null);
0335:
0336:                return putInternal(key, data, PutMode.NOOVERWRITE);
0337:            }
0338:
0339:            /**
0340:             * Javadoc for this public method is generated via
0341:             * the doc templates in the doc_src directory.
0342:             */
0343:            public OperationStatus putNoDupData(DatabaseEntry key,
0344:                    DatabaseEntry data) throws DatabaseException {
0345:
0346:                checkState(false);
0347:                DatabaseUtil.checkForNullDbt(key, "key", true);
0348:                DatabaseUtil.checkForNullDbt(data, "data", true);
0349:                DatabaseUtil.checkForPartialKey(key);
0350:                checkUpdatesAllowed("putNoDupData");
0351:                trace(Level.FINEST, "Cursor.putNoDupData: ", key, data, null);
0352:
0353:                return putInternal(key, data, PutMode.NODUP);
0354:            }
0355:
0356:            /**
0357:             * Javadoc for this public method is generated via
0358:             * the doc templates in the doc_src directory.
0359:             */
0360:            public OperationStatus putCurrent(DatabaseEntry data)
0361:                    throws DatabaseException {
0362:
0363:                checkState(true);
0364:                DatabaseUtil.checkForNullDbt(data, "data", true);
0365:                checkUpdatesAllowed("putCurrent");
0366:                trace(Level.FINEST, "Cursor.putCurrent: ", null, data, null);
0367:
0368:                return putInternal(null, data, PutMode.CURRENT);
0369:            }
0370:
0371:            /**
0372:             * Javadoc for this public method is generated via
0373:             * the doc templates in the doc_src directory.
0374:             */
0375:            public OperationStatus getCurrent(DatabaseEntry key,
0376:                    DatabaseEntry data, LockMode lockMode)
0377:                    throws DatabaseException {
0378:
0379:                try {
0380:                    checkState(true);
0381:                    checkArgsNoValRequired(key, data);
0382:                    trace(Level.FINEST, "Cursor.getCurrent: ", lockMode);
0383:
0384:                    return getCurrentInternal(key, data, lockMode);
0385:                } catch (Error E) {
0386:                    dbImpl.getDbEnvironment().invalidate(E);
0387:                    throw E;
0388:                }
0389:            }
0390:
0391:            /**
0392:             * Javadoc for this public method is generated via
0393:             * the doc templates in the doc_src directory.
0394:             */
0395:            public OperationStatus getFirst(DatabaseEntry key,
0396:                    DatabaseEntry data, LockMode lockMode)
0397:                    throws DatabaseException {
0398:
0399:                checkState(false);
0400:                checkArgsNoValRequired(key, data);
0401:                trace(Level.FINEST, "Cursor.getFirst: ", lockMode);
0402:
0403:                return position(key, data, lockMode, true);
0404:            }
0405:
0406:            /**
0407:             * Javadoc for this public method is generated via
0408:             * the doc templates in the doc_src directory.
0409:             */
0410:            public OperationStatus getLast(DatabaseEntry key,
0411:                    DatabaseEntry data, LockMode lockMode)
0412:                    throws DatabaseException {
0413:
0414:                checkState(false);
0415:                checkArgsNoValRequired(key, data);
0416:                trace(Level.FINEST, "Cursor.getLast: ", lockMode);
0417:
0418:                return position(key, data, lockMode, false);
0419:            }
0420:
0421:            /**
0422:             * Javadoc for this public method is generated via
0423:             * the doc templates in the doc_src directory.
0424:             */
0425:            public OperationStatus getNext(DatabaseEntry key,
0426:                    DatabaseEntry data, LockMode lockMode)
0427:                    throws DatabaseException {
0428:
0429:                checkState(false);
0430:                checkArgsNoValRequired(key, data);
0431:                trace(Level.FINEST, "Cursor.getNext: ", lockMode);
0432:
0433:                if (cursorImpl.isNotInitialized()) {
0434:                    return position(key, data, lockMode, true);
0435:                } else {
0436:                    return retrieveNext(key, data, lockMode, GetMode.NEXT);
0437:                }
0438:            }
0439:
0440:            /**
0441:             * Javadoc for this public method is generated via
0442:             * the doc templates in the doc_src directory.
0443:             */
0444:            public OperationStatus getNextDup(DatabaseEntry key,
0445:                    DatabaseEntry data, LockMode lockMode)
0446:                    throws DatabaseException {
0447:
0448:                checkState(true);
0449:                checkArgsNoValRequired(key, data);
0450:                trace(Level.FINEST, "Cursor.getNextDup: ", lockMode);
0451:
0452:                return retrieveNext(key, data, lockMode, GetMode.NEXT_DUP);
0453:            }
0454:
0455:            /**
0456:             * Javadoc for this public method is generated via
0457:             * the doc templates in the doc_src directory.
0458:             */
0459:            public OperationStatus getNextNoDup(DatabaseEntry key,
0460:                    DatabaseEntry data, LockMode lockMode)
0461:                    throws DatabaseException {
0462:
0463:                checkState(false);
0464:                checkArgsNoValRequired(key, data);
0465:                trace(Level.FINEST, "Cursor.getNextNoDup: ", lockMode);
0466:
0467:                if (cursorImpl.isNotInitialized()) {
0468:                    return position(key, data, lockMode, true);
0469:                } else {
0470:                    return retrieveNext(key, data, lockMode, GetMode.NEXT_NODUP);
0471:                }
0472:            }
0473:
0474:            /**
0475:             * Javadoc for this public method is generated via
0476:             * the doc templates in the doc_src directory.
0477:             */
0478:            public OperationStatus getPrev(DatabaseEntry key,
0479:                    DatabaseEntry data, LockMode lockMode)
0480:                    throws DatabaseException {
0481:
0482:                checkState(false);
0483:                checkArgsNoValRequired(key, data);
0484:                trace(Level.FINEST, "Cursor.getPrev: ", lockMode);
0485:
0486:                if (cursorImpl.isNotInitialized()) {
0487:                    return position(key, data, lockMode, false);
0488:                } else {
0489:                    return retrieveNext(key, data, lockMode, GetMode.PREV);
0490:                }
0491:            }
0492:
0493:            /**
0494:             * Javadoc for this public method is generated via
0495:             * the doc templates in the doc_src directory.
0496:             */
0497:            public OperationStatus getPrevDup(DatabaseEntry key,
0498:                    DatabaseEntry data, LockMode lockMode)
0499:                    throws DatabaseException {
0500:
0501:                checkState(true);
0502:                checkArgsNoValRequired(key, data);
0503:                trace(Level.FINEST, "Cursor.getPrevDup: ", lockMode);
0504:
0505:                return retrieveNext(key, data, lockMode, GetMode.PREV_DUP);
0506:            }
0507:
0508:            /**
0509:             * Javadoc for this public method is generated via
0510:             * the doc templates in the doc_src directory.
0511:             */
0512:            public OperationStatus getPrevNoDup(DatabaseEntry key,
0513:                    DatabaseEntry data, LockMode lockMode)
0514:                    throws DatabaseException {
0515:
0516:                checkState(false);
0517:                checkArgsNoValRequired(key, data);
0518:                trace(Level.FINEST, "Cursor.getPrevNoDup: ", lockMode);
0519:
0520:                if (cursorImpl.isNotInitialized()) {
0521:                    return position(key, data, lockMode, false);
0522:                } else {
0523:                    return retrieveNext(key, data, lockMode, GetMode.PREV_NODUP);
0524:                }
0525:            }
0526:
0527:            /**
0528:             * Javadoc for this public method is generated via
0529:             * the doc templates in the doc_src directory.
0530:             */
0531:            public OperationStatus getSearchKey(DatabaseEntry key,
0532:                    DatabaseEntry data, LockMode lockMode)
0533:                    throws DatabaseException {
0534:
0535:                checkState(false);
0536:                DatabaseUtil.checkForNullDbt(key, "key", true);
0537:                DatabaseUtil.checkForNullDbt(data, "data", false);
0538:                trace(Level.FINEST, "Cursor.getSearchKey: ", key, null,
0539:                        lockMode);
0540:
0541:                return search(key, data, lockMode, SearchMode.SET);
0542:            }
0543:
0544:            /**
0545:             * Javadoc for this public method is generated via
0546:             * the doc templates in the doc_src directory.
0547:             */
0548:            public OperationStatus getSearchKeyRange(DatabaseEntry key,
0549:                    DatabaseEntry data, LockMode lockMode)
0550:                    throws DatabaseException {
0551:
0552:                checkState(false);
0553:                DatabaseUtil.checkForNullDbt(key, "key", true);
0554:                DatabaseUtil.checkForNullDbt(data, "data", false);
0555:                trace(Level.FINEST, "Cursor.getSearchKeyRange: ", key, null,
0556:                        lockMode);
0557:
0558:                return search(key, data, lockMode, SearchMode.SET_RANGE);
0559:            }
0560:
0561:            /**
0562:             * Javadoc for this public method is generated via
0563:             * the doc templates in the doc_src directory.
0564:             */
0565:            public OperationStatus getSearchBoth(DatabaseEntry key,
0566:                    DatabaseEntry data, LockMode lockMode)
0567:                    throws DatabaseException {
0568:
0569:                checkState(false);
0570:                checkArgsValRequired(key, data);
0571:                trace(Level.FINEST, "Cursor.getSearchBoth: ", key, data,
0572:                        lockMode);
0573:
0574:                return search(key, data, lockMode, SearchMode.BOTH);
0575:            }
0576:
0577:            /**
0578:             * Javadoc for this public method is generated via
0579:             * the doc templates in the doc_src directory.
0580:             */
0581:            public OperationStatus getSearchBothRange(DatabaseEntry key,
0582:                    DatabaseEntry data, LockMode lockMode)
0583:                    throws DatabaseException {
0584:
0585:                checkState(false);
0586:                checkArgsValRequired(key, data);
0587:                trace(Level.FINEST, "Cursor.getSearchBothRange: ", key, data,
0588:                        lockMode);
0589:
0590:                return search(key, data, lockMode, SearchMode.BOTH_RANGE);
0591:            }
0592:
0593:            /**
0594:             * Counts duplicates without parameter checking.
0595:             */
0596:            int countInternal(LockMode lockMode) throws DatabaseException {
0597:
0598:                try {
0599:                    CursorImpl original = null;
0600:                    CursorImpl dup = null;
0601:
0602:                    /*
0603:                     * We depart from the usual beginRead/endRead sequence because
0604:                     * count() should not retain locks unless transactions are used.
0605:                     * Therefore we always close the dup cursor after using it.
0606:                     */
0607:                    try {
0608:                        original = cursorImpl;
0609:                        dup = original.cloneCursor(true);
0610:                        return dup.count(getLockType(lockMode, false));
0611:                    } finally {
0612:                        if (dup != original && dup != null) {
0613:                            dup.close();
0614:                        }
0615:                    }
0616:                } catch (Error E) {
0617:                    dbImpl.getDbEnvironment().invalidate(E);
0618:                    throw E;
0619:                }
0620:            }
0621:
0622:            /**
0623:             * Internal version of delete() that does no parameter checking.  Calls
0624:             * deleteNoNotify() and notifies triggers (performs secondary updates).
0625:             */
0626:            OperationStatus deleteInternal() throws DatabaseException {
0627:
0628:                try {
0629:                    /* Get existing data if updating secondaries. */
0630:                    DatabaseEntry oldKey = null;
0631:                    DatabaseEntry oldData = null;
0632:                    boolean doNotifyTriggers = dbHandle != null
0633:                            && dbHandle.hasTriggers();
0634:                    if (doNotifyTriggers) {
0635:                        oldKey = new DatabaseEntry();
0636:                        oldData = new DatabaseEntry();
0637:                        OperationStatus status = getCurrentInternal(oldKey,
0638:                                oldData, LockMode.RMW);
0639:                        if (status != OperationStatus.SUCCESS) {
0640:                            return OperationStatus.KEYEMPTY;
0641:                        }
0642:                    }
0643:
0644:                    /*
0645:                     * Notify triggers before the actual deletion so that a primary
0646:                     * record never exists while secondary keys refer to it.  This is
0647:                     * relied on by secondary read-uncommitted.
0648:                     */
0649:                    if (doNotifyTriggers) {
0650:                        dbHandle.notifyTriggers(cursorImpl.getLocker(), oldKey,
0651:                                oldData, null);
0652:                    }
0653:
0654:                    /* The actual deletion. */
0655:                    OperationStatus status = deleteNoNotify();
0656:                    return status;
0657:                } catch (Error E) {
0658:                    dbImpl.getDbEnvironment().invalidate(E);
0659:                    throw E;
0660:                }
0661:            }
0662:
0663:            /**
0664:             * Clone the cursor, delete at current position, and if successful, swap
0665:             * cursors.  Does not notify triggers (does not perform secondary updates).
0666:             */
0667:            OperationStatus deleteNoNotify() throws DatabaseException {
0668:
0669:                CursorImpl original = null;
0670:                CursorImpl dup = null;
0671:                OperationStatus status = OperationStatus.KEYEMPTY;
0672:                try {
0673:                    /* Clone, add dup to cursor. */
0674:                    original = cursorImpl;
0675:                    dup = original.cloneCursor(true);
0676:
0677:                    /* Latch the bins and do the delete with the dup. */
0678:                    dup.latchBINs();
0679:                    status = dup.delete();
0680:
0681:                    return status;
0682:                } finally {
0683:                    if (original != null) {
0684:                        original.releaseBINs();
0685:                    }
0686:                    if (dup != null) {
0687:                        dup.releaseBINs();
0688:                    }
0689:
0690:                    /* Swap if it was a success. */
0691:                    boolean success = (status == OperationStatus.SUCCESS);
0692:                    if (cursorImpl == dup) {
0693:                        if (!success) {
0694:                            cursorImpl.reset();
0695:                        }
0696:                    } else {
0697:                        if (success) {
0698:                            original.close();
0699:                            cursorImpl = dup;
0700:                        } else {
0701:                            dup.close();
0702:                        }
0703:                    }
0704:                }
0705:            }
0706:
0707:            /**
0708:             * Internal version of put() that does no parameter checking.  Calls
0709:             * putNoNotify() and notifies triggers (performs secondary updates).
0710:             * Prevents phantoms.
0711:             */
0712:            OperationStatus putInternal(DatabaseEntry key, DatabaseEntry data,
0713:                    PutMode putMode) throws DatabaseException {
0714:
0715:                try {
0716:                    /* Need to get existing data if updating secondaries. */
0717:                    DatabaseEntry oldData = null;
0718:                    boolean doNotifyTriggers = dbHandle != null
0719:                            && dbHandle.hasTriggers();
0720:                    if (doNotifyTriggers
0721:                            && (putMode == PutMode.CURRENT || putMode == PutMode.OVERWRITE)) {
0722:                        oldData = new DatabaseEntry();
0723:                        if (key == null && putMode == PutMode.CURRENT) {
0724:                            /* Key is returned by CursorImpl.putCurrent as foundKey. */
0725:                            key = new DatabaseEntry();
0726:                        }
0727:                    }
0728:
0729:                    /* Perform put. */
0730:                    OperationStatus commitStatus = putNoNotify(key, data,
0731:                            putMode, oldData);
0732:
0733:                    /* Notify triggers (update secondaries). */
0734:                    if (doNotifyTriggers
0735:                            && commitStatus == OperationStatus.SUCCESS) {
0736:                        if (oldData != null && oldData.getData() == null) {
0737:                            oldData = null;
0738:                        }
0739:                        dbHandle.notifyTriggers(cursorImpl.getLocker(), key,
0740:                                oldData, data);
0741:                    }
0742:                    return commitStatus;
0743:                } catch (Error E) {
0744:                    dbImpl.getDbEnvironment().invalidate(E);
0745:                    throw E;
0746:                }
0747:            }
0748:
0749:            /**
0750:             * Performs the put operation but does not notify triggers (does not
0751:             * perform secondary updates).  Prevents phantoms.
0752:             */
0753:            OperationStatus putNoNotify(DatabaseEntry key, DatabaseEntry data,
0754:                    PutMode putMode, DatabaseEntry returnOldData)
0755:                    throws DatabaseException {
0756:
0757:                Locker nextKeyLocker = null;
0758:                CursorImpl nextKeyCursor = null;
0759:                try {
0760:                    /* If other transactions are serializable, lock the next key. */
0761:                    Locker cursorLocker = cursorImpl.getLocker();
0762:                    if (putMode != PutMode.CURRENT
0763:                            && dbImpl.getDbEnvironment().getTxnManager()
0764:                                    .areOtherSerializableTransactionsActive(
0765:                                            cursorLocker)) {
0766:                        nextKeyLocker = new BuddyLocker(dbImpl
0767:                                .getDbEnvironment(), cursorLocker);
0768:                        nextKeyCursor = new CursorImpl(dbImpl, nextKeyLocker);
0769:                        /* Perform eviction for user cursors. */
0770:                        nextKeyCursor.setAllowEviction(true);
0771:                        nextKeyCursor.lockNextKeyForInsert(key, data);
0772:                    }
0773:
0774:                    /* Perform the put operation. */
0775:                    return putAllowPhantoms(key, data, putMode, returnOldData,
0776:                            nextKeyCursor);
0777:                } finally {
0778:                    /* Release the next-key lock. */
0779:                    if (nextKeyCursor != null) {
0780:                        nextKeyCursor.close();
0781:                    }
0782:                    if (nextKeyLocker != null) {
0783:                        nextKeyLocker.operationEnd();
0784:                    }
0785:                }
0786:            }
0787:
0788:            /**
0789:             * Clone the cursor, put key/data according to PutMode, and if successful,
0790:             * swap cursors.  Does not notify triggers (does not perform secondary
0791:             * updates).  Does not prevent phantoms.
0792:             *
0793:             * @param nextKeyCursor is the cursor used to lock the next key during
0794:             * phantom prevention.  If this cursor is non-null and initialized, it's
0795:             * BIN will be used to initialize the dup cursor used to perform insertion.
0796:             * This enables an optimization that skips the search for the BIN.
0797:             */
0798:            private OperationStatus putAllowPhantoms(DatabaseEntry key,
0799:                    DatabaseEntry data, PutMode putMode,
0800:                    DatabaseEntry returnOldData, CursorImpl nextKeyCursor)
0801:                    throws DatabaseException {
0802:
0803:                if (data == null) {
0804:                    throw new NullPointerException(
0805:                            "put passed a null DatabaseEntry arg");
0806:                }
0807:
0808:                if (putMode != PutMode.CURRENT && key == null) {
0809:                    throw new IllegalArgumentException(
0810:                            "put passed a null DatabaseEntry arg");
0811:                }
0812:
0813:                CursorImpl original = null;
0814:                OperationStatus status = OperationStatus.NOTFOUND;
0815:                CursorImpl dup = null;
0816:                try {
0817:                    /* Latch and clone. */
0818:                    original = cursorImpl;
0819:
0820:                    if (putMode == PutMode.CURRENT) {
0821:                        /* Call addCursor for putCurrent. */
0822:                        dup = original.cloneCursor(true);
0823:                    } else {
0824:
0825:                        /*
0826:                         * Do not call addCursor when inserting.  Copy the position of
0827:                         * nextKeyCursor if available.
0828:                         */
0829:                        dup = original.cloneCursor(false, nextKeyCursor);
0830:                    }
0831:
0832:                    /* Perform operation. */
0833:                    if (putMode == PutMode.CURRENT) {
0834:                        status = dup.putCurrent(data, key, returnOldData);
0835:                    } else if (putMode == PutMode.OVERWRITE) {
0836:                        status = dup.put(key, data, returnOldData);
0837:                    } else if (putMode == PutMode.NOOVERWRITE) {
0838:                        status = dup.putNoOverwrite(key, data);
0839:                    } else if (putMode == PutMode.NODUP) {
0840:                        status = dup.putNoDupData(key, data);
0841:                    } else {
0842:                        throw new InternalException("unknown PutMode");
0843:                    }
0844:
0845:                    return status;
0846:                } finally {
0847:                    if (original != null) {
0848:                        original.releaseBINs();
0849:                    }
0850:
0851:                    boolean success = (status == OperationStatus.SUCCESS);
0852:                    if (cursorImpl == dup) {
0853:                        if (!success) {
0854:                            cursorImpl.reset();
0855:                        }
0856:                    } else {
0857:                        if (success) {
0858:                            original.close();
0859:                            cursorImpl = dup;
0860:                        } else {
0861:                            if (dup != null) {
0862:                                dup.close();
0863:                            }
0864:                        }
0865:                    }
0866:                }
0867:            }
0868:
0869:            /**
0870:             * Position the cursor at the first or last record of the database.
0871:             * Prevents phantoms.
0872:             */
0873:            OperationStatus position(DatabaseEntry key, DatabaseEntry data,
0874:                    LockMode lockMode, boolean first) throws DatabaseException {
0875:
0876:                try {
0877:                    if (!isSerializableIsolation(lockMode)) {
0878:                        return positionAllowPhantoms(key, data, getLockType(
0879:                                lockMode, false), first);
0880:                    }
0881:
0882:                    /*
0883:                     * Perform range locking to prevent phantoms and handle restarts.
0884:                     */
0885:                    while (true) {
0886:                        try {
0887:                            /* Range lock the EOF node before getLast. */
0888:                            if (!first) {
0889:                                cursorImpl.lockEofNode(LockType.RANGE_READ);
0890:                            }
0891:
0892:                            /* Use a range lock for getFirst. */
0893:                            LockType lockType = getLockType(lockMode, first);
0894:
0895:                            /* Perform operation. */
0896:                            OperationStatus status = positionAllowPhantoms(key,
0897:                                    data, lockType, first);
0898:
0899:                            /*
0900:                             * Range lock the EOF node when getFirst returns NOTFOUND.
0901:                             */
0902:                            if (first && status != OperationStatus.SUCCESS) {
0903:                                cursorImpl.lockEofNode(LockType.RANGE_READ);
0904:                            }
0905:
0906:                            return status;
0907:                        } catch (RangeRestartException e) {
0908:                            continue;
0909:                        }
0910:                    }
0911:                } catch (Error E) {
0912:                    dbImpl.getDbEnvironment().invalidate(E);
0913:                    throw E;
0914:                }
0915:            }
0916:
0917:            /**
0918:             * Position without preventing phantoms.
0919:             */
0920:            private OperationStatus positionAllowPhantoms(DatabaseEntry key,
0921:                    DatabaseEntry data, LockType lockType, boolean first)
0922:                    throws DatabaseException {
0923:
0924:                assert (key != null && data != null);
0925:
0926:                OperationStatus status = OperationStatus.NOTFOUND;
0927:                CursorImpl dup = null;
0928:                try {
0929:
0930:                    /*
0931:                     * Pass false: no need to call addCursor here because
0932:                     * CursorImpl.position will be adding it after it finds the bin.
0933:                     */
0934:                    dup = beginRead(false);
0935:
0936:                    /* Search for first or last. */
0937:                    if (!dup.positionFirstOrLast(first, null)) {
0938:                        /* Tree is empty. */
0939:                        status = OperationStatus.NOTFOUND;
0940:                        assert LatchSupport.countLatchesHeld() == 0 : LatchSupport
0941:                                .latchesHeldToString();
0942:
0943:                    } else {
0944:                        /* Found something in this tree. */
0945:                        assert LatchSupport.countLatchesHeld() == 1 : LatchSupport
0946:                                .latchesHeldToString();
0947:                        status = dup.getCurrentAlreadyLatched(key, data,
0948:                                lockType, first);
0949:
0950:                        if (status == OperationStatus.SUCCESS) {
0951:                            if (dup.getDupBIN() != null) {
0952:                                dup.incrementLNCount();
0953:                            }
0954:                        } else {
0955:                            /* The record we're pointing at may be deleted. */
0956:                            status = dup.getNext(key, data, lockType, first,
0957:                                    false);
0958:                        }
0959:                    }
0960:                } finally {
0961:
0962:                    /*
0963:                     * positionFirstOrLast returns with the target BIN latched, so it
0964:                     * is the responsibility of this method to make sure the latches
0965:                     * are released.
0966:                     */
0967:                    cursorImpl.releaseBINs();
0968:                    endRead(dup, status == OperationStatus.SUCCESS);
0969:                }
0970:                return status;
0971:            }
0972:
0973:            /**
0974:             * Perform search by key, data, or both.  Prevents phantoms.
0975:             */
0976:            OperationStatus search(DatabaseEntry key, DatabaseEntry data,
0977:                    LockMode lockMode, SearchMode searchMode)
0978:                    throws DatabaseException {
0979:
0980:                try {
0981:                    if (!isSerializableIsolation(lockMode)) {
0982:                        LockType lockType = getLockType(lockMode, false);
0983:                        KeyChangeStatus result = searchAllowPhantoms(key, data,
0984:                                lockType, lockType, searchMode);
0985:                        return result.status;
0986:                    }
0987:
0988:                    /*
0989:                     * Perform range locking to prevent phantoms and handle restarts.
0990:                     */
0991:                    while (true) {
0992:                        try {
0993:                            /* Do not use a range lock for the initial search. */
0994:                            LockType searchLockType = getLockType(lockMode,
0995:                                    false);
0996:
0997:                            /* Switch to a range lock when advancing forward. */
0998:                            LockType advanceLockType = getLockType(lockMode,
0999:                                    true);
1000:
1001:                            /* Do not modify key/data params until SUCCESS. */
1002:                            DatabaseEntry tryKey = new DatabaseEntry(key
1003:                                    .getData(), key.getOffset(), key.getSize());
1004:                            DatabaseEntry tryData = new DatabaseEntry(data
1005:                                    .getData(), data.getOffset(), data
1006:                                    .getSize());
1007:                            KeyChangeStatus result;
1008:
1009:                            if (searchMode.isExactSearch()) {
1010:
1011:                                /*
1012:                                 * Artificial range search to range lock the next key.
1013:                                 */
1014:                                result = searchExactAndRangeLock(tryKey,
1015:                                        tryData, searchLockType,
1016:                                        advanceLockType, searchMode);
1017:                            } else {
1018:                                /* Normal range search. */
1019:                                result = searchAllowPhantoms(tryKey, tryData,
1020:                                        searchLockType, advanceLockType,
1021:                                        searchMode);
1022:
1023:                                /* Lock the EOF node if no records follow the key. */
1024:                                if (result.status != OperationStatus.SUCCESS) {
1025:                                    cursorImpl.lockEofNode(LockType.RANGE_READ);
1026:                                }
1027:                            }
1028:
1029:                            /*
1030:                             * Only overwrite key/data on SUCCESS, after all locking.
1031:                             */
1032:                            if (result.status == OperationStatus.SUCCESS) {
1033:                                key.setData(tryKey.getData(), 0, tryKey
1034:                                        .getSize());
1035:                                data.setData(tryData.getData(), 0, tryData
1036:                                        .getSize());
1037:                            }
1038:
1039:                            return result.status;
1040:                        } catch (RangeRestartException e) {
1041:                            continue;
1042:                        }
1043:                    }
1044:                } catch (Error E) {
1045:                    dbImpl.getDbEnvironment().invalidate(E);
1046:                    throw E;
1047:                }
1048:            }
1049:
1050:            /**
1051:             * For an exact search, perform a range search and return NOTFOUND if the
1052:             * key changes (or if the data changes for BOTH) during the search.
1053:             * If no exact match is found the range search will range lock the
1054:             * following key for phantom prevention.  Importantly, the cursor position
1055:             * is not changed if an exact match is not found, even though we advance to
1056:             * the following key in order to range lock it.
1057:             */
1058:            private KeyChangeStatus searchExactAndRangeLock(DatabaseEntry key,
1059:                    DatabaseEntry data, LockType searchLockType,
1060:                    LockType advanceLockType, SearchMode searchMode)
1061:                    throws DatabaseException {
1062:
1063:                /* Convert exact search to range search. */
1064:                searchMode = (searchMode == SearchMode.SET) ? SearchMode.SET_RANGE
1065:                        : SearchMode.BOTH_RANGE;
1066:
1067:                KeyChangeStatus result = null;
1068:                boolean noNextKeyFound;
1069:
1070:                CursorImpl dup = beginRead(false /* searchAndPosition will add cursor */);
1071:
1072:                try {
1073:
1074:                    /*
1075:                     * Perform a range search and return NOTFOUND if an exact match is
1076:                     * not found.  Pass advanceAfterRangeSearch=true to advance even if
1077:                     * the key is not matched, to lock the following key.
1078:                     */
1079:                    result = searchInternal(dup, key, data, searchLockType,
1080:                            advanceLockType, searchMode, true /*advanceAfterRangeSearch*/);
1081:
1082:                    /* The keyChange value is independent of the status value. */
1083:                    noNextKeyFound = !result.keyChange;
1084:
1085:                    /* If the key changed, then we do not have an exact match. */
1086:                    if (result.keyChange
1087:                            && result.status == OperationStatus.SUCCESS) {
1088:                        result.status = OperationStatus.NOTFOUND;
1089:                    }
1090:                } finally {
1091:                    endRead(dup, result != null
1092:                            && result.status == OperationStatus.SUCCESS);
1093:                }
1094:
1095:                /* Lock the EOF node if no more records, whether or not more dups. */
1096:                if (noNextKeyFound) {
1097:                    cursorImpl.lockEofNode(LockType.RANGE_READ);
1098:                }
1099:
1100:                return result;
1101:            }
1102:
1103:            /**
1104:             * Perform search without preventing phantoms.
1105:             */
1106:            private KeyChangeStatus searchAllowPhantoms(DatabaseEntry key,
1107:                    DatabaseEntry data, LockType searchLockType,
1108:                    LockType advanceLockType, SearchMode searchMode)
1109:                    throws DatabaseException {
1110:
1111:                OperationStatus status = OperationStatus.NOTFOUND;
1112:
1113:                CursorImpl dup = beginRead(false /* searchAndPosition will add cursor */);
1114:
1115:                try {
1116:                    KeyChangeStatus result = searchInternal(dup, key, data,
1117:                            searchLockType, advanceLockType, searchMode, false /*advanceAfterRangeSearch*/);
1118:
1119:                    status = result.status;
1120:                    return result;
1121:                } finally {
1122:                    endRead(dup, status == OperationStatus.SUCCESS);
1123:                }
1124:            }
1125:
1126:            /**
1127:             * Perform search for a given CursorImpl.
1128:             */
1129:            private KeyChangeStatus searchInternal(CursorImpl dup,
1130:                    DatabaseEntry key, DatabaseEntry data,
1131:                    LockType searchLockType, LockType advanceLockType,
1132:                    SearchMode searchMode, boolean advanceAfterRangeSearch)
1133:                    throws DatabaseException {
1134:
1135:                assert key != null && data != null;
1136:
1137:                OperationStatus status = OperationStatus.NOTFOUND;
1138:                boolean keyChange = false;
1139:
1140:                try {
1141:                    /* search */
1142:                    int searchResult = dup.searchAndPosition(key, data,
1143:                            searchMode, searchLockType);
1144:                    if ((searchResult & CursorImpl.FOUND) != 0) {
1145:
1146:                        /*
1147:                         * The search found a possibly valid record.
1148:                         * CursorImpl.searchAndPosition's job is to settle the cursor
1149:                         * at a particular location on a BIN. In some cases, the
1150:                         * current position may not actually hold a valid record, so
1151:                         * it's this layer's responsiblity to judge if it might need to
1152:                         * bump the cursor along and search more. For example, we might
1153:                         * have to do so if the position holds a deleted record.
1154:                         *
1155:                         * Advance the cursor if:
1156:                         *
1157:                         * 1. This is a range type search and there was no match on the
1158:                         * search criteria (the key or key and data depending on the
1159:                         * type of search). Then we search forward until there's a
1160:                         * match.
1161:                         *
1162:                         * 2. If this is not a range type search, check the record at
1163:                         * the current position. If this is not a duplicate set,
1164:                         * CursorImpl.searchAndPosition gave us an exact answer.
1165:                         * However since it doesn't peer into the duplicate set, we may
1166:                         * need to probe further in if there are deleted records in the
1167:                         * duplicate set. i.e, we have to be able to find k1/d2 even if
1168:                         * there's k1/d1(deleted), k1/d2, k1/d3, etc in a duplicate
1169:                         * set.
1170:                         *
1171:                         * Note that searchResult has four bits possibly set:
1172:                         *
1173:                         * FOUND has already been checked above.
1174:                         *
1175:                         * EXACT_KEY means an exact match on the key portion was made.
1176:                         *
1177:                         * EXACT_DATA means that if searchMode was BOTH or BOTH_RANGE
1178:                         * then an exact match was made on the data (in addition to the
1179:                         * key).
1180:                         *
1181:                         * FOUND_LAST means that the cursor is positioned at the last
1182:                         * record in the database.
1183:                         */
1184:                        boolean exactKeyMatch = ((searchResult & CursorImpl.EXACT_KEY) != 0);
1185:                        boolean exactDataMatch = ((searchResult & CursorImpl.EXACT_DATA) != 0);
1186:                        boolean foundLast = ((searchResult & CursorImpl.FOUND_LAST) != 0);
1187:
1188:                        /*
1189:                         * rangeMatch means that a range match of some sort (either
1190:                         * SET_RANGE or BOTH_RANGE) was specified and there wasn't a
1191:                         * complete match.  If SET_RANGE was spec'd and EXACT_KEY was
1192:                         * not returned as set, then the key didn't match exactly.  If
1193:                         * BOTH_RANGE was spec'd and EXACT_DATA was not returned as
1194:                         * set, then the data didn't match exactly.
1195:                         */
1196:                        boolean rangeMatch = false;
1197:                        if (searchMode == SearchMode.SET_RANGE
1198:                                && !exactKeyMatch) {
1199:                            rangeMatch = true;
1200:                        }
1201:
1202:                        if (searchMode == SearchMode.BOTH_RANGE
1203:                                && (!exactKeyMatch || !exactDataMatch)) {
1204:                            rangeMatch = true;
1205:                        }
1206:
1207:                        /*
1208:                         * Pass null for key to getCurrentAlreadyLatched if searchMode
1209:                         * is SET since the key is not supposed to be set in that case.
1210:                         */
1211:                        DatabaseEntry useKey = (searchMode == SearchMode.SET) ? null
1212:                                : key;
1213:
1214:                        /*
1215:                         * rangeMatch => an exact match was not found so we need to
1216:                         * advance the cursor to a real item using getNextXXX.  If
1217:                         * rangeMatch is true, then cursor is currently on some entry,
1218:                         * but that entry is either deleted or is prior to the target
1219:                         * key/data.  It is also possible that rangeMatch is false (we
1220:                         * have an exact match) but the entry is deleted.  So we test
1221:                         * for rangeMatch or a deleted entry, and if either is true
1222:                         * then we advance to the next non-deleted entry.
1223:                         */
1224:                        if (rangeMatch
1225:                                || (status = dup.getCurrentAlreadyLatched(
1226:                                        useKey, data, searchLockType, true)) == OperationStatus.KEYEMPTY) {
1227:
1228:                            if (foundLast) {
1229:                                status = OperationStatus.NOTFOUND;
1230:                            } else if (searchMode == SearchMode.SET) {
1231:
1232:                                /*
1233:                                 * SET is an exact operation, so this isn't a
1234:                                 * rangeMatch, it's a deleted record.  We should
1235:                                 * advance, but only to duplicates for the same key.
1236:                                 */
1237:                                status = dup.getNextDuplicate(key, data,
1238:                                        advanceLockType, true, rangeMatch);
1239:                            } else if (searchMode == SearchMode.BOTH) {
1240:
1241:                                /*
1242:                                 * BOTH is also an exact operation, but we should not
1243:                                 * advance past a deleted record because the data match
1244:                                 * is exact.  However, this API should return NOTFOUND
1245:                                 * instead of KEYEMPTY (which may be been set above).
1246:                                 */
1247:                                if (status == OperationStatus.KEYEMPTY) {
1248:                                    status = OperationStatus.NOTFOUND;
1249:                                }
1250:                            } else {
1251:                                assert !searchMode.isExactSearch();
1252:
1253:                                /* Save the search key for a BOTH_RANGE search. */
1254:                                byte[] searchKey = null;
1255:                                if (searchMode.isDataSearch()) {
1256:                                    searchKey = Key.makeKey(key);
1257:                                }
1258:
1259:                                /*
1260:                                 * This may be a deleted record or a rangeMatch, and in
1261:                                 * either case we should advance.  We must determine
1262:                                 * whether the key changes when we advance.
1263:                                 */
1264:                                if (exactKeyMatch) {
1265:                                    KeyChangeStatus result = dup
1266:                                            .getNextWithKeyChangeStatus(key,
1267:                                                    data, advanceLockType,
1268:                                                    true, rangeMatch);
1269:                                    status = result.status;
1270:
1271:                                    /*
1272:                                     * For BOTH_RANGE, advancing always causes a data
1273:                                     * change, which is considered a key change.  For
1274:                                     * SET_RANGE, getNextWithKeyChangeStatus determined
1275:                                     * the key change status.
1276:                                     */
1277:                                    keyChange = searchMode.isDataSearch() ? (status == OperationStatus.SUCCESS)
1278:                                            : result.keyChange;
1279:
1280:                                } else if (searchMode.isDataSearch()
1281:                                        && !advanceAfterRangeSearch) {
1282:
1283:                                    /*
1284:                                     * If we did not match the key (exactly) for
1285:                                     * BOTH_RANGE, and advanceAfterSearchRangeBoth is
1286:                                     * false, then return NOTFOUND.
1287:                                     */
1288:                                    status = OperationStatus.NOTFOUND;
1289:                                } else {
1290:
1291:                                    /*
1292:                                     * If we didn't match the key, skip over duplicates
1293:                                     * to the next key with getNextNoDup.
1294:                                     */
1295:                                    status = dup.getNextNoDup(key, data,
1296:                                            advanceLockType, true, rangeMatch);
1297:
1298:                                    /* getNextNoDup always causes a key change. */
1299:                                    keyChange = (status == OperationStatus.SUCCESS);
1300:                                }
1301:
1302:                                /*
1303:                                 * If we moved past the search key after a BOTH_RANGE
1304:                                 * search, return NOTFOUND.  Leave the keyChange value
1305:                                 * intact, since we want to return this accurately
1306:                                 * regardless of the status return.
1307:                                 */
1308:                                if (status == OperationStatus.SUCCESS
1309:                                        && searchMode.isDataSearch()) {
1310:                                    if (Key.compareKeys(key.getData(),
1311:                                            searchKey, dbImpl
1312:                                                    .getBtreeComparator()) != 0) {
1313:                                        status = OperationStatus.NOTFOUND;
1314:                                    }
1315:                                }
1316:                            }
1317:                        }
1318:                    }
1319:                } finally {
1320:
1321:                    /*
1322:                     * searchAndPosition returns with the target BIN latched, so it is
1323:                     * the responsibility of this method to make sure the latches are
1324:                     * released.
1325:                     */
1326:                    cursorImpl.releaseBINs();
1327:                    if (status != OperationStatus.SUCCESS && dup != cursorImpl) {
1328:                        dup.releaseBINs();
1329:                    }
1330:                }
1331:
1332:                return new KeyChangeStatus(status, keyChange);
1333:            }
1334:
1335:            /**
1336:             * Retrieve the next or previous record.  Prevents phantoms.
1337:             */
1338:            OperationStatus retrieveNext(DatabaseEntry key, DatabaseEntry data,
1339:                    LockMode lockMode, GetMode getMode)
1340:                    throws DatabaseException {
1341:
1342:                try {
1343:                    if (!isSerializableIsolation(lockMode)) {
1344:                        return retrieveNextAllowPhantoms(key, data,
1345:                                getLockType(lockMode, false), getMode);
1346:                    }
1347:
1348:                    /*
1349:                     * Perform range locking to prevent phantoms and handle restarts.
1350:                     */
1351:                    while (true) {
1352:                        try {
1353:                            OperationStatus status;
1354:                            if (getMode == GetMode.NEXT_DUP) {
1355:
1356:                                /*
1357:                                 * Special case to lock the next key if no more dups.
1358:                                 */
1359:                                status = getNextDupAndRangeLock(key, data,
1360:                                        lockMode);
1361:                            } else {
1362:
1363:                                /* Get a range lock for 'prev' operations. */
1364:                                if (!getMode.isForward()) {
1365:                                    rangeLockCurrentPosition(getMode);
1366:                                }
1367:
1368:                                /*
1369:                                 * Use a range lock if performing a 'next' operation.
1370:                                 */
1371:                                LockType lockType = getLockType(lockMode,
1372:                                        getMode.isForward());
1373:
1374:                                /* Perform the operation. */
1375:                                status = retrieveNextAllowPhantoms(key, data,
1376:                                        lockType, getMode);
1377:
1378:                                if (getMode.isForward()
1379:                                        && status != OperationStatus.SUCCESS) {
1380:                                    /* NEXT, NEXT_NODUP: lock the EOF node. */
1381:                                    cursorImpl.lockEofNode(LockType.RANGE_READ);
1382:                                }
1383:                            }
1384:
1385:                            return status;
1386:                        } catch (RangeRestartException e) {
1387:                            continue;
1388:                        }
1389:                    }
1390:                } catch (Error E) {
1391:                    dbImpl.getDbEnvironment().invalidate(E);
1392:                    throw E;
1393:                }
1394:            }
1395:
1396:            /**
1397:             * Retrieve the next dup; if no next dup is found then range lock the
1398:             * following key for phantom prevention.  Importantly, the cursor position
1399:             * is not changed if there are no more dups, even though we advance to the
1400:             * following key in order to range lock it.
1401:             */
1402:            private OperationStatus getNextDupAndRangeLock(DatabaseEntry key,
1403:                    DatabaseEntry data, LockMode lockMode)
1404:                    throws DatabaseException {
1405:
1406:                /* Do not modify key/data params until SUCCESS. */
1407:                DatabaseEntry tryKey = new DatabaseEntry();
1408:                DatabaseEntry tryData = new DatabaseEntry();
1409:
1410:                /* Get a range lock. */
1411:                LockType lockType = getLockType(lockMode, true);
1412:                OperationStatus status;
1413:                boolean noNextKeyFound;
1414:
1415:                /*
1416:                 * Perform a NEXT and return NOTFOUND if the key changes
1417:                 * during the search.
1418:                 */
1419:                while (true) {
1420:                    assert LatchSupport.countLatchesHeld() == 0;
1421:                    CursorImpl dup = beginRead(true);
1422:
1423:                    try {
1424:                        KeyChangeStatus result = dup
1425:                                .getNextWithKeyChangeStatus(tryKey, tryData,
1426:                                        lockType, true, false);
1427:                        status = result.status;
1428:                        noNextKeyFound = (status != OperationStatus.SUCCESS);
1429:                        if (result.keyChange
1430:                                && status == OperationStatus.SUCCESS) {
1431:                            status = OperationStatus.NOTFOUND;
1432:                        }
1433:                    } catch (DatabaseException DBE) {
1434:                        endRead(dup, false);
1435:                        throw DBE;
1436:                    }
1437:
1438:                    if (checkForInsertion(GetMode.NEXT, cursorImpl, dup)) {
1439:                        endRead(dup, false);
1440:                        continue;
1441:                    } else {
1442:                        endRead(dup, status == OperationStatus.SUCCESS);
1443:                        assert LatchSupport.countLatchesHeld() == 0;
1444:                        break;
1445:                    }
1446:                }
1447:
1448:                /* Lock the EOF node if no more records, whether or not more dups. */
1449:                if (noNextKeyFound) {
1450:                    cursorImpl.lockEofNode(LockType.RANGE_READ);
1451:                }
1452:
1453:                /* Only overwrite key/data on SUCCESS. */
1454:                if (status == OperationStatus.SUCCESS) {
1455:                    key.setData(tryKey.getData(), 0, tryKey.getSize());
1456:                    data.setData(tryData.getData(), 0, tryData.getSize());
1457:                }
1458:
1459:                return status;
1460:            }
1461:
1462:            /**
1463:             * For 'prev' operations, upgrade to a range lock at the current position.
1464:             * For PREV_NODUP, range lock the first duplicate instead.  If there are no
1465:             * records at the current position, get a range lock on the next record or,
1466:             * if not found, on the logical EOF node.  Do not modify the current
1467:             * cursor position, use a separate cursor.
1468:             */
1469:            private void rangeLockCurrentPosition(GetMode getMode)
1470:                    throws DatabaseException {
1471:
1472:                DatabaseEntry tempKey = new DatabaseEntry();
1473:                DatabaseEntry tempData = new DatabaseEntry();
1474:                tempKey.setPartial(0, 0, true);
1475:                tempData.setPartial(0, 0, true);
1476:
1477:                OperationStatus status;
1478:                CursorImpl dup = cursorImpl.cloneCursor(true);
1479:                try {
1480:                    if (getMode == GetMode.PREV_NODUP) {
1481:                        status = dup.getFirstDuplicate(tempKey, tempData,
1482:                                LockType.RANGE_READ);
1483:                    } else {
1484:                        status = dup.getCurrent(tempKey, tempData,
1485:                                LockType.RANGE_READ);
1486:                    }
1487:                    if (status != OperationStatus.SUCCESS) {
1488:                        while (true) {
1489:                            assert LatchSupport.countLatchesHeld() == 0;
1490:
1491:                            status = dup.getNext(tempKey, tempData,
1492:                                    LockType.RANGE_READ, true, false);
1493:
1494:                            if (checkForInsertion(GetMode.NEXT, cursorImpl, dup)) {
1495:                                dup.close();
1496:                                dup = cursorImpl.cloneCursor(true);
1497:                                continue;
1498:                            } else {
1499:                                assert LatchSupport.countLatchesHeld() == 0;
1500:                                break;
1501:                            }
1502:                        }
1503:                    }
1504:                } finally {
1505:                    if (cursorImpl == dup) {
1506:                        dup.reset();
1507:                    } else {
1508:                        dup.close();
1509:                    }
1510:                }
1511:
1512:                if (status != OperationStatus.SUCCESS) {
1513:                    cursorImpl.lockEofNode(LockType.RANGE_READ);
1514:                }
1515:            }
1516:
1517:            /**
1518:             * Retrieve without preventing phantoms.
1519:             */
1520:            private OperationStatus retrieveNextAllowPhantoms(
1521:                    DatabaseEntry key, DatabaseEntry data, LockType lockType,
1522:                    GetMode getMode) throws DatabaseException {
1523:
1524:                assert (key != null && data != null);
1525:
1526:                OperationStatus status;
1527:
1528:                while (true) {
1529:                    assert LatchSupport.countLatchesHeld() == 0;
1530:                    CursorImpl dup = beginRead(true);
1531:
1532:                    try {
1533:                        if (getMode == GetMode.NEXT) {
1534:                            status = dup.getNext(key, data, lockType, true,
1535:                                    false);
1536:                        } else if (getMode == GetMode.PREV) {
1537:                            status = dup.getNext(key, data, lockType, false,
1538:                                    false);
1539:                        } else if (getMode == GetMode.NEXT_DUP) {
1540:                            status = dup.getNextDuplicate(key, data, lockType,
1541:                                    true, false);
1542:                        } else if (getMode == GetMode.PREV_DUP) {
1543:                            status = dup.getNextDuplicate(key, data, lockType,
1544:                                    false, false);
1545:                        } else if (getMode == GetMode.NEXT_NODUP) {
1546:                            status = dup.getNextNoDup(key, data, lockType,
1547:                                    true, false);
1548:                        } else if (getMode == GetMode.PREV_NODUP) {
1549:                            status = dup.getNextNoDup(key, data, lockType,
1550:                                    false, false);
1551:                        } else {
1552:                            throw new InternalException("unknown GetMode");
1553:                        }
1554:                    } catch (DatabaseException DBE) {
1555:                        endRead(dup, false);
1556:                        throw DBE;
1557:                    }
1558:
1559:                    if (checkForInsertion(getMode, cursorImpl, dup)) {
1560:                        endRead(dup, false);
1561:                        continue;
1562:                    } else {
1563:                        endRead(dup, status == OperationStatus.SUCCESS);
1564:                        assert LatchSupport.countLatchesHeld() == 0;
1565:                        break;
1566:                    }
1567:                }
1568:                return status;
1569:            }
1570:
1571:            /**
1572:             * Returns the current key and data.  There is no need to prevent phantoms.
1573:             */
1574:            OperationStatus getCurrentInternal(DatabaseEntry key,
1575:                    DatabaseEntry data, LockMode lockMode)
1576:                    throws DatabaseException {
1577:
1578:                /* Do not use a range lock. */
1579:                LockType lockType = getLockType(lockMode, false);
1580:
1581:                return cursorImpl.getCurrent(key, data, lockType);
1582:            }
1583:
1584:            /*
1585:             * Something may have been added to the original cursor (cursorImpl) while
1586:             * we were getting the next BIN.  cursorImpl would have been adjusted
1587:             * properly but we would have skipped a BIN in the process.
1588:             *
1589:             * Note that when we call LN.isDeleted(), we do not need to lock the LN.
1590:             * If we see a non-committed deleted entry, we'll just iterate around in
1591:             * the caller.  So a false positive is ok.
1592:             *
1593:             * @return true if an unaccounted for insertion happened.
1594:             */
1595:            private boolean checkForInsertion(GetMode getMode,
1596:                    CursorImpl origCursor, CursorImpl dupCursor)
1597:                    throws DatabaseException {
1598:
1599:                BIN origBIN = origCursor.getBIN();
1600:                BIN dupBIN = dupCursor.getBIN();
1601:                DBIN origDBIN = origCursor.getDupBIN();
1602:
1603:                /* If fetchTarget returns null below, a deleted LN was cleaned. */
1604:
1605:                boolean forward = true;
1606:                if (getMode == GetMode.PREV || getMode == GetMode.PREV_DUP
1607:                        || getMode == GetMode.PREV_NODUP) {
1608:                    forward = false;
1609:                }
1610:                boolean ret = false;
1611:                if (origBIN != dupBIN) {
1612:                    /* We jumped to the next BIN during getNext(). */
1613:                    origCursor.latchBINs();
1614:
1615:                    try {
1616:                        if (origDBIN == null) {
1617:                            if (forward) {
1618:                                if (origBIN.getNEntries() - 1 > origCursor
1619:                                        .getIndex()) {
1620:
1621:                                    /*
1622:                                     * We were adjusted to something other than the
1623:                                     * last entry so some insertion happened.
1624:                                     */
1625:                                    for (int i = origCursor.getIndex() + 1; i < origBIN
1626:                                            .getNEntries(); i++) {
1627:                                        if (!origBIN.isEntryKnownDeleted(i)) {
1628:                                            Node n = origBIN.fetchTarget(i);
1629:                                            if (n != null
1630:                                                    && !n.containsDuplicates()) {
1631:                                                LN ln = (LN) n;
1632:                                                /* See comment above about locking. */
1633:                                                if (!ln.isDeleted()) {
1634:                                                    ret = true;
1635:                                                    break;
1636:                                                }
1637:                                            }
1638:                                        } else {
1639:                                            /* Need to check the DupCountLN. */
1640:                                        }
1641:                                    }
1642:                                }
1643:                            } else {
1644:                                if (origCursor.getIndex() > 0) {
1645:
1646:                                    /*
1647:                                     * We were adjusted to something other than the
1648:                                     * first entry so some insertion happened.
1649:                                     */
1650:                                    for (int i = 0; i < origCursor.getIndex(); i++) {
1651:                                        if (!origBIN.isEntryKnownDeleted(i)) {
1652:                                            Node n = origBIN.fetchTarget(i);
1653:                                            if (n != null
1654:                                                    && !n.containsDuplicates()) {
1655:                                                LN ln = (LN) n;
1656:                                                /* See comment above about locking. */
1657:                                                if (!ln.isDeleted()) {
1658:                                                    ret = true;
1659:                                                    break;
1660:                                                }
1661:                                            } else {
1662:                                                /* Need to check the DupCountLN. */
1663:                                            }
1664:                                        }
1665:                                    }
1666:                                }
1667:                            }
1668:                        }
1669:                    } finally {
1670:                        origCursor.releaseBINs();
1671:                    }
1672:                    return ret;
1673:                }
1674:
1675:                if (origDBIN != dupCursor.getDupBIN()
1676:                        && origCursor.getIndex() == dupCursor.getIndex()
1677:                        && getMode != GetMode.NEXT_NODUP
1678:                        && getMode != GetMode.PREV_NODUP) {
1679:                    /* Same as above, only for the dupBIN. */
1680:                    origCursor.latchBINs();
1681:                    try {
1682:                        if (forward) {
1683:                            if (origDBIN.getNEntries() - 1 > origCursor
1684:                                    .getDupIndex()) {
1685:
1686:                                /*
1687:                                 * We were adjusted to something other than the last
1688:                                 * entry so some insertion happened.
1689:                                 */
1690:                                for (int i = origCursor.getDupIndex() + 1; i < origDBIN
1691:                                        .getNEntries(); i++) {
1692:                                    if (!origDBIN.isEntryKnownDeleted(i)) {
1693:                                        Node n = origDBIN.fetchTarget(i);
1694:                                        LN ln = (LN) n;
1695:                                        /* See comment above about locking. */
1696:                                        if (n != null && !ln.isDeleted()) {
1697:                                            ret = true;
1698:                                            break;
1699:                                        }
1700:                                    }
1701:                                }
1702:                            }
1703:                        } else {
1704:                            if (origCursor.getDupIndex() > 0) {
1705:
1706:                                /*
1707:                                 * We were adjusted to something other than the first
1708:                                 * entry so some insertion happened.
1709:                                 */
1710:                                for (int i = 0; i < origCursor.getDupIndex(); i++) {
1711:                                    if (!origDBIN.isEntryKnownDeleted(i)) {
1712:                                        Node n = origDBIN.fetchTarget(i);
1713:                                        LN ln = (LN) n;
1714:                                        /* See comment above about locking. */
1715:                                        if (n != null && !ln.isDeleted()) {
1716:                                            ret = true;
1717:                                            break;
1718:                                        }
1719:                                    }
1720:                                }
1721:                            }
1722:                        }
1723:                    } finally {
1724:                        origCursor.releaseBINs();
1725:                    }
1726:                    return ret;
1727:                }
1728:                return false;
1729:            }
1730:
1731:            /**
1732:             * If the cursor is initialized, dup it and return the dup; otherwise,
1733:             * return the original.  This avoids the overhead of duping when the
1734:             * original is uninitialized.  The cursor returned must be passed to
1735:             * endRead() to close the correct cursor.
1736:             */
1737:            private CursorImpl beginRead(boolean addCursor)
1738:                    throws DatabaseException {
1739:
1740:                CursorImpl dup;
1741:                if (cursorImpl.isNotInitialized()) {
1742:                    dup = cursorImpl;
1743:                } else {
1744:                    dup = cursorImpl.cloneCursor(addCursor);
1745:                }
1746:                return dup;
1747:            }
1748:
1749:            /**
1750:             * If the operation is successful, swaps cursors and closes the original
1751:             * cursor; otherwise, closes the duped cursor.  In the case where the
1752:             * original cursor was not duped by beginRead because it was uninitialized,
1753:             * just resets the original cursor if the operation did not succeed.
1754:             */
1755:            private void endRead(CursorImpl dup, boolean success)
1756:                    throws DatabaseException {
1757:
1758:                if (dup == cursorImpl) {
1759:                    if (!success) {
1760:                        cursorImpl.reset();
1761:                    }
1762:                } else {
1763:                    if (success) {
1764:                        cursorImpl.close();
1765:                        cursorImpl = dup;
1766:                    } else {
1767:                        dup.close();
1768:                    }
1769:                }
1770:            }
1771:
1772:            boolean advanceCursor(DatabaseEntry key, DatabaseEntry data) {
1773:                return cursorImpl.advanceCursor(key, data);
1774:            }
1775:
1776:            private LockType getLockType(LockMode lockMode, boolean rangeLock) {
1777:
1778:                if (isReadUncommittedMode(lockMode)) {
1779:                    return LockType.NONE;
1780:                } else if (lockMode == null || lockMode == LockMode.DEFAULT) {
1781:                    return rangeLock ? LockType.RANGE_READ : LockType.READ;
1782:                } else if (lockMode == LockMode.RMW) {
1783:                    return rangeLock ? LockType.RANGE_WRITE : LockType.WRITE;
1784:                } else if (lockMode == LockMode.READ_COMMITTED) {
1785:                    throw new IllegalArgumentException(lockMode.toString()
1786:                            + " not allowed with Cursor methods");
1787:                } else {
1788:                    assert false : lockMode;
1789:                    return LockType.NONE;
1790:                }
1791:            }
1792:
1793:            /**
1794:             * Returns whether the given lock mode will cause a read-uncommitted when
1795:             * used with this cursor, taking into account the default cursor
1796:             * configuration.
1797:             */
1798:            boolean isReadUncommittedMode(LockMode lockMode) {
1799:
1800:                return (lockMode == LockMode.READ_UNCOMMITTED || (readUncommittedDefault && (lockMode == null || lockMode == LockMode.DEFAULT)));
1801:            }
1802:
1803:            private boolean isSerializableIsolation(LockMode lockMode) {
1804:
1805:                return serializableIsolationDefault
1806:                        && !isReadUncommittedMode(lockMode);
1807:            }
1808:
1809:            protected void checkUpdatesAllowed(String operation)
1810:                    throws DatabaseException {
1811:
1812:                if (updateOperationsProhibited) {
1813:                    throw new DatabaseException(
1814:                            "A transaction was not supplied when opening this cursor: "
1815:                                    + operation);
1816:                }
1817:            }
1818:
1819:            /**
1820:             * Note that this flavor of checkArgs doesn't require that the dbt data is
1821:             * set.
1822:             */
1823:            private void checkArgsNoValRequired(DatabaseEntry key,
1824:                    DatabaseEntry data) {
1825:                DatabaseUtil.checkForNullDbt(key, "key", false);
1826:                DatabaseUtil.checkForNullDbt(data, "data", false);
1827:            }
1828:
1829:            /**
1830:             * Note that this flavor of checkArgs requires that the dbt data is set.
1831:             */
1832:            private void checkArgsValRequired(DatabaseEntry key,
1833:                    DatabaseEntry data) {
1834:                DatabaseUtil.checkForNullDbt(key, "key", true);
1835:                DatabaseUtil.checkForNullDbt(data, "data", true);
1836:            }
1837:
1838:            /**
1839:             * Check the environment and cursor state.
1840:             */
1841:            void checkState(boolean mustBeInitialized) throws DatabaseException {
1842:
1843:                checkEnv();
1844:                cursorImpl.checkCursorState(mustBeInitialized);
1845:            }
1846:
1847:            /**
1848:             * @throws RunRecoveryException if the underlying environment is invalid.
1849:             */
1850:            void checkEnv() throws RunRecoveryException {
1851:
1852:                cursorImpl.checkEnv();
1853:            }
1854:
1855:            /**
1856:             * Send trace messages to the java.util.logger. Don't rely on the logger
1857:             * alone to conditionalize whether we send this message, we don't even want
1858:             * to construct the message if the level is not enabled.
1859:             */
1860:            void trace(Level level, String methodName, DatabaseEntry key,
1861:                    DatabaseEntry data, LockMode lockMode) {
1862:                if (logger.isLoggable(level)) {
1863:                    StringBuffer sb = new StringBuffer();
1864:                    sb.append(methodName);
1865:                    traceCursorImpl(sb);
1866:                    if (key != null) {
1867:                        sb.append(" key=").append(key.dumpData());
1868:                    }
1869:                    if (data != null) {
1870:                        sb.append(" data=").append(data.dumpData());
1871:                    }
1872:                    if (lockMode != null) {
1873:                        sb.append(" lockMode=").append(lockMode);
1874:                    }
1875:                    logger.log(level, sb.toString());
1876:                }
1877:            }
1878:
1879:            /**
1880:             * Send trace messages to the java.util.logger. Don't rely on the logger
1881:             * alone to conditionalize whether we send this message, we don't even want
1882:             * to construct the message if the level is not enabled.
1883:             */
1884:            void trace(Level level, String methodName, LockMode lockMode) {
1885:                if (logger.isLoggable(level)) {
1886:                    StringBuffer sb = new StringBuffer();
1887:                    sb.append(methodName);
1888:                    traceCursorImpl(sb);
1889:                    if (lockMode != null) {
1890:                        sb.append(" lockMode=").append(lockMode);
1891:                    }
1892:                    logger.log(level, sb.toString());
1893:                }
1894:            }
1895:
1896:            private void traceCursorImpl(StringBuffer sb) {
1897:                sb.append(" locker=").append(cursorImpl.getLocker().getId());
1898:                if (cursorImpl.getBIN() != null) {
1899:                    sb.append(" bin=").append(cursorImpl.getBIN().getNodeId());
1900:                }
1901:                sb.append(" idx=").append(cursorImpl.getIndex());
1902:
1903:                if (cursorImpl.getDupBIN() != null) {
1904:                    sb.append(" Dbin=").append(
1905:                            cursorImpl.getDupBIN().getNodeId());
1906:                }
1907:                sb.append(" dupIdx=").append(cursorImpl.getDupIndex());
1908:            }
1909:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.