boolean highPriority,
FlushStats fstats)
throws DatabaseException {
LogManager logManager = envImpl.getLogManager();
DbTree dbTree = envImpl.getDbTree();
/*
* Use a tracker to count lazily compressed, deferred write, LNs as
* obsolete. A local tracker is used to accumulate tracked obsolete
* info so it can be added in a single call under the log write latch.
* [#15365]
*/
LocalUtilizationTracker localTracker =
new LocalUtilizationTracker(envImpl);
while (dirtyMap.getNumLevels() > 0) {
/* Work on one level's worth of nodes in ascending level order. */
Integer currentLevel = dirtyMap.getLowestLevelSet();
int currentLevelVal = currentLevel.intValue();
/*
* Flush MapLNs just prior to flushing the first level of the
* mapping tree. Only flush a database if it has not already been
* flushed since checkpoint start.
*/
if (currentLevelVal == IN.DBMAP_LEVEL) {
dirtyMap.flushMapLNs(checkpointStart);
}
/* Flush the nodes at the current level. */
while (true) {
CheckpointReference targetRef =
dirtyMap.removeNextNode(currentLevel);
if (targetRef == null) {
break;
}
/*
* Check to make sure the DB was not deleted after putting it
* in the dirty map, and prevent the DB from being deleted
* while we're working with it.
*/
DatabaseImpl db = null;
try {
db = dbTree.getDb(targetRef.dbId);
if (db != null && !db.isDeleted()) {
/* Flush if we're below maxFlushLevel. */
int maxFlushLevel = getHighestFlushLevelInternal
(db, highestFlushLevels);
if (currentLevelVal <= maxFlushLevel) {
/* Evict before each operation. */
envImpl.criticalEviction(true /*backgroundIO*/);
flushIN
(envImpl, db, logManager, targetRef, dirtyMap,
currentLevelVal, maxFlushLevel, allowDeltas,
checkpointStart, highPriority,
fstats, localTracker,
true /*allowLogSubtree*/);
/*
* Sleep if background read/write limit was
* exceeded.
*/
envImpl.sleepAfterBackgroundIO();
}
}
} finally {
dbTree.releaseDb(db);
}
}
/* We're done with this level. */
dirtyMap.removeLevel(currentLevel);