envImpl.criticalEviction(false /*backgroundIO*/);
DatabaseImpl database = null;
boolean operationOk = false;
HandleLocker handleLocker = null;
final Locker locker = LockerFactory.getWritableLocker
(this, txn, isInternalDb, dbConfig.getTransactional(),
autoTxnIsReplicated, null);
try {
/*
* Create the handle locker and lock the NameLN of an existing
* database. A read lock on the NameLN is acquired for both locker
* and handleLocker. Note: getDb may return a deleted database.
*/
handleLocker = newDb.initHandleLocker(envImpl, locker);
database = envImpl.getDbTree().getDb(locker, databaseName,
handleLocker);
boolean dbCreated = false;
final boolean databaseExists =
(database != null) && !database.isDeleted();
if (databaseExists) {
if (dbConfig.getAllowCreate() &&
dbConfig.getExclusiveCreate()) {
throw new DatabaseExistsException
("Database " + databaseName + " already exists");
}
newDb.initExisting(this, locker, database, dbConfig);
} else {
/* Release deleted DB. [#13415] */
envImpl.getDbTree().releaseDb(database);
database = null;
if (!isInternalDb &&
DbTree.isReservedDbName(databaseName)) {
throw new IllegalArgumentException
(databaseName + " is a reserved database name.");
}
if (!dbConfig.getAllowCreate()) {
throw new DatabaseNotFoundException("Database " +
databaseName +
" not found.");
}
/*
* Init a new DB. This calls DbTree.createDb and the new
* database is returned. A write lock on the NameLN is
* acquired by locker and a read lock by the handleLocker.
*/
database = newDb.initNew(this, locker, databaseName, dbConfig);
dbCreated = true;
}
/*
* The open is successful. We add the opened database handle to
* this environment to track open handles in general, and to the
* locker so that it can be invalidated by a user txn abort.
*/
operationOk = true;
addReferringHandle(newDb);
locker.addOpenedDatabase(newDb);
/* Run triggers before any subsequent auto commits. */
final boolean firstWriteHandle =
newDb.isWritable() &&
(newDb.getDatabaseImpl().noteWriteHandleOpen() == 1);
if (dbCreated || firstWriteHandle) {
TriggerManager.runOpenTriggers(locker, newDb, dbCreated);
}
} finally {
/*
* If the open fails, decrement the DB usage count and release
* handle locks. In other cases this is done by Database.close()
* or invalidate(), the latter in the case of a user txn abort.
*/
if (!operationOk) {
envImpl.getDbTree().releaseDb(database);
if (handleLocker != null) {
handleLocker.operationEnd(false);
}
}
/*
* Tell the locker that this operation is over. Some types of
* lockers (BasicLocker and auto Txn) will actually finish.
*/
locker.operationEnd(operationOk);
}
}