void removePerDbMetadata(final Collection<Long> fileNums,
final Set<DatabaseId> databases)
throws DatabaseException {
final LogManager logManager = env.getLogManager();
final DbTree dbTree = env.getDbTree();
/* Only call logMapTreeRoot once for ID and NAME DBs. */
DatabaseImpl idDatabase = dbTree.getDb(DbTree.ID_DB_ID);
DatabaseImpl nameDatabase = dbTree.getDb(DbTree.NAME_DB_ID);
boolean logRoot = false;
if (logManager.removeDbFileSummaries(idDatabase, fileNums)) {
logRoot = true;
}
if (logManager.removeDbFileSummaries(nameDatabase, fileNums)) {
logRoot = true;
}
if (logRoot) {
env.logMapTreeRoot();
}
/* Use DB ID set if available to avoid full scan of ID DB. */
if (databases != null) {
for (DatabaseId dbId : databases) {
if (!dbId.equals(DbTree.ID_DB_ID) &&
!dbId.equals(DbTree.NAME_DB_ID)) {
DatabaseImpl db = dbTree.getDb(dbId);
try {
if (db != null &&
logManager.removeDbFileSummaries(db, fileNums)) {
dbTree.modifyDbRoot(db);
}
} finally {
dbTree.releaseDb(db);
}
}
}
} else {
/*
* Use LockType.NONE for traversing the ID DB so that a lock is not
* held when calling modifyDbRoot, which must release locks to
* handle deadlocks.
*/
CursorImpl.traverseDbWithCursor(idDatabase,
LockType.NONE,
true /*allowEviction*/,
new CursorImpl.WithCursor() {
public boolean withCursor(CursorImpl cursor,
DatabaseEntry key,
DatabaseEntry data)
throws DatabaseException {
MapLN mapLN = (MapLN) cursor.getCurrentLN(LockType.NONE);
if (mapLN != null) {
DatabaseImpl db = mapLN.getDatabase();
if (logManager.removeDbFileSummaries(db, fileNums)) {
/*
* Because we're using dirty-read, silently do
* nothing if the DB does not exist
* (mustExist=false).
*/
dbTree.modifyDbRoot
(db, DbLsn.NULL_LSN /*ifBeforeLsn*/,
false /*mustExist*/);
}
}
return true;