FixLog.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited by: Willie-Sue, June 18, 1985 5:07:32 pm PDT
DIRECTORY
FS USING [PagesForBytes],
IO,
Rope USING [ROPE],
ViewerClasses USING [Viewer],
ViewerIO USING [CreateViewerStreams],
ViewerOps USING [FindViewer, OpenIcon],
WalnutDefs USING [Error],
WalnutLog USING [LogLength, OpenLogStreams, ReturnCurrentLogStreams, ShutdownLog],
WalnutLogExpunge USING [CopyEntry, EndExpunge, GetExpungeProgress, PeekEntry, SetPosition, Shutdown, SkipEntry, StartExpunge],
WalnutRoot USING [CloseTransaction, CommitAndContinue, Open, RegisterStatsProc, StartTransaction, SwapLogs, UnregisterStatsProc];
FixLog: CEDAR PROGRAM
IMPORTS
FS, IO, ViewerIO, ViewerOps, WalnutDefs, WalnutLog, WalnutLogExpunge, WalnutRoot
= BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
out: STREAMNIL;
DebugStream: PROC RETURNS [IO.STREAM]
= BEGIN
v: ViewerClasses.Viewer← ViewerOps.FindViewer["NewWalnut FixLog"];
out: IO.STREAM← ViewerIO.CreateViewerStreams["NewWalnut FixLog", v].out;
IF v#NIL THEN IF v.iconic THEN ViewerOps.OpenIcon[v];
RETURN[out];
END;
debugging: BOOLFALSE;
Fix: PROC[rootFile: ROPE, entriesToIgonore: LIST OF REF ANY] = {
previousAt, at: INT ← -1;
ident: ATOM;
logLength, newLen: INT;
expungeID: INT;
num, numSinceFlush: INT ← 0;
bytesBetweenFlushes: INT = 200000;
toBeIgnored: LIST OF ATOM;
pagesNeeded: INT;
FOR ei: LIST OF REF ANY ← entriesToIgonore, ei.rest UNTIL ei = NIL DO
ax: ATOMNARROW[ei.first];
toBeIgnored ← CONS[ax, toBeIgnored];
ENDLOOP;
out ← DebugStream[];
WalnutRoot.RegisterStatsProc[Report];
[] ← WalnutRoot.Open[rootFile];
[] ← WalnutRoot.StartTransaction[];
[] ← WalnutLog.OpenLogStreams[];
pagesNeeded ← FS.PagesForBytes[logLength ← WalnutLog.LogLength[]];
WalnutLog.ReturnCurrentLogStreams[];
expungeID ← WalnutLogExpunge.StartExpunge[pagesNeeded];
out.PutF["\n Fixing, using the rootfile: %g\n", IO.rope[rootFile]];
out.PutRope["\n Ignoring the following entries: "];
FOR ignore: LIST OF ATOM ← toBeIgnored, ignore.rest UNTIL ignore = NIL DO
out.PutF[" %g,", IO.atom[ignore.first]];
ENDLOOP;
out.PutChar['\n];
[] ← WalnutLogExpunge.SetPosition[0];
BEGIN ENABLE WalnutDefs.Error => {
out.PutF["WalnutDefs Error: code: %g, info: %g at %g",
IO.atom[code], IO.rope[explanation], IO.time[] ];
GOTO error;
};
DO
bytesThisCopy, newPos: INT;
didSkip: BOOLFALSE;
previousAt ← at;
[ident, , at]← WalnutLogExpunge.PeekEntry[];
IF ident = NIL AND at # -1 THEN EXIT;
IF at = previousAt THEN {  -- probably transAbort
[] ← WalnutLogExpunge.SkipEntry[];
out.PutF["\n At pos %g a secoond time\n", IO.int[at]];
LOOP
};
FOR ignore: LIST OF ATOM ← toBeIgnored, ignore.rest UNTIL ignore = NIL DO
IF ident = ignore.first THEN
{ [] ← WalnutLogExpunge.SkipEntry[]; didSkip ← TRUE; EXIT; };
ENDLOOP;
IF didSkip THEN LOOP;
IF ident = $LogFileInfo THEN { [] ← WalnutLogExpunge.SkipEntry[]; LOOP };
[newPos, bytesThisCopy] ← WalnutLogExpunge.CopyEntry[];
IF debugging THEN out.PutF[" - copied to %g", IO.int[newPos]];
IF ident = $CreateMsg THEN {
IF (num← num + 1) MOD 10 = 0 THEN
IF num MOD 100 = 0 THEN out.PutF["(%g)", IO.int[num]]
ELSE out.PutChar['.];
};
numSinceFlush ← numSinceFlush + bytesThisCopy;
IF numSinceFlush >= bytesBetweenFlushes THEN {
[] ← WalnutLogExpunge.GetExpungeProgress[];
WalnutRoot.CommitAndContinue[];
numSinceFlush ← 0;
};
ENDLOOP;
[] ← WalnutLogExpunge.GetExpungeProgress[];
WalnutLogExpunge.EndExpunge[];
WalnutRoot.CommitAndContinue[];
[ , newLen] ← WalnutRoot.SwapLogs[expungeID];
WalnutRoot.UnregisterStatsProc[Report];
WalnutRoot.CloseTransaction[];
out.PutF["\n The old log was %g bytes, the new log is %g bytes",
IO.int[logLength], IO.int[newLen]];
out.PutF["\nThe log file contains %g messages", IO.int[num]];
EXITS
error => {
WalnutLogExpunge.EndExpunge[];
WalnutRoot.UnregisterStatsProc[Report];
WalnutLogExpunge.Shutdown[];
WalnutLog.ShutdownLog[];
WalnutRoot.CloseTransaction[];
};
END;
};
Report: PROC[r: ROPE] =
{ out.PutF["\n %g @ %g\n", IO.rope[r], IO.time[]] };
END.