* Use a single transaction for opening the primary DB and its
* secondaries. If opening any secondary fails, abort the
* transaction and undo the changes to the state of the store.
* Also support undo if the store is non-transactional.
*/
Transaction txn = null;
DatabaseConfig dbConfig = getPrimaryConfig(entityMeta);
if (dbConfig.getTransactional() &&
DbCompat.getThreadTransaction(env) == null) {
txn = env.beginTransaction(null, null);
}
PrimaryOpenState priOpenState =
new PrimaryOpenState(entityClassName);
boolean success = false;
try {
/* Open the primary database. */
String[] fileAndDbNames =
parseDbName(storePrefix + entityClassName);
Database db;
try {
db = DbCompat.openDatabase
(env, txn, fileAndDbNames[0], fileAndDbNames[1],
dbConfig);
} catch (FileNotFoundException e) {
throw new DatabaseException(e);
}
priOpenState.addDatabase(db);
/* Create index object. */
priIndex = new PrimaryIndex
(db, primaryKeyClass, keyBinding, entityClass,
entityBinding);
/* Update index and database maps. */
priIndexMap.put(entityClassName, priIndex);
if (DbCompat.getDeferredWrite(dbConfig)) {
deferredWriteDatabases.put(db, null);
}
/* If not read-only, open all associated secondaries. */
if (!dbConfig.getReadOnly()) {
openSecondaryIndexes(txn, entityMeta, priOpenState);
/*
* To enable foreign key contratints, also open all primary
* indexes referring to this class via a relatedEntity
* property in another entity. [#15358]
*/
Set<String> inverseClassNames =
inverseRelatedEntityMap.get(entityClassName);
if (inverseClassNames != null) {
for (String relatedClsName : inverseClassNames) {
getRelatedIndex(relatedClsName);
}
}
}
success = true;
} finally {
if (success) {
if (txn != null) {
txn.commit();
}
} else {
if (txn != null) {
txn.abort();
} else {
priOpenState.closeDatabases();
}
priOpenState.undoState();
}