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];
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: ATOM ← NARROW[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: BOOL ← FALSE;
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;
};