if (in != null &&
(processDupTree || !in.containsDuplicates())) {
for (int i = 0; i < in.getNEntries(); i++) {
long lsn = in.getLsn(i);
Node node = in.getTarget(i);
if (in.isEntryPendingDeleted(i) ||
in.isEntryKnownDeleted(i)) {
/* Dirty LNs (deferred write) get special treatment. */
if (node instanceof LN) {
LN ln = (LN) node;
if (ln.isDirty()) {
callback.processDirtyDeletedLN
(lsn, ln, in.getKey(i));
}
}
continue;
}
if (accumulate &&
(node == null) &&
lsn != DbLsn.NULL_LSN) {
if (accumulatedLSNFileNumbers == null) {
accumulatedLSNFileNumbers = new OffsetList();
accumulatedLSNFileOffsets = new OffsetList();
}
accumulatedLSNFileNumbers.add(DbLsn.getFileNumber(lsn),
false);
accumulatedLSNFileOffsets.add(DbLsn.getFileOffset(lsn),
false);
/*
* If we're maintaining a map from LSN to owning IN/index,
* then update the map here.
*/
addToLsnINMap(Long.valueOf(lsn), in, i);
/* callback.processLSN is called when we fetch this LSN. */
} else if (lsn != DbLsn.NULL_LSN ||
passNullLSNNodes) {
/*
* If the child is resident, use that log type, else we can
* assume it's an LN.
*/
byte[] lnKey = (node == null || node instanceof LN) ?
in.getKey(i) : null;
callProcessLSNHandleExceptions
(lsn,
(node == null) ?
LogEntryType.LOG_LN :
node.getLogType(),
node, lnKey);
if (node instanceof IN) {
IN nodeAsIN = (IN) node;
try {
nodeAsIN.latch(CacheMode.UNCHANGED);
accumulateLSNs(nodeAsIN);
} finally {
nodeAsIN.releaseLatch();
}
}
}
}
}
/* Handle the DupCountLN for a DIN root. */
if (isDINRoot) {
DIN din = (DIN) in;
ChildReference dupCountLNRef = din.getDupCountLNRef();
long lsn = dupCountLNRef.getLsn();
if (lsn == DbLsn.NULL_LSN) {
DupCountLN dcl = din.getDupCountLN();
callback.processDupCount(dcl.getDupCount());
} else {
/* Negative index signifies a DupCountLN. */
addToLsnINMap(Long.valueOf(lsn), in, -1);
Node node = fetchLSNHandleExceptions(lsn, lnKeyEntry);
if (node != null) {
callProcessLSNHandleExceptions
(lsn, LogEntryType.LOG_DUPCOUNTLN, node,
dupCountLNRef.getKey());
}