*/
private IN selectIN(INList inList, ScanIterator scanIter)
throws DatabaseException {
/* Find the best target in the next <nodesPerScan> nodes. */
IN target = null;
long targetGeneration = Long.MAX_VALUE;
int targetLevel = Integer.MAX_VALUE;
boolean targetDirty = true;
boolean envIsReadOnly = envImpl.isReadOnly();
int scanned = 0;
boolean wrapped = false;
while (scanned < nodesPerScan) {
if (scanIter.hasNext()) {
IN in = scanIter.next();
nNodesScannedThisRun++;
DatabaseImpl db = in.getDatabase();
/* If the database was deleted, remove it from the inlist. */
if (db == null || db.getIsDeleted()) {
scanIter.remove();
continue;
}
/*
* Don't evict the DatabaseImpl Id Mapping Tree (db 0), both
* for object identity reasons and because the id mapping tree
* should stay cached.
*/
if (db.getId().equals(DbTree.ID_DB_ID)) {
continue;
}
/*
* If this is a read only database and we have at least one
* target, skip any dirty INs (recovery dirties INs even in a
* read-only environment). We take at least one target so we
* don't loop endlessly if everything is dirty.
*/
if (envIsReadOnly && (target != null) && in.getDirty()) {
continue;
}
/*
* Only scan evictable or strippable INs. This prevents higher
* level INs from being selected for eviction, unless they are
* part of an unused tree.
*/
int evictType = in.getEvictionType();
if (evictType == IN.MAY_NOT_EVICT) {
continue;
}
/*
* This node is in the scanned node set. Select according to
* the configured eviction policy.
*/
if (evictByLruOnly) {
/*
* Select the node with the lowest generation number,
* irrespective of tree level or dirtyness.
*/
if (targetGeneration > in.getGeneration()) {
targetGeneration = in.getGeneration();
target = in;
}
} else {
/*
* Select first by tree level, then by dirtyness, then by
* generation/LRU.
*/
int level = normalizeLevel(in, evictType);
if (targetLevel != level) {
if (targetLevel > level) {
targetLevel = level;
targetDirty = in.getDirty();
targetGeneration = in.getGeneration();
target = in;
}
} else if (targetDirty != in.getDirty()) {
if (targetDirty) {
targetDirty = false;
targetGeneration = in.getGeneration();
target = in;
}
} else {
if (targetGeneration > in.getGeneration()) {
targetGeneration = in.getGeneration();
target = in;
}
}
}
scanned++;