[cmd: Handle] RETURNS [result: REF ← NIL, msg: ROPE ← NIL]
CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...]
out: IO.STREAM;
noisy: BOOL ← FALSE;
offset: INT ← 0;
ok: BOOL;
checkpointWord: YggEnvironment.WordNumber;
checkpointRecord: YggLog.RecordID;
startAnalysisRecord: YggLog.RecordID;
currentRecord: YggLog.RecordID;
nextRecord: YggLog.RecordID;
out ← cmd.out;
[] ← YggLogBasic.EstablishLogFile[];
[ok, checkpointWord, checkpointRecord, startAnalysisRecord] ← YggLogControl.DiscoverWhereToStartAnalysisPass[FALSE];
IF ~ok THEN out.PutF["\nCheckpoint does not point at the start of a checkpoint record"];
out.PutF["\nCheckpoint at %g words and %g record ID, with start at %g words\n", IO.card[checkpointWord.low], IO.card[checkpointRecord.low], IO.card[startAnalysisRecord.low] ];
{
notStartOfRecord: BOOL;
[notStartOfRecord: notStartOfRecord, currentRecord: currentRecord] ←
YggLogBasic.OpenRecordStreamFromCheckpoint[checkpointWord: checkpointWord,
checkpointRecord: checkpointRecord, firstRecord: startAnalysisRecord];
IF notStartOfRecord THEN ERROR;
};
DO
status: YggLog.ReadProcStatus;
wordsRead: CARDINAL;
sizeOfRecordDataInWords: CARD;
recordHeader: LONG POINTER TO YggLogRep.TransactionHeader;
recordData: LONG POINTER;
IF YggLogBasic.CheckCurrentRecord[].truncated THEN EXIT;
[status: status, wordsRead: wordsRead] ← YggLog.ReadForRecovery[thisRecord: currentRecord, wordsToSkip: 0, to: [base: LOOPHOLE[RecoveryBlock], length: 4096]];
IF status # normal THEN ERROR;
IF wordsRead < 4 THEN ERROR; -- fix this
recordHeader ← LOOPHOLE[RecoveryBlock];
sizeOfRecordDataInWords ← wordsRead - WORDS[YggLogRep.TransactionHeader]/WORDS[CARD32];
recordData ← LOOPHOLE[RecoveryBlock, LONG POINTER] + UNITS[YggLogRep.TransactionHeader];
Now we have:
sizeOfRecordDataInWords 32 bit words of data starting at recordData
it is for optr of recordHeader.optr
= [segmentId: segmentIdT, highOffset: CARD16, lowOffset: CARD32]
TRUSTED {
out.PutF["segmentId: %g, lowOffset: %g, sizeOfRecordDataInWords: %g\n", IO.card[recordHeader.optr.segmentId.value], IO.card[recordHeader.optr.lowOffset], IO.card[sizeOfRecordDataInWords]];
};
{
endOfLog, truncatedRecord: BOOL;
[endOfLog: endOfLog, truncatedRecord: truncatedRecord, currentRecord: nextRecord] ← YggLogBasic.AdvanceRecordStream[];
IF endOfLog THEN EXIT;
};
currentRecord ← nextRecord;
ENDLOOP;
};