+ " in entry " + (count - remaining + 1) + " at " + addressToString(from, timestamp));
}
final long pageAddress = PM.getEntryPageAddress(_readBuffer, index);
final long pageTimestamp = PM.getEntryTimestamp(_readBuffer, index);
final long journalAddress = PM.getEntryJournalAddress(_readBuffer, index);
final PageNode pageNode = new PageNode(volumeHandle, pageAddress, journalAddress, pageTimestamp);
final PageNode lastPageNode;
boolean linked = false;
//
// The following logic places the recovered PageNode in either the
// page map or the branch map. The timestamp written in the PM
// record determines which map receives the page, corresponding with
// two different recovery scenarios.
//
// In one scenario, the PM was written as part of a normal rollover,
// and all pages in it are part of the recovered history. In this
// the timestamp at the time the PM record is written will be larger
// than any existing page, and therefore the page will be added to
// the page map.
//
// However, if the PM record was written immediately after a dirty
// startup, the PM's timestamp will be consistent with the recovery
// checkpoint, and there will be pages with timestamps after that.
// Those pages are part of the branch; they are retained in the
// recovery state solely to allow long-record recovery, and will
// then be discarded.
//
// Because pre-2.4.1 PM records were written with a timestamp of
// zero, this is handled as a special case. All pages from such
// journals are recovered.
//
if (timestamp != 0 && timestamp < pageTimestamp) {
lastPageNode = _branchMap.get(pageNode);
if (lastPageNode == null || journalAddress > lastPageNode.getJournalAddress()) {
pageNode.setPrevious(lastPageNode);
_branchMap.put(pageNode, pageNode);
linked = true;
}
} else {
lastPageNode = _pageMap.get(pageNode);
if (lastPageNode == null || journalAddress > lastPageNode.getJournalAddress()) {
pageNode.setPrevious(lastPageNode);
_pageMap.put(pageNode, pageNode);
linked = true;
}
}