int clrskipped = 0;
int logrecordseen = 0;
StreamLogScan scanLog;
Compensation compensation = null;
Undoable lop = null;
// stream to read the log record - initial size 4096, scanLog needs
// to resize if the log record is larget than that.
ArrayInputStream rawInput = null;
try
{
if (undoStartAt == null)
{
// don't know where to start, rollback from end of log
scanLog = (StreamLogScan)
logFactory.openBackwardsScan(undoStopAt);
}
else
{
if (undoStartAt.lessThan(undoStopAt))
{
// nothing to undo!
return;
}
long undoStartInstant =
((LogCounter) undoStartAt).getValueAsLong();
scanLog = (StreamLogScan)
logFactory.openBackwardsScan(undoStartInstant, undoStopAt);
}
if (SanityManager.DEBUG)
SanityManager.ASSERT(
scanLog != null, "cannot open log for undo");
rawInput = new ArrayInputStream(new byte[4096]);
LogRecord record;
while ((record =
scanLog.getNextRecord(rawInput, undoId, 0))
!= null)
{
if (SanityManager.DEBUG)
{
SanityManager.ASSERT(
record.getTransactionId().equals(undoId),
"getNextRecord return unqualified log record for undo");
}
logrecordseen++;
if (record.isCLR())
{
clrskipped++;
// the loggable is still in the input stream, get rid of it
record.skipLoggable();
// read the undoInstant
long undoInstant = rawInput.readLong();
if (SanityManager.DEBUG)
{
if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
{
SanityManager.DEBUG(
LogToFile.DBG_FLAG,
"Skipping over CLRs, reset scan to " +
LogCounter.toDebugString(undoInstant));
}
}
scanLog.resetPosition(new LogCounter(undoInstant));
// scanLog now positioned at the beginning of the log
// record that was rolled back by this CLR.
// The scan is a backward one so getNextRecord will skip
// over the record that was rolled back and go to the one
// previous to it
continue;
}
lop = record.getUndoable();
if (lop != null)
{
int optionalDataLength = rawInput.readInt();
int savePosition = rawInput.getPosition();
rawInput.setLimit(optionalDataLength);
compensation = lop.generateUndo(t, rawInput);
if (SanityManager.DEBUG)
{
if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
{