Source Code Cross Referenced for Database.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: Database.java,v 1.216.2.6 2008/01/07 15:14:07 cwl Exp $
0007:         */
0008:
0009:        package com.sleepycat.je;
0010:
0011:        import java.util.ArrayList;
0012:        import java.util.Comparator;
0013:        import java.util.Iterator;
0014:        import java.util.List;
0015:        import java.util.logging.Level;
0016:        import java.util.logging.Logger;
0017:
0018:        import com.sleepycat.je.dbi.DatabaseImpl;
0019:        import com.sleepycat.je.dbi.EnvironmentImpl;
0020:        import com.sleepycat.je.dbi.GetMode;
0021:        import com.sleepycat.je.dbi.PutMode;
0022:        import com.sleepycat.je.dbi.TruncateResult;
0023:        import com.sleepycat.je.dbi.CursorImpl.SearchMode;
0024:        import com.sleepycat.je.txn.Locker;
0025:        import com.sleepycat.je.txn.LockerFactory;
0026:        import com.sleepycat.je.utilint.DatabaseUtil;
0027:        import com.sleepycat.je.utilint.TinyHashSet;
0028:        import com.sleepycat.je.utilint.Tracer;
0029:
0030:        public class Database {
0031:
0032:            /*
0033:             * DbState embodies the Database handle state.
0034:             */
0035:            static class DbState {
0036:                private String stateName;
0037:
0038:                DbState(String stateName) {
0039:                    this .stateName = stateName;
0040:                }
0041:
0042:                public String toString() {
0043:                    return "DbState." + stateName;
0044:                }
0045:            }
0046:
0047:            static DbState OPEN = new DbState("OPEN");
0048:            static DbState CLOSED = new DbState("CLOSED");
0049:            static DbState INVALID = new DbState("INVALID");
0050:
0051:            /* The current state of the handle. */
0052:            private DbState state;
0053:
0054:            /* Handles onto the owning environment and the databaseImpl object. */
0055:            Environment envHandle; // used by subclasses
0056:            private DatabaseImpl databaseImpl;
0057:
0058:            DatabaseConfig configuration; // properties used at execution
0059:
0060:            /* True if this handle permits write operations; */
0061:            private boolean isWritable;
0062:
0063:            /* Transaction that owns the db lock held while the Database is open. */
0064:            Locker handleLocker;
0065:
0066:            /* Set of cursors open against this db handle. */
0067:            private TinyHashSet cursors = new TinyHashSet();
0068:
0069:            /*
0070:             * DatabaseTrigger list.  The list is null if empty, and is checked for
0071:             * null to avoiding read locking overhead when no triggers are present.
0072:             * Access to this list is protected by the shared trigger latch in
0073:             * EnvironmentImpl.
0074:             */
0075:            private List triggerList;
0076:
0077:            private Logger logger;
0078:
0079:            /**
0080:             * Creates a database but does not open or fully initialize it.
0081:             * Is protected for use in compat package.
0082:             */
0083:            protected Database(Environment env) {
0084:                this .envHandle = env;
0085:                handleLocker = null;
0086:                logger = envHandle.getEnvironmentImpl().getLogger();
0087:            }
0088:
0089:            /**
0090:             * Create a database, called by Environment.
0091:             */
0092:            void initNew(Environment env, Locker locker, String databaseName,
0093:                    DatabaseConfig dbConfig) throws DatabaseException {
0094:
0095:                dbConfig.validateForNewDb();
0096:
0097:                init(env, dbConfig);
0098:
0099:                /* Make the databaseImpl. */
0100:                EnvironmentImpl environmentImpl = DbInternal
0101:                        .envGetEnvironmentImpl(envHandle);
0102:                databaseImpl = environmentImpl.createDb(locker, databaseName,
0103:                        dbConfig, this );
0104:                databaseImpl.addReferringHandle(this );
0105:            }
0106:
0107:            /**
0108:             * Open a database, called by Environment.
0109:             */
0110:            void initExisting(Environment env, Locker locker,
0111:                    DatabaseImpl databaseImpl, DatabaseConfig dbConfig)
0112:                    throws DatabaseException {
0113:
0114:                /*
0115:                 * Make sure the configuration used for the open is compatible with the
0116:                 * existing databaseImpl.
0117:                 */
0118:                validateConfigAgainstExistingDb(dbConfig, databaseImpl);
0119:
0120:                init(env, dbConfig);
0121:                this .databaseImpl = databaseImpl;
0122:                databaseImpl.addReferringHandle(this );
0123:
0124:                /*
0125:                 * Copy the duplicates and transactional properties of the underlying
0126:                 * database, in case the useExistingConfig property is set.
0127:                 */
0128:                configuration.setSortedDuplicates(databaseImpl
0129:                        .getSortedDuplicates());
0130:                configuration.setTransactional(databaseImpl.isTransactional());
0131:            }
0132:
0133:            private void init(Environment env, DatabaseConfig config)
0134:                    throws DatabaseException {
0135:
0136:                handleLocker = null;
0137:
0138:                envHandle = env;
0139:                configuration = config.cloneConfig();
0140:                isWritable = !configuration.getReadOnly();
0141:                state = OPEN;
0142:            }
0143:
0144:            /**
0145:             * See if this new handle's configuration is compatible with the
0146:             * pre-existing database.
0147:             */
0148:            private void validateConfigAgainstExistingDb(DatabaseConfig config,
0149:                    DatabaseImpl databaseImpl) throws DatabaseException {
0150:
0151:                /*
0152:                 * The allowDuplicates property is persistent and immutable.  It does
0153:                 * not need to be specified if the useExistingConfig property is set.
0154:                 */
0155:                if (!config.getUseExistingConfig()) {
0156:                    if (databaseImpl.getSortedDuplicates() != config
0157:                            .getSortedDuplicates()) {
0158:                        throw new DatabaseException(
0159:                                "You can't open a Database with a duplicatesAllowed "
0160:                                        + "configuration of "
0161:                                        + config.getSortedDuplicates()
0162:                                        + " if the underlying database was created with a "
0163:                                        + "duplicatesAllowedSetting of "
0164:                                        + databaseImpl.getSortedDuplicates()
0165:                                        + ".");
0166:                    }
0167:                }
0168:
0169:                /*
0170:                 * The transactional property is kept constant while any handles are
0171:                 * open, and set when the first handle is opened.  It does not need to
0172:                 * be specified if the useExistingConfig property is set.
0173:                 */
0174:                if (databaseImpl.hasOpenHandles()) {
0175:                    if (!config.getUseExistingConfig()) {
0176:                        if (config.getTransactional() != databaseImpl
0177:                                .isTransactional()) {
0178:                            throw new DatabaseException(
0179:                                    "You can't open a Database with a transactional "
0180:                                            + "configuration of "
0181:                                            + config.getTransactional()
0182:                                            + " if the underlying database was created with a "
0183:                                            + "transactional configuration of "
0184:                                            + databaseImpl.isTransactional()
0185:                                            + ".");
0186:                        }
0187:                    }
0188:                } else {
0189:                    databaseImpl.setTransactional(config.getTransactional());
0190:                }
0191:
0192:                /*
0193:                 * The deferredWrite property is kept constant while any handles are
0194:                 * open, and set when the first handle is opened.  It does not need to
0195:                 * be specified if the useExistingConfig property is set.
0196:                 */
0197:                if (databaseImpl.hasOpenHandles()) {
0198:                    if (!config.getUseExistingConfig()) {
0199:                        if (config.getDeferredWrite() != databaseImpl
0200:                                .isDeferredWrite()) {
0201:                            throw new DatabaseException(
0202:                                    "You can't open a Database with a deferredWrite "
0203:                                            + "configuration of "
0204:                                            + config.getDeferredWrite()
0205:                                            + " if the underlying database was created with a "
0206:                                            + "deferredWrite configuration of "
0207:                                            + databaseImpl.isDeferredWrite()
0208:                                            + ".");
0209:                        }
0210:                    }
0211:                } else {
0212:                    databaseImpl.setDeferredWrite(config.getDeferredWrite());
0213:                }
0214:
0215:                /*
0216:                 * Only re-set the comparators if the override is allowed.
0217:                 */
0218:                boolean comparatorModified = false;
0219:                if (config.getOverrideBtreeComparator()) {
0220:                    comparatorModified |= databaseImpl.setBtreeComparator(
0221:                            config.getBtreeComparator(), config
0222:                                    .getBtreeComparatorByClassName());
0223:                }
0224:
0225:                if (config.getOverrideDuplicateComparator()) {
0226:                    comparatorModified |= databaseImpl.setDuplicateComparator(
0227:                            config.getDuplicateComparator(), config
0228:                                    .getDuplicateComparatorByClassName());
0229:                }
0230:
0231:                /* [#15743] */
0232:                if (comparatorModified) {
0233:                    EnvironmentImpl envImpl = envHandle.getEnvironmentImpl();
0234:
0235:                    /* Dirty the root. */
0236:                    envImpl.getDbMapTree().modifyDbRoot(databaseImpl);
0237:                }
0238:            }
0239:
0240:            public synchronized void close() throws DatabaseException {
0241:
0242:                try {
0243:                    closeInternal();
0244:                } catch (Error E) {
0245:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0246:                    throw E;
0247:                }
0248:            }
0249:
0250:            private void closeInternal() throws DatabaseException {
0251:
0252:                StringBuffer errors = null;
0253:
0254:                checkEnv();
0255:                checkProhibitedDbState(CLOSED, "Can't close Database:");
0256:
0257:                trace(Level.FINEST, "Database.close: ", null, null);
0258:
0259:                /* Disassociate triggers before closing. */
0260:                removeAllTriggers();
0261:
0262:                envHandle.removeReferringHandle(this );
0263:                if (cursors.size() > 0) {
0264:                    errors = new StringBuffer(
0265:                            "There are open cursors against the database.\n");
0266:                    errors.append("They will be closed.\n");
0267:
0268:                    /*
0269:                     * Copy the cursors set before iterating since the dbc.close()
0270:                     * mutates the set.
0271:                     */
0272:                    Iterator iter = cursors.copy().iterator();
0273:                    while (iter.hasNext()) {
0274:                        Cursor dbc = (Cursor) iter.next();
0275:
0276:                        try {
0277:                            dbc.close();
0278:                        } catch (DatabaseException DBE) {
0279:                            errors.append("Exception while closing cursors:\n");
0280:                            errors.append(DBE.toString());
0281:                        }
0282:                    }
0283:                }
0284:
0285:                if (databaseImpl != null) {
0286:                    databaseImpl.removeReferringHandle(this );
0287:                    envHandle.getEnvironmentImpl().releaseDb(databaseImpl);
0288:                    databaseImpl = null;
0289:
0290:                    /*
0291:                     * Tell our protecting txn that we're closing. If this type
0292:                     * of transaction doesn't live beyond the life of the handle,
0293:                     * it will release the db handle lock.
0294:                     */
0295:                    handleLocker.setHandleLockOwner(true, this , true);
0296:                    handleLocker.operationEnd(true);
0297:                    state = CLOSED;
0298:                }
0299:
0300:                if (errors != null) {
0301:                    throw new DatabaseException(errors.toString());
0302:                }
0303:            }
0304:
0305:            /**
0306:             * Javadoc for this public method is generated via
0307:             * the doc templates in the doc_src directory.
0308:             */
0309:            public void sync() throws DatabaseException {
0310:
0311:                checkEnv();
0312:                checkRequiredDbState(OPEN, "Can't call Database.sync:");
0313:                checkWritable("sync");
0314:                trace(Level.FINEST, "Database.sync", null, null, null, null);
0315:
0316:                databaseImpl.sync(true);
0317:            }
0318:
0319:            /**
0320:             * Javadoc for this public method is generated via
0321:             * the doc templates in the doc_src directory.
0322:             */
0323:            public Sequence openSequence(Transaction txn, DatabaseEntry key,
0324:                    SequenceConfig config) throws DatabaseException {
0325:
0326:                try {
0327:                    checkEnv();
0328:                    DatabaseUtil.checkForNullDbt(key, "key", true);
0329:                    checkRequiredDbState(OPEN,
0330:                            "Can't call Database.openSequence:");
0331:                    checkWritable("openSequence");
0332:                    trace(Level.FINEST, "Database.openSequence", txn, key,
0333:                            null, null);
0334:
0335:                    return new Sequence(this , txn, key, config);
0336:                } catch (Error E) {
0337:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0338:                    throw E;
0339:                }
0340:            }
0341:
0342:            /**
0343:             * Javadoc for this public method is generated via
0344:             * the doc templates in the doc_src directory.
0345:             */
0346:            public void removeSequence(Transaction txn, DatabaseEntry key)
0347:                    throws DatabaseException {
0348:
0349:                try {
0350:                    delete(txn, key);
0351:                } catch (Error E) {
0352:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0353:                    throw E;
0354:                }
0355:            }
0356:
0357:            public synchronized Cursor openCursor(Transaction txn,
0358:                    CursorConfig cursorConfig) throws DatabaseException {
0359:
0360:                try {
0361:                    checkEnv();
0362:                    checkRequiredDbState(OPEN, "Can't open a cursor");
0363:                    CursorConfig useConfig = (cursorConfig == null) ? CursorConfig.DEFAULT
0364:                            : cursorConfig;
0365:
0366:                    if (useConfig.getReadUncommitted()
0367:                            && useConfig.getReadCommitted()) {
0368:                        throw new IllegalArgumentException(
0369:                                "Only one may be specified: "
0370:                                        + "ReadCommitted or ReadUncommitted");
0371:                    }
0372:
0373:                    trace(Level.FINEST, "Database.openCursor", txn,
0374:                            cursorConfig);
0375:                    Cursor ret = newDbcInstance(txn, useConfig);
0376:
0377:                    return ret;
0378:                } catch (Error E) {
0379:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0380:                    throw E;
0381:                }
0382:            }
0383:
0384:            /**
0385:             * Is overridden by SecondaryDatabase.
0386:             */
0387:            Cursor newDbcInstance(Transaction txn, CursorConfig cursorConfig)
0388:                    throws DatabaseException {
0389:
0390:                return new Cursor(this , txn, cursorConfig);
0391:            }
0392:
0393:            public OperationStatus delete(Transaction txn, DatabaseEntry key)
0394:                    throws DatabaseException {
0395:
0396:                try {
0397:                    checkEnv();
0398:                    DatabaseUtil.checkForNullDbt(key, "key", true);
0399:                    checkRequiredDbState(OPEN, "Can't call Database.delete:");
0400:                    checkWritable("delete");
0401:                    trace(Level.FINEST, "Database.delete", txn, key, null, null);
0402:
0403:                    OperationStatus commitStatus = OperationStatus.NOTFOUND;
0404:                    Locker locker = null;
0405:                    try {
0406:                        locker = LockerFactory.getWritableLocker(envHandle,
0407:                                txn, isTransactional());
0408:                        commitStatus = deleteInternal(locker, key, null);
0409:                        return commitStatus;
0410:                    } finally {
0411:                        if (locker != null) {
0412:                            locker.operationEnd(commitStatus);
0413:                        }
0414:                    }
0415:                } catch (Error E) {
0416:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0417:                    throw E;
0418:                }
0419:            }
0420:
0421:            /*
0422:             * This is commented out until we agree on whether this should even be in
0423:             * the API.  See [14264].
0424:            private OperationStatus delete(Transaction txn,
0425:            			   DatabaseEntry key,
0426:            			   DatabaseEntry data)
0427:                throws DatabaseException {
0428:
0429:            try {
0430:                checkEnv();
0431:                DatabaseUtil.checkForNullDbt(key, "key", true);
0432:                DatabaseUtil.checkForNullDbt(data, "data", true);
0433:                checkRequiredDbState(OPEN, "Can't call Database.delete:");
0434:                checkWritable("delete");
0435:                trace(Level.FINEST, "Database.delete", txn, key, data, null);
0436:
0437:                OperationStatus commitStatus = OperationStatus.NOTFOUND;
0438:                Locker locker = null;
0439:                try {
0440:            	locker = LockerFactory.getWritableLocker
0441:            	    (envHandle, txn, isTransactional());
0442:            	commitStatus = deleteInternal(locker, key, data);
0443:            	return commitStatus;
0444:                } finally {
0445:            	if (locker != null) {
0446:            	    locker.operationEnd(commitStatus);
0447:            	}
0448:                }
0449:            } catch (Error E) {
0450:                DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0451:                throw E;
0452:            }
0453:            }
0454:             */
0455:
0456:            /**
0457:             * Internal version of delete() that does no parameter checking.  Notify
0458:             * triggers.  Deletes all duplicates.
0459:             */
0460:            OperationStatus deleteInternal(Locker locker, DatabaseEntry key,
0461:                    DatabaseEntry data) throws DatabaseException {
0462:
0463:                Cursor cursor = null;
0464:                try {
0465:                    cursor = new Cursor(this , locker, null);
0466:                    cursor.setNonCloning(true);
0467:                    OperationStatus commitStatus = OperationStatus.NOTFOUND;
0468:
0469:                    /* Position a cursor at the specified data record. */
0470:                    DatabaseEntry oldData;
0471:                    OperationStatus searchStatus;
0472:                    if (data == null) {
0473:                        oldData = new DatabaseEntry();
0474:                        searchStatus = cursor.search(key, oldData,
0475:                                LockMode.RMW, SearchMode.SET);
0476:                    } else {
0477:                        oldData = data;
0478:                        searchStatus = cursor.search(key, oldData,
0479:                                LockMode.RMW, SearchMode.BOTH);
0480:                    }
0481:
0482:                    /* Delete all records with that key. */
0483:                    if (searchStatus == OperationStatus.SUCCESS) {
0484:                        do {
0485:
0486:                            /*
0487:                             * Notify triggers before the actual deletion so that a
0488:                             * primary record never exists while secondary keys refer
0489:                             * to it.  This is relied on by secondary read-uncommitted.
0490:                             */
0491:                            if (hasTriggers()) {
0492:                                notifyTriggers(locker, key, oldData, null);
0493:                            }
0494:                            /* The actual deletion. */
0495:                            commitStatus = cursor.deleteNoNotify();
0496:                            if (commitStatus != OperationStatus.SUCCESS) {
0497:                                return commitStatus;
0498:                            }
0499:
0500:                            if (data != null) {
0501:                                /* delete(key, data) called so only delete one item. */
0502:                                break;
0503:                            }
0504:
0505:                            /* Get another duplicate. */
0506:                            if (databaseImpl.getSortedDuplicates()) {
0507:                                searchStatus = cursor
0508:                                        .retrieveNext(key, oldData,
0509:                                                LockMode.RMW, GetMode.NEXT_DUP);
0510:                            } else {
0511:                                searchStatus = OperationStatus.NOTFOUND;
0512:                            }
0513:                        } while (searchStatus == OperationStatus.SUCCESS);
0514:                        commitStatus = OperationStatus.SUCCESS;
0515:                    }
0516:                    return commitStatus;
0517:                } finally {
0518:                    if (cursor != null) {
0519:                        cursor.close();
0520:                    }
0521:                }
0522:            }
0523:
0524:            public OperationStatus get(Transaction txn, DatabaseEntry key,
0525:                    DatabaseEntry data, LockMode lockMode)
0526:                    throws DatabaseException {
0527:
0528:                try {
0529:                    checkEnv();
0530:                    DatabaseUtil.checkForNullDbt(key, "key", true);
0531:                    DatabaseUtil.checkForNullDbt(data, "data", false);
0532:                    checkRequiredDbState(OPEN, "Can't call Database.get:");
0533:                    trace(Level.FINEST, "Database.get", txn, key, null,
0534:                            lockMode);
0535:
0536:                    CursorConfig cursorConfig = CursorConfig.DEFAULT;
0537:                    if (lockMode == LockMode.READ_COMMITTED) {
0538:                        cursorConfig = CursorConfig.READ_COMMITTED;
0539:                        lockMode = null;
0540:                    }
0541:
0542:                    Cursor cursor = null;
0543:                    try {
0544:                        cursor = new Cursor(this , txn, cursorConfig);
0545:                        cursor.setNonCloning(true);
0546:                        return cursor.search(key, data, lockMode,
0547:                                SearchMode.SET);
0548:                    } finally {
0549:                        if (cursor != null) {
0550:                            cursor.close();
0551:                        }
0552:                    }
0553:                } catch (Error E) {
0554:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0555:                    throw E;
0556:                }
0557:            }
0558:
0559:            public OperationStatus getSearchBoth(Transaction txn,
0560:                    DatabaseEntry key, DatabaseEntry data, LockMode lockMode)
0561:                    throws DatabaseException {
0562:
0563:                try {
0564:                    checkEnv();
0565:                    DatabaseUtil.checkForNullDbt(key, "key", true);
0566:                    DatabaseUtil.checkForNullDbt(data, "data", true);
0567:                    checkRequiredDbState(OPEN,
0568:                            "Can't call Database.getSearchBoth:");
0569:                    trace(Level.FINEST, "Database.getSearchBoth", txn, key,
0570:                            data, lockMode);
0571:
0572:                    CursorConfig cursorConfig = CursorConfig.DEFAULT;
0573:                    if (lockMode == LockMode.READ_COMMITTED) {
0574:                        cursorConfig = CursorConfig.READ_COMMITTED;
0575:                        lockMode = null;
0576:                    }
0577:
0578:                    Cursor cursor = null;
0579:                    try {
0580:                        cursor = new Cursor(this , txn, cursorConfig);
0581:                        cursor.setNonCloning(true);
0582:                        return cursor.search(key, data, lockMode,
0583:                                SearchMode.BOTH);
0584:                    } finally {
0585:                        if (cursor != null) {
0586:                            cursor.close();
0587:                        }
0588:                    }
0589:                } catch (Error E) {
0590:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0591:                    throw E;
0592:                }
0593:            }
0594:
0595:            public OperationStatus put(Transaction txn, DatabaseEntry key,
0596:                    DatabaseEntry data) throws DatabaseException {
0597:
0598:                checkEnv();
0599:                DatabaseUtil.checkForNullDbt(key, "key", true);
0600:                DatabaseUtil.checkForNullDbt(data, "data", true);
0601:                DatabaseUtil.checkForPartialKey(key);
0602:                checkRequiredDbState(OPEN, "Can't call Database.put");
0603:                checkWritable("put");
0604:                trace(Level.FINEST, "Database.put", txn, key, data, null);
0605:
0606:                return putInternal(txn, key, data, PutMode.OVERWRITE);
0607:            }
0608:
0609:            public OperationStatus putNoOverwrite(Transaction txn,
0610:                    DatabaseEntry key, DatabaseEntry data)
0611:                    throws DatabaseException {
0612:
0613:                checkEnv();
0614:                DatabaseUtil.checkForNullDbt(key, "key", true);
0615:                DatabaseUtil.checkForNullDbt(data, "data", true);
0616:                DatabaseUtil.checkForPartialKey(key);
0617:                checkRequiredDbState(OPEN, "Can't call Database.putNoOverWrite");
0618:                checkWritable("putNoOverwrite");
0619:                trace(Level.FINEST, "Database.putNoOverwrite", txn, key, data,
0620:                        null);
0621:
0622:                return putInternal(txn, key, data, PutMode.NOOVERWRITE);
0623:            }
0624:
0625:            public OperationStatus putNoDupData(Transaction txn,
0626:                    DatabaseEntry key, DatabaseEntry data)
0627:                    throws DatabaseException {
0628:
0629:                checkEnv();
0630:                DatabaseUtil.checkForNullDbt(key, "key", true);
0631:                DatabaseUtil.checkForNullDbt(data, "data", true);
0632:                DatabaseUtil.checkForPartialKey(key);
0633:                checkRequiredDbState(OPEN, "Can't call Database.putNoDupData");
0634:                checkWritable("putNoDupData");
0635:                trace(Level.FINEST, "Database.putNoDupData", txn, key, data,
0636:                        null);
0637:
0638:                return putInternal(txn, key, data, PutMode.NODUP);
0639:            }
0640:
0641:            /**
0642:             * Internal version of put() that does no parameter checking.
0643:             */
0644:            OperationStatus putInternal(Transaction txn, DatabaseEntry key,
0645:                    DatabaseEntry data, PutMode putMode)
0646:                    throws DatabaseException {
0647:
0648:                try {
0649:                    Locker locker = null;
0650:                    Cursor cursor = null;
0651:                    OperationStatus commitStatus = OperationStatus.KEYEXIST;
0652:                    try {
0653:                        locker = LockerFactory.getWritableLocker(envHandle,
0654:                                txn, isTransactional());
0655:
0656:                        cursor = new Cursor(this , locker, null);
0657:                        cursor.setNonCloning(true);
0658:                        commitStatus = cursor.putInternal(key, data, putMode);
0659:                        return commitStatus;
0660:                    } finally {
0661:                        if (cursor != null) {
0662:                            cursor.close();
0663:                        }
0664:                        if (locker != null) {
0665:                            locker.operationEnd(commitStatus);
0666:                        }
0667:                    }
0668:                } catch (Error E) {
0669:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0670:                    throw E;
0671:                }
0672:            }
0673:
0674:            /**
0675:             */
0676:            public JoinCursor join(Cursor[] cursors, JoinConfig config)
0677:                    throws DatabaseException {
0678:
0679:                try {
0680:                    checkEnv();
0681:                    checkRequiredDbState(OPEN, "Can't call Database.join");
0682:                    DatabaseUtil.checkForNullParam(cursors, "cursors");
0683:                    if (cursors.length == 0) {
0684:                        throw new IllegalArgumentException(
0685:                                "At least one cursor is required.");
0686:                    }
0687:
0688:                    /*
0689:                     * Check that all cursors use the same locker, if any cursor is
0690:                     * transactional.  And if non-transactional, that all databases are
0691:                     * in the same environment.
0692:                     */
0693:                    Locker locker = cursors[0].getCursorImpl().getLocker();
0694:                    if (!locker.isTransactional()) {
0695:                        EnvironmentImpl env = envHandle.getEnvironmentImpl();
0696:                        for (int i = 1; i < cursors.length; i += 1) {
0697:                            Locker locker2 = cursors[i].getCursorImpl()
0698:                                    .getLocker();
0699:                            if (locker2.isTransactional()) {
0700:                                throw new IllegalArgumentException(
0701:                                        "All cursors must use the same transaction.");
0702:                            }
0703:                            EnvironmentImpl env2 = cursors[i].getDatabaseImpl()
0704:                                    .getDbEnvironment();
0705:                            if (env != env2) {
0706:                                throw new IllegalArgumentException(
0707:                                        "All cursors must use the same environment.");
0708:                            }
0709:                        }
0710:                        locker = null; /* Don't reuse a non-transactional locker. */
0711:                    } else {
0712:                        for (int i = 1; i < cursors.length; i += 1) {
0713:                            Locker locker2 = cursors[i].getCursorImpl()
0714:                                    .getLocker();
0715:                            if (locker.getTxnLocker() != locker2.getTxnLocker()) {
0716:                                throw new IllegalArgumentException(
0717:                                        "All cursors must use the same transaction.");
0718:                            }
0719:                        }
0720:                    }
0721:
0722:                    /* Create the join cursor. */
0723:                    return new JoinCursor(locker, this , cursors, config);
0724:                } catch (Error E) {
0725:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0726:                    throw E;
0727:                }
0728:            }
0729:
0730:            /**
0731:             * @deprecated It has not been possible to implement this method with
0732:             * correct transactional semantics without incurring a performance penalty
0733:             * on all Database operations. Truncate functionality has been moved to
0734:             * Environment.truncateDatabase(), which requires that all Database handles
0735:             * on the database are closed before the truncate operation can execute.
0736:             */
0737:            public int truncate(Transaction txn, boolean countRecords)
0738:                    throws DatabaseException {
0739:
0740:                try {
0741:                    checkEnv();
0742:                    checkRequiredDbState(OPEN, "Can't call Database.truncate");
0743:                    checkWritable("truncate");
0744:                    Tracer.trace(Level.FINEST, envHandle.getEnvironmentImpl(),
0745:                            "Database.truncate: txnId="
0746:                                    + ((txn == null) ? "null" : Long
0747:                                            .toString(txn.getId())));
0748:
0749:                    Locker locker = null;
0750:                    boolean triggerLock = false;
0751:                    boolean operationOk = false;
0752:
0753:                    try {
0754:                        locker = LockerFactory.getWritableLocker(envHandle,
0755:                                txn, isTransactional(), true /*retainLocks*/,
0756:                                null);
0757:
0758:                        /*
0759:                         * Pass true to always get a read lock on the triggers, so we
0760:                         * are sure that no secondaries are added during truncation.
0761:                         */
0762:                        acquireTriggerListReadLock();
0763:                        triggerLock = true;
0764:
0765:                        /* Truncate primary. */
0766:                        int count = truncateInternal(locker, countRecords);
0767:
0768:                        /* Truncate secondaries. */
0769:                        for (int i = 0; i < triggerList.size(); i += 1) {
0770:                            Object obj = triggerList.get(i);
0771:                            if (obj instanceof  SecondaryTrigger) {
0772:                                SecondaryDatabase secDb = ((SecondaryTrigger) obj)
0773:                                        .getDb();
0774:                                secDb.truncateInternal(locker, false);
0775:                            }
0776:                        }
0777:
0778:                        operationOk = true;
0779:                        return count;
0780:                    } finally {
0781:                        if (locker != null) {
0782:                            locker.operationEnd(operationOk);
0783:                        }
0784:                        if (triggerLock) {
0785:                            releaseTriggerListReadLock();
0786:                        }
0787:                    }
0788:                } catch (Error E) {
0789:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0790:                    throw E;
0791:                }
0792:            }
0793:
0794:            /**
0795:             * Internal unchecked truncate that optionally counts records.
0796:             * @deprecated
0797:             */
0798:            int truncateInternal(Locker locker, boolean countRecords)
0799:                    throws DatabaseException {
0800:
0801:                if (databaseImpl == null) {
0802:                    throw new DatabaseException(
0803:                            "couldn't find database - truncate");
0804:                }
0805:                databaseImpl.checkIsDeleted("truncate");
0806:
0807:                /*
0808:                 * Truncate must obtain a write lock. In order to do so, it assumes
0809:                 * ownership for the handle lock and transfers it from this Database
0810:                 * object to the txn.
0811:                 */
0812:                if (handleLocker.isHandleLockTransferrable()) {
0813:                    handleLocker.transferHandleLock(this , locker, false);
0814:                }
0815:
0816:                boolean operationOk = false;
0817:                try {
0818:
0819:                    /*
0820:                     * truncate clones the existing database and returns a new one to
0821:                     * replace it with.  The old databaseImpl object is marked
0822:                     * 'deleted'.
0823:                     */
0824:                    TruncateResult result = envHandle.getEnvironmentImpl()
0825:                            .truncate(locker, databaseImpl);
0826:                    databaseImpl = result.getDatabase();
0827:
0828:                    operationOk = true;
0829:                    return countRecords ? result.getRecordCount() : -1;
0830:                } finally {
0831:
0832:                    /*
0833:                     * The txn will know if it's living past the end of this operation,
0834:                     * and if it needs to transfer the handle lock.  operationEnd()
0835:                     * will be called one level up by the public truncate() method.
0836:                     */
0837:                    locker.setHandleLockOwner(operationOk, this , false);
0838:                }
0839:            }
0840:
0841:            /*
0842:             * @deprecated As of JE 2.0.55, replaced by
0843:             * {@link Database#preload(PreloadConfig)}.
0844:             */
0845:            public void preload(long maxBytes) throws DatabaseException {
0846:
0847:                checkEnv();
0848:                checkRequiredDbState(OPEN, "Can't call Database.preload");
0849:                databaseImpl.checkIsDeleted("preload");
0850:
0851:                PreloadConfig config = new PreloadConfig();
0852:                config.setMaxBytes(maxBytes);
0853:                databaseImpl.preload(config);
0854:            }
0855:
0856:            /*
0857:             * @deprecated As of JE 2.1.1, replaced by
0858:             * {@link Database#preload(PreloadConfig)}.
0859:             */
0860:            public void preload(long maxBytes, long maxMillisecs)
0861:                    throws DatabaseException {
0862:
0863:                checkEnv();
0864:                checkRequiredDbState(OPEN, "Can't call Database.preload");
0865:                databaseImpl.checkIsDeleted("preload");
0866:
0867:                PreloadConfig config = new PreloadConfig();
0868:                config.setMaxBytes(maxBytes);
0869:                config.setMaxMillisecs(maxMillisecs);
0870:                databaseImpl.preload(config);
0871:            }
0872:
0873:            public PreloadStats preload(PreloadConfig config)
0874:                    throws DatabaseException {
0875:
0876:                checkEnv();
0877:                checkRequiredDbState(OPEN, "Can't call Database.preload");
0878:                databaseImpl.checkIsDeleted("preload");
0879:
0880:                return databaseImpl.preload(config);
0881:            }
0882:
0883:            public long count() throws DatabaseException {
0884:
0885:                checkEnv();
0886:                checkRequiredDbState(OPEN, "Can't call Database.count");
0887:                databaseImpl.checkIsDeleted("count");
0888:
0889:                return databaseImpl.count();
0890:            }
0891:
0892:            public DatabaseStats getStats(StatsConfig config)
0893:                    throws DatabaseException {
0894:
0895:                checkEnv();
0896:                checkRequiredDbState(OPEN, "Can't call Database.stat");
0897:                StatsConfig useConfig = (config == null) ? StatsConfig.DEFAULT
0898:                        : config;
0899:
0900:                if (databaseImpl != null) {
0901:                    databaseImpl.checkIsDeleted("stat");
0902:                    return databaseImpl.stat(useConfig);
0903:                }
0904:                return null;
0905:            }
0906:
0907:            public DatabaseStats verify(VerifyConfig config)
0908:                    throws DatabaseException {
0909:
0910:                try {
0911:                    checkEnv();
0912:                    checkRequiredDbState(OPEN, "Can't call Database.verify");
0913:                    databaseImpl.checkIsDeleted("verify");
0914:                    VerifyConfig useConfig = (config == null) ? VerifyConfig.DEFAULT
0915:                            : config;
0916:
0917:                    DatabaseStats stats = databaseImpl.getEmptyStats();
0918:                    databaseImpl.verify(useConfig, stats);
0919:                    return stats;
0920:                } catch (Error E) {
0921:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0922:                    throw E;
0923:                }
0924:            }
0925:
0926:            public String getDatabaseName() throws DatabaseException {
0927:
0928:                try {
0929:                    checkEnv();
0930:                    if (databaseImpl != null) {
0931:                        return databaseImpl.getName();
0932:                    } else {
0933:                        return null;
0934:                    }
0935:                } catch (Error E) {
0936:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0937:                    throw E;
0938:                }
0939:            }
0940:
0941:            /*
0942:             * Non-transactional database name, safe to access when creating error
0943:             * messages.
0944:             */
0945:            String getDebugName() {
0946:                if (databaseImpl != null) {
0947:                    return databaseImpl.getDebugName();
0948:                } else {
0949:                    return null;
0950:                }
0951:            }
0952:
0953:            public DatabaseConfig getConfig() throws DatabaseException {
0954:
0955:                try {
0956:                    DatabaseConfig showConfig = configuration.cloneConfig();
0957:
0958:                    /*
0959:                     * Set the comparators from the database impl, they might have
0960:                     * changed from another handle.
0961:                     */
0962:                    Comparator btComp = null;
0963:                    Comparator dupComp = null;
0964:                    boolean btCompByClass = false;
0965:                    boolean dupCompByClass = false;
0966:                    if (databaseImpl != null) {
0967:                        btComp = databaseImpl.getBtreeComparator();
0968:                        dupComp = databaseImpl.getDuplicateComparator();
0969:                        btCompByClass = databaseImpl
0970:                                .getBtreeComparatorByClass();
0971:                        dupCompByClass = databaseImpl
0972:                                .getDuplicateComparatorByClass();
0973:                    }
0974:                    showConfig
0975:                            .setBtreeComparatorInternal(btComp, btCompByClass);
0976:                    showConfig.setDuplicateComparatorInternal(dupComp,
0977:                            dupCompByClass);
0978:                    return showConfig;
0979:                } catch (Error E) {
0980:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
0981:                    throw E;
0982:                }
0983:            }
0984:
0985:            /**
0986:             * Equivalent to getConfig().getTransactional() but cheaper.
0987:             */
0988:            boolean isTransactional() throws DatabaseException {
0989:
0990:                return databaseImpl.isTransactional();
0991:            }
0992:
0993:            public Environment getEnvironment() throws DatabaseException {
0994:
0995:                return envHandle;
0996:            }
0997:
0998:            public List getSecondaryDatabases() throws DatabaseException {
0999:
1000:                try {
1001:                    List list = new ArrayList();
1002:                    if (hasTriggers()) {
1003:                        acquireTriggerListReadLock();
1004:                        try {
1005:                            for (int i = 0; i < triggerList.size(); i += 1) {
1006:                                Object obj = triggerList.get(i);
1007:                                if (obj instanceof  SecondaryTrigger) {
1008:                                    list.add(((SecondaryTrigger) obj).getDb());
1009:                                }
1010:                            }
1011:                        } finally {
1012:                            releaseTriggerListReadLock();
1013:                        }
1014:                    }
1015:                    return list;
1016:                } catch (Error E) {
1017:                    DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E);
1018:                    throw E;
1019:                }
1020:            }
1021:
1022:            /*
1023:             * Helpers, not part of the public API
1024:             */
1025:
1026:            /**
1027:             * @return true if the Database was opened read/write.
1028:             */
1029:            boolean isWritable() {
1030:                return isWritable;
1031:            }
1032:
1033:            /**
1034:             * Return the databaseImpl object instance.
1035:             */
1036:            DatabaseImpl getDatabaseImpl() {
1037:                return databaseImpl;
1038:            }
1039:
1040:            /**
1041:             * The handleLocker is the one that holds the db handle lock.
1042:             */
1043:            void setHandleLocker(Locker locker) {
1044:                handleLocker = locker;
1045:            }
1046:
1047:            synchronized void removeCursor(Cursor dbc) {
1048:                cursors.remove(dbc);
1049:            }
1050:
1051:            synchronized void addCursor(Cursor dbc) {
1052:                cursors.add(dbc);
1053:            }
1054:
1055:            /**
1056:             * @throws DatabaseException if the Database state is not this value.
1057:             */
1058:            void checkRequiredDbState(DbState required, String msg)
1059:                    throws DatabaseException {
1060:
1061:                if (state != required) {
1062:                    throw new DatabaseException(msg
1063:                            + " Database state can't be " + state + " must be "
1064:                            + required);
1065:                }
1066:            }
1067:
1068:            /**
1069:             * @throws DatabaseException if the Database state is this value.
1070:             */
1071:            void checkProhibitedDbState(DbState prohibited, String msg)
1072:                    throws DatabaseException {
1073:
1074:                if (state == prohibited) {
1075:                    throw new DatabaseException(msg
1076:                            + " Database state must not be " + prohibited);
1077:                }
1078:            }
1079:
1080:            /**
1081:             * @throws RunRecoveryException if the underlying environment is
1082:             * invalid
1083:             */
1084:            void checkEnv() throws RunRecoveryException {
1085:
1086:                EnvironmentImpl env = envHandle.getEnvironmentImpl();
1087:                if (env != null) {
1088:                    env.checkIfInvalid();
1089:                }
1090:            }
1091:
1092:            /**
1093:             * Invalidate the handle, called by txn.abort by way of DbInternal.
1094:             */
1095:            synchronized void invalidate() {
1096:                state = INVALID;
1097:                envHandle.removeReferringHandle(this );
1098:                if (databaseImpl != null) {
1099:                    databaseImpl.removeReferringHandle(this );
1100:                    envHandle.getEnvironmentImpl().releaseDb(databaseImpl);
1101:
1102:                    /*
1103:                     * Database.close may be called after an abort.  By setting the
1104:                     * databaseImpl field to null we ensure that close won't call
1105:                     * releaseDb or endOperation. [#13415]
1106:                     */
1107:                    databaseImpl = null;
1108:                }
1109:            }
1110:
1111:            /**
1112:             * Check that write operations aren't used on a readonly Database.
1113:             */
1114:            private void checkWritable(String operation)
1115:                    throws DatabaseException {
1116:
1117:                if (!isWritable) {
1118:                    throw new DatabaseException("Database is Read Only: "
1119:                            + operation);
1120:                }
1121:            }
1122:
1123:            /**
1124:             * Send trace messages to the java.util.logger. Don't rely on the logger
1125:             * alone to conditionalize whether we send this message, we don't even want
1126:             * to construct the message if the level is not enabled.
1127:             */
1128:            void trace(Level level, String methodName, Transaction txn,
1129:                    DatabaseEntry key, DatabaseEntry data, LockMode lockMode)
1130:                    throws DatabaseException {
1131:
1132:                if (logger.isLoggable(level)) {
1133:                    StringBuffer sb = new StringBuffer();
1134:                    sb.append(methodName);
1135:                    if (txn != null) {
1136:                        sb.append(" txnId=").append(txn.getId());
1137:                    }
1138:                    sb.append(" key=").append(key.dumpData());
1139:                    if (data != null) {
1140:                        sb.append(" data=").append(data.dumpData());
1141:                    }
1142:                    if (lockMode != null) {
1143:                        sb.append(" lockMode=").append(lockMode);
1144:                    }
1145:                    logger.log(level, sb.toString());
1146:                }
1147:            }
1148:
1149:            /**
1150:             * Send trace messages to the java.util.logger. Don't rely on the logger
1151:             * alone to conditionalize whether we send this message, we don't even want
1152:             * to construct the message if the level is not enabled.
1153:             */
1154:            void trace(Level level, String methodName, Transaction txn,
1155:                    CursorConfig config) throws DatabaseException {
1156:
1157:                if (logger.isLoggable(level)) {
1158:                    StringBuffer sb = new StringBuffer();
1159:                    sb.append(methodName);
1160:                    sb.append(" name=" + getDebugName());
1161:                    if (txn != null) {
1162:                        sb.append(" txnId=").append(txn.getId());
1163:                    }
1164:                    if (config != null) {
1165:                        sb.append(" config=").append(config);
1166:                    }
1167:                    logger.log(level, sb.toString());
1168:                }
1169:            }
1170:
1171:            /*
1172:             * Manage triggers.
1173:             */
1174:
1175:            /**
1176:             * Returns whether any triggers are currently associated with this primary.
1177:             * Note that an update of the trigger list may be in progress and this
1178:             * method does not wait for that update to be completed.
1179:             */
1180:            boolean hasTriggers() {
1181:
1182:                return triggerList != null;
1183:            }
1184:
1185:            /**
1186:             * Gets a read-lock on the list of triggers.  releaseTriggerListReadLock()
1187:             * must be called to release the lock.  Called by all primary put and
1188:             * delete operations.
1189:             */
1190:            private void acquireTriggerListReadLock() throws DatabaseException {
1191:
1192:                EnvironmentImpl env = envHandle.getEnvironmentImpl();
1193:                env.getTriggerLatch().acquireShared();
1194:                if (triggerList == null) {
1195:                    triggerList = new ArrayList();
1196:                }
1197:            }
1198:
1199:            /**
1200:             * Releases a lock acquired by calling acquireTriggerListReadLock().
1201:             */
1202:            private void releaseTriggerListReadLock() throws DatabaseException {
1203:
1204:                EnvironmentImpl env = envHandle.getEnvironmentImpl();
1205:                env.getTriggerLatch().release();
1206:            }
1207:
1208:            /**
1209:             * Gets a write lock on the list of triggers.  An empty list is created if
1210:             * necessary, so null is never returned.  releaseTriggerListWriteLock()
1211:             * must always be called to release the lock.
1212:             */
1213:            private void acquireTriggerListWriteLock() throws DatabaseException {
1214:
1215:                EnvironmentImpl env = envHandle.getEnvironmentImpl();
1216:                env.getTriggerLatch().acquireExclusive();
1217:                if (triggerList == null) {
1218:                    triggerList = new ArrayList();
1219:                }
1220:            }
1221:
1222:            /**
1223:             * Releases a lock acquired by calling acquireTriggerListWriteLock().  If
1224:             * the list is now empty then it is set to null, that is, hasTriggers()
1225:             * will subsequently return false.
1226:             */
1227:            private void releaseTriggerListWriteLock() throws DatabaseException {
1228:
1229:                if (triggerList.size() == 0) {
1230:                    triggerList = null;
1231:                }
1232:                EnvironmentImpl env = envHandle.getEnvironmentImpl();
1233:                env.getTriggerLatch().release();
1234:            }
1235:
1236:            /**
1237:             * Adds a given trigger to the list of triggers.  Called while opening
1238:             * a SecondaryDatabase.
1239:             *
1240:             * @param insertAtFront true to insert at the front, or false to append.
1241:             */
1242:            void addTrigger(DatabaseTrigger trigger, boolean insertAtFront)
1243:                    throws DatabaseException {
1244:
1245:                acquireTriggerListWriteLock();
1246:                try {
1247:                    if (insertAtFront) {
1248:                        triggerList.add(0, trigger);
1249:                    } else {
1250:                        triggerList.add(trigger);
1251:                    }
1252:                    trigger.triggerAdded(this );
1253:                } finally {
1254:                    releaseTriggerListWriteLock();
1255:                }
1256:            }
1257:
1258:            /**
1259:             * Removes a given trigger from the list of triggers.  Called by
1260:             * SecondaryDatabase.close().
1261:             */
1262:            void removeTrigger(DatabaseTrigger trigger)
1263:                    throws DatabaseException {
1264:
1265:                acquireTriggerListWriteLock();
1266:                try {
1267:                    triggerList.remove(trigger);
1268:                    trigger.triggerRemoved(this );
1269:                } finally {
1270:                    releaseTriggerListWriteLock();
1271:                }
1272:            }
1273:
1274:            /**
1275:             * Clears the list of triggers.  Called by close(), this allows closing the
1276:             * primary before its secondaries, although we document that secondaries
1277:             * should be closed first.
1278:             */
1279:            private void removeAllTriggers() throws DatabaseException {
1280:
1281:                acquireTriggerListWriteLock();
1282:                try {
1283:                    for (int i = 0; i < triggerList.size(); i += 1) {
1284:                        DatabaseTrigger trigger = (DatabaseTrigger) triggerList
1285:                                .get(i);
1286:                        trigger.triggerRemoved(this );
1287:                    }
1288:                    triggerList.clear();
1289:                } finally {
1290:                    releaseTriggerListWriteLock();
1291:                }
1292:            }
1293:
1294:            /**
1295:             * Notifies associated triggers when a put() or delete() is performed on
1296:             * the primary.  This method is normally called only if hasTriggers() has
1297:             * returned true earlier.  This avoids acquiring a shared latch for
1298:             * primaries with no triggers.  If a trigger is added during the update
1299:             * process, there is no requirement to immediately start updating it.
1300:             *
1301:             * @param locker the internal locker.
1302:             *
1303:             * @param priKey the primary key.
1304:             *
1305:             * @param oldData the primary data before the change, or null if the record
1306:             * did not previously exist.
1307:             *
1308:             * @param newData the primary data after the change, or null if the record
1309:             * has been deleted.
1310:             */
1311:            void notifyTriggers(Locker locker, DatabaseEntry priKey,
1312:                    DatabaseEntry oldData, DatabaseEntry newData)
1313:                    throws DatabaseException {
1314:
1315:                acquireTriggerListReadLock();
1316:                try {
1317:                    for (int i = 0; i < triggerList.size(); i += 1) {
1318:                        DatabaseTrigger trigger = (DatabaseTrigger) triggerList
1319:                                .get(i);
1320:
1321:                        /* Notify trigger. */
1322:                        trigger.databaseUpdated(this, locker, priKey, oldData,
1323:                                newData);
1324:                    }
1325:                } finally {
1326:                    releaseTriggerListReadLock();
1327:                }
1328:            }
1329:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.