CleanerFileReader reader = new CleanerFileReader
(env, readBufferSize, DbLsn.NULL_LSN, fileNum);
/* Validate all entries before ever deleting a file. */
reader.setAlwaysValidateChecksum(true);
DbTree dbMapTree = env.getDbMapTree();
TreeLocation location = new TreeLocation();
int nProcessedLNs = 0;
while (reader.readNextEntry()) {
cleaner.nEntriesRead += 1;
long lsn = reader.getLastLsn();
long fileOffset = DbLsn.getFileOffset(lsn);
boolean isLN = reader.isLN();
boolean isIN = reader.isIN();
boolean isRoot = reader.isRoot();
boolean isObsolete = false;
/* Stop if the daemon is shut down. */
if (env.isClosing()) {
return false;
}
/* Check for a known obsolete node. */
while (nextObsolete < fileOffset && obsoleteIter.hasNext()) {
nextObsolete = obsoleteIter.next();
}
if (nextObsolete == fileOffset) {
isObsolete = true;
}
/* Check for the entry type next because it is very cheap. */
if (!isObsolete &&
!isLN &&
!isIN &&
!isRoot) {
/* Consider all entries we do not process as obsolete. */
isObsolete = true;
}
/* Check for a deleted LN next because it is very cheap. */
if (!isObsolete &&
isLN &&
reader.getLN().isDeleted()) {
/* Deleted LNs are always obsolete. */
isObsolete = true;
}
/* Check the current tracker last, as it is more expensive. */
if (!isObsolete &&
tfs != null &&
tfs.containsObsoleteOffset(fileOffset)) {
isObsolete = true;
}
/* Skip known obsolete nodes. */
if (isObsolete) {
/* Count obsolete stats. */
if (isLN) {
nLNsObsoleteThisRun++;
} else if (isIN) {
nINsObsoleteThisRun++;
}
/* Must update the pending DB set for obsolete entries. */
DatabaseId dbId = reader.getDatabaseId();
if (dbId != null) {
checkPendingDbSet.add(dbId);
}
continue;
}
/* Evict before processing each entry. */
if (Cleaner.DO_CRITICAL_EVICTION) {
env.getEvictor().doCriticalEviction();
}
/* The entry is not known to be obsolete -- process it now. */
if (isLN) {
LN targetLN = reader.getLN();
DatabaseId dbId = reader.getDatabaseId();
byte[] key = reader.getKey();
byte[] dupKey = reader.getDupTreeKey();
lookAheadCache.add
(new Long(DbLsn.getFileOffset(lsn)),
new LNInfo(targetLN, dbId, key, dupKey));
if (lookAheadCache.isFull()) {
processLN(fileNum, location, lookAheadCache, dbCache);
}
/*
* Process pending LNs before proceeding in order to
* prevent the pending list from growing too large.
*/
nProcessedLNs += 1;
if (nProcessedLNs % PROCESS_PENDING_EVERY_N_LNS == 0) {
cleaner.processPending();
}
} else if (isIN) {
IN targetIN = reader.getIN();
DatabaseId dbId = reader.getDatabaseId();
DatabaseImpl db = dbMapTree.getDb
(dbId, cleaner.lockTimeout, dbCache);
targetIN.setDatabase(db);
processIN(targetIN, db, lsn);
} else if (isRoot) {
env.rewriteMapTreeRoot(lsn);
} else {
assert false;
}
}
/* Process remaining queued LNs. */
while (!lookAheadCache.isEmpty()) {
if (Cleaner.DO_CRITICAL_EVICTION) {
env.getEvictor().doCriticalEviction();
}
processLN(fileNum, location, lookAheadCache, dbCache);
}
/* Update the pending DB set. */
for (Iterator i = checkPendingDbSet.iterator(); i.hasNext();) {
DatabaseId dbId = (DatabaseId) i.next();
DatabaseImpl db = dbMapTree.getDb
(dbId, cleaner.lockTimeout, dbCache);
cleaner.addPendingDB(db);
}
/* Update reader stats. */