DIRECTORY FS USING [PagesForBytes], IO, RefTab USING [EachPairAction, Ref, Val, Create, Fetch, Store, Pairs], 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 [CommitAndContinue, Open, RegisterStatsProc, Shutdown, StartTransaction, SwapLogs, UnregisterStatsProc], WalnutStream USING [Open, PeekEntry]; LogInfo: CEDAR PROGRAM IMPORTS FS, IO, RefTab, ViewerIO, ViewerOps, WalnutDefs, WalnutLog, WalnutLogExpunge, WalnutRoot, WalnutStream = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; out: STREAM _ NIL; debugging: BOOL _ FALSE; Xyz: TYPE = REF ValueObject; ValueObject: TYPE = RECORD[num, bytes: INT _ 0]; TSStream: PROC[name: ROPE] RETURNS [in, out: STREAM] = { v: ViewerClasses.Viewer _ ViewerOps.FindViewer[name]; [in, out] _ ViewerIO.CreateViewerStreams[name, v]; IF v#NIL THEN IF v.iconic THEN ViewerOps.OpenIcon[v]; }; Scan: PROC[logFile: ROPE] = { strm: STREAM; out _ TSStream["Walnut ScanLog"].out; strm _ WalnutStream.Open[name: logFile, readOnly: TRUE]; out.PutF["\n Scanning the logfile: %g\n\n(0)", IO.rope[logFile]]; strm.SetIndex[0]; DoScan[strm]; strm.Close[]; }; 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 _ TSStream["Walnut FixLog"].out; 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]]; IF toBeIgnored = NIL THEN out.PutRope[" No entries will be ignored\n"] ELSE { 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 second 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 }; IF ~ValidIdent[ident, at] 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.Shutdown[]; out.PutF["\n The old log was %g bytes, the new log is %g bytes", IO.int[logLength], IO.int[newLen]]; out.PutF["\n The log file contains %g messages", IO.int[num]]; EXITS error => { WalnutLogExpunge.EndExpunge[]; WalnutRoot.UnregisterStatsProc[Report]; WalnutLogExpunge.Shutdown[]; WalnutLog.ShutdownLog[]; WalnutRoot.Shutdown[]; }; END; }; ValidIdent: PROC[ident: ATOM, at: INT] RETURNS[valid: BOOL] = { SELECT ident FROM $LogFileInfo => RETURN[TRUE]; $CreateMsg => RETURN[TRUE]; $ExpungeMsgs => RETURN[TRUE]; $WriteExpungeLog => RETURN[TRUE]; $CreateMsgSet => RETURN[TRUE]; $DestroyMsgSet => RETURN[TRUE]; $EmptyMsgSet => RETURN[TRUE]; $HasBeenRead => RETURN[TRUE]; $AddMsg => RETURN[TRUE]; $RemoveMsg => RETURN[TRUE]; $MoveMsg => RETURN[TRUE]; $RecordNewMailInfo => RETURN[TRUE]; $StartCopyNewMail => RETURN[TRUE]; $EndCopyNewMailInfo => RETURN[TRUE]; $AcceptNewMail => RETURN[TRUE]; $StartReadArchiveFile => RETURN[TRUE]; $EndReadArchiveFile => RETURN[TRUE]; $StartCopyReadArchive => RETURN[TRUE]; $EndCopyReadArchiveInfo => RETURN[TRUE]; ENDCASE => NULL; out.PutF["\n~~~~ Invalid Entry with identifier $%g at log pos %g\n", IO.atom[ident], IO.int[at] ]; RETURN[FALSE] }; DoScan: PROC[strm: STREAM] = { ident: ATOM; length: INT; table: RefTab.Ref _ RefTab.Create[]; found: BOOL; val: RefTab.Val; count: INT _ 0; at : INT _ strm.GetIndex[]; ForPrinting: RefTab.EachPairAction = { ident: ATOM _ NARROW[key]; this: Xyz _ NARROW[val]; out.PutF["Ident: %g, num: %g, bytes: %g\n", IO.atom[ident], IO.int[this.num], IO.int[this.bytes] ]; RETURN[FALSE]; -- don't quit }; DO this: Xyz; [ident, , length] _ WalnutStream.PeekEntry[strm]; IF ident = NIL THEN EXIT; strm.SetIndex[at _ at + length]; [found, val] _ RefTab.Fetch[table, ident]; IF found THEN { this _ NARROW[val]; this.num _ this.num + 1; this.bytes _ this.bytes + length; } ELSE this _ NEW[ValueObject _ [1, length]]; [] _ RefTab.Store[table, ident, this]; IF (count _ count + 1) MOD 10 = 0 THEN { IF count MOD 100 = 0 THEN out.PutF["(%g)", IO.int[count]] ELSE out.PutChar['~]; }; ENDLOOP; out.PutF["\n\n\t\tThe log contained the following %g entries:\n", IO.int[count]]; [] _ RefTab.Pairs[table, ForPrinting]; }; Report: PROC[msg: ROPE] = { out.PutF["\n %g @ %g\n", IO.rope[msg], IO.time[]] }; END. ΒLogInfo.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by: Willie-Sue, July 11, 1985 1:24:32 pm PDT this changes whenever WalnutKernelDefs.LogEntry changes Κλ˜šœ ™ Icodešœ Οmœ1™<—Jšœ8™8J˜šΟk ˜ Jšžœžœ˜Jšžœ˜Jšœžœ9˜EJšœžœžœ˜Jšœžœ ˜Jšœ žœ˜%Jšœ žœ˜'Jšœ žœ ˜Jšœ žœC˜RJšœžœh˜~Jšœ žœi˜yJšœ žœ˜%—J˜šœ žœž˜J˜šž˜Jšžœžœ˜$JšœA˜AJ˜—Jšœž˜J˜Jšžœžœžœ˜Jšžœžœžœžœ˜Jšœžœžœ˜Jšœ žœžœ˜Jšœžœžœ ˜Jšœ žœžœ žœ˜0J˜J˜—š Οnœžœžœžœ žœ˜8Jšœ5˜5Jšœ žœ(˜2Jš žœžœžœžœ žœ˜5Jšœ˜—J˜šŸœžœ žœ˜Jšœžœ˜ Jšœ%˜%Jšœ2žœ˜8Jšœ0žœ˜BJ˜Jšœ ˜ Jšœ ˜ J˜—J˜šŸœžœ žœžœžœžœžœ˜@Jšœžœ˜Jšœžœ˜ Jšœžœ˜Jšœ žœ˜Jšœžœ˜Jšœžœ ˜"Jšœ žœžœžœ˜Jšœ žœ˜J˜šžœžœžœžœžœžœžœž˜EJšœžœžœ ˜Jšœžœ˜$Jšžœ˜—J˜Jšœ$˜$Jšœ%˜%J˜Jšœ˜J˜#J˜ Jšœžœ2˜BJ˜$Jšœ7˜7J˜Jšœ1žœ˜DJ˜šžœžœž˜J˜,šžœ˜Jšœ3˜3š žœ žœžœžœžœ žœž˜IJšœžœ˜(Jšžœ˜—J˜J˜——J˜J˜%J˜šžœžœ˜"šœ7˜7Jšžœ žœžœ ˜1—Jšžœ˜ J˜—šž˜Jšœžœ˜Jšœ žœžœ˜Jšœ˜Jšœ-˜-Jš žœ žœžœ žœžœ˜%šžœžœΟc˜1Jšœ"˜"Jšœ)žœ ˜5Jšž˜J˜—J˜š žœ žœžœžœžœ žœž˜Išžœž˜Jšœ/žœžœ˜=—Jšžœ˜—Jšžœ žœžœ˜J˜Jšžœžœ&žœ˜Išžœž˜Jšœ%žœ˜,—J˜Jšœ7˜7J˜Jšžœ žœžœ˜>šžœžœ˜šžœžœž˜!šžœžœ žœžœ ˜5Jšžœ˜—J˜——J˜Jšœ.˜.šžœ&žœ˜.J˜+J˜Jšœ˜J˜—Jšžœ˜—J˜Jšœ+˜+J˜J˜J˜Jšœ-˜-Jšœ'˜'J˜J˜šœ@˜@Jšžœžœ˜#—Jšœ1žœ ˜>˜šž˜˜ J˜Jšœ'˜'Jšœ˜Jšœ˜J˜J˜——Jšžœ˜—J˜—J˜š Ÿ œžœžœžœžœžœ˜?Jšœ7™7šžœž˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜!Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœ žœžœ˜Jšœžœžœ˜Jšœ žœžœ˜Jšœžœžœ˜#Jšœžœžœ˜"Jšœžœžœ˜$Jšœžœžœ˜Jšœžœžœ˜&Jšœžœžœ˜$Jšœžœžœ˜&Jšœžœžœ˜(Jšžœžœ˜—šœD˜DJšžœžœ ˜—Jšžœžœ˜ J˜—J˜šŸœžœžœ˜Jšœžœ˜ Jšœžœ˜ J˜$Jšœžœ˜ J˜Jšœžœ˜Jšœžœ˜J˜šŸ œ˜&Jšœžœžœ˜Jšœ žœ˜šœ+˜+Jšžœžœžœ˜7—Jšžœžœ  ˜J˜—J˜šž˜J˜ Jšœ2˜2Jšžœ žœžœžœ˜J˜ Jšœ*˜*šžœžœ˜Jšœžœ˜J˜Jšœ!˜!J˜—Jšžœžœ˜+J˜Jšœ&˜&šžœžœžœ˜(šžœžœ žœžœ ˜9Jšžœ˜—J˜—Jšžœ˜—JšœBžœ ˜QJ˜&J˜J˜—J˜šŸœžœžœ˜Jšœžœ žœ ˜6—J˜Jšžœ˜J˜—…—¨"U