long evictBytes = 0;
/* Evict utilization tracking info without holding the INList latch. */
evictBytes += envImpl.getUtilizationTracker().evictMemory();
INList inList = envImpl.getInMemoryINs();
inList.latchMajor();
int inListStartSize = inList.getSize();
try {
/*
* Setup the round robin iterator. Note that because critical
* eviction is now called during recovery, when the INList is
* sometimes abruptly cleared, nextNode may not be null when
* the INList is empty.
*/
if (inListStartSize == 0) {
nextNode = null;
return 0;
} else {
if (nextNode == null) {
nextNode = inList.first();
}
}
ScanIterator scanIter = new ScanIterator(nextNode, inList);
/*
* Keep evicting until we've freed enough memory or we've visited
* the maximum number of nodes allowed. Each iteration of the while
* loop is called an eviction batch.
*
* In order to prevent endless evicting and not keep the INList
* major latch for too long, limit this run to one pass over the
* IN list.
*/
while ((evictBytes < requiredEvictBytes) &&
(nNodesScannedThisRun <= inListStartSize)) {
IN target = selectIN(inList, scanIter);
if (target == null) {
break;
} else {
assert evictProfile.count(target);//intentional side effect
evictBytes += evict(inList, target, scanIter);
}
nBatchSets++;
}
/*
* At the end of the scan, look at the next element in the INList
* and put it in nextNode for the next time we scan the INList.
*/
nextNode = scanIter.mark();
finished = true;
} finally {
nNodesScanned += nNodesScannedThisRun;
inList.releaseMajorLatch();
Tracer.trace(detailedTraceLevel, envImpl,
"Evictor: pass=" + nEvictPasses +
" finished=" + finished +
" source=" + source +
" requiredEvictBytes=" +