DIRECTORY IO, AlpineLog, LogBasic, LogRep, Commander, Rope, Process, RestartFile, FileLog, RuntimeError, RedBlackTree ; AnalyzeAlpineLog: CEDAR PROGRAM IMPORTS IO, AlpineLog, LogBasic, Commander, Process, RestartFile, RuntimeError, RedBlackTree EXPORTS SHARES FileLog = BEGIN WordNumber: TYPE = LogBasic.WordNumber; logSize: INT; FileLogRecord: TYPE = FileLog.FileLogRecord; pageNode: TYPE = RECORD [ file: INT, firstPage, count: INT, occurrenceCount: INT ]; GetKey: RedBlackTree.GetKey ~ { RETURN[data] }; Compare: RedBlackTree.Compare ~ { key: REF pageNode _ NARROW[k]; d: REF pageNode _ NARROW[data]; IF key.file < d.file THEN RETURN[less]; IF key.file > d.file THEN RETURN[greater]; IF key.firstPage < d.firstPage THEN RETURN[less]; IF key.firstPage > d.firstPage THEN RETURN[greater]; IF key.count < d.count THEN RETURN[less]; IF key.count > d.count THEN RETURN[greater]; RETURN[equal]; }; Analyze: PROC [out: IO.STREAM] ~ TRUSTED { wordNumberForCheckpointCompleteRecord: WordNumber _ RestartFile.ReadRestartRecord[].wordNumberForCheckpointCompleteRecord; currentRecord, checkpointRecord, startAnalysisRecord: AlpineLog.RecordID; currentRecordType: LocalRecordType; pageTable: RedBlackTree.Table _ RedBlackTree.Create[ GetKey, Compare ]; PrintPageNode: RedBlackTree.EachNode ~ CHECKED { node: REF pageNode _ NARROW[data]; out.PutF[ "File %g Page %g Length %g Occurrences %g \n", IO.int[node.file], IO.int[node.firstPage], IO.int[node.count], IO.int[node.occurrenceCount] ]; }; newNode, oldNode: REF pageNode; TRUSTED { logSize _ LogBasic.LogFileSize[]*256 }; [checkpointRecord: checkpointRecord, startAnalysisRecord: startAnalysisRecord] _ CheckpointCompleteRecordFromWord[wordNumberForCheckpointCompleteRecord]; TRUSTED {currentRecord _ LogBasic.OpenRecordStreamFromWord[LogBasic.LocateFirstRecord[]].currentRecord;}; DO currentRecordType _ PeekType[currentRecord]; RecordTypeCount[currentRecordType] _ RecordTypeCount[currentRecordType]+1; IF (currentRecordType = writePages) OR (currentRecordType = writeLeaderPage) THEN out.PutF[ "At position %g the record type is %g \n", IO.int[currentRecord.lowBits MOD logSize], IO.rope[RecordTypeName[currentRecordType]] ]; SELECT currentRecordType FROM writePages => { header: FileLogRecord[writePages]; [] _ AlpineLog.ReadForRecovery[thisRecord: currentRecord, to: [base: @header, length: SIZE[FileLogRecord[writePages]]] ! RuntimeError.UNCAUGHT => CONTINUE]; out.PutF[ "\tFileID: %g Pages: %g %g\n", IO.card[LOOPHOLE[header.fileID.id]], IO.card[header.pageRun.firstPage], IO.card[header.pageRun.count]]; oldNode _ NARROW[RedBlackTree.Lookup[ pageTable, newNode _ NEW[pageNode _ [LOOPHOLE[header.fileID.id], header.pageRun.firstPage, header.pageRun.count, 1] ]]]; IF oldNode # NIL THEN { oldNode.occurrenceCount _ oldNode.occurrenceCount + 1; } ELSE RedBlackTree.Insert[pageTable, newNode, newNode]; }; writeLeaderPage => { header: FileLogRecord[writeLeaderPage]; [] _ AlpineLog.ReadForRecovery[thisRecord: currentRecord, to: [base: @header, length: SIZE[FileLogRecord[writeLeaderPage]]] ! RuntimeError.UNCAUGHT => CONTINUE]; out.PutF[ "\tFileID: %g Count: %g\n", IO.card[LOOPHOLE[header.fileID.id]], IO.card[header.pageCount]]; oldNode _ NARROW[RedBlackTree.Lookup[ pageTable, newNode _ NEW[pageNode _ [LOOPHOLE[header.fileID.id], -1, 1, 1] ]]]; IF oldNode # NIL THEN { oldNode.occurrenceCount _ oldNode.occurrenceCount + 1; } ELSE RedBlackTree.Insert[pageTable, newNode, newNode]; }; ENDCASE => NULL; { endOfLog, truncatedRecord: BOOL; [endOfLog: endOfLog, truncatedRecord: truncatedRecord, currentRecord: currentRecord] _ LogBasic.AdvanceRecordStream[]; IF LOOPHOLE[currentRecord.lowBits, INT] MOD logSize = LOOPHOLE[startAnalysisRecord.lowBits, INT] MOD logSize THEN EXIT; }; Process.CheckForAbort[]; ENDLOOP; LogBasic.CloseRecordStream[]; RedBlackTree.EnumerateIncreasing[ pageTable, PrintPageNode ]; }; PeekType: PROC [thisRecord: AlpineLog.RecordID] RETURNS [localRecordType: LocalRecordType] = TRUSTED { recordTypeHeader: LogRep.RecordTypeHeader; status: AlpineLog.ReadProcStatus; [status: status] _ LogBasic.GetCurrentRecord[currentRecord: thisRecord, to: [base: @recordTypeHeader, length: LogRep.RecordTypeHeader.SIZE]]; IF status = sourceExhausted THEN ERROR ; RETURN [GetLocalType[recordTypeHeader.type]]; }; LocalRecordType: TYPE = { noop, checkpointBegin, checkpointComplete, coordinatorBegin, coordinatorRegisterWorker, coordinatorCollecting, coordinatorCompleting, coordinatorComplete, workerBegin, workerReady, workerCompleting, workerComplete, writePages, writeLeaderPage, setSize, create, delete, lock, reserved, none }; RecordTypeName: ARRAY LocalRecordType OF Rope.ROPE = [ "noop", "checkpointBegin", "checkpointComplete", "coordinatorBegin", "coordinatorRegisterWorker", "coordinatorCollecting", "coordinatorCompleting", "coordinatorComplete", "workerBegin", "workerReady", "workerCompleting", "workerComplete", "writePages", "writeLeaderPage", "setSize", "create", "delete", "lock", "reserved", "none" ]; RecordTypeCount: ARRAY LocalRecordType OF INT; GetLocalType: PROC [recordType: AlpineLog.RecordType] RETURNS [localRecordType: LocalRecordType] ~ { SELECT recordType FROM noop => localRecordType _ noop; checkpointBegin => localRecordType _ checkpointBegin; checkpointComplete => localRecordType _ checkpointComplete; coordinatorBegin => localRecordType _ coordinatorBegin; coordinatorRegisterWorker => localRecordType _ coordinatorRegisterWorker; coordinatorCollecting => localRecordType _ coordinatorCollecting; coordinatorCompleting => localRecordType _ coordinatorCompleting; coordinatorComplete => localRecordType _ coordinatorComplete; workerBegin => localRecordType _ workerBegin; workerReady => localRecordType _ workerReady; workerCompleting => localRecordType _ workerCompleting; workerComplete => localRecordType _ workerComplete; writePages => localRecordType _ writePages; writeLeaderPage => localRecordType _ writeLeaderPage; setSize => localRecordType _ setSize; create => localRecordType _ create; delete => localRecordType _ delete; lock => localRecordType _ localRecordType _ lock; reserved => localRecordType _ reserved; ENDCASE => localRecordType _ none; }; CheckpointCompleteRecordFromWord: PROC [checkpointWord: WordNumber] RETURNS [ ok: BOOL, checkpointRecord, startAnalysisRecord: AlpineLog.RecordID] = TRUSTED { { checkpointCompleteRecordBody: LogRep.CheckpointCompleteRecord; notStartOfRecord: BOOL; currentRecord: AlpineLog.RecordID; [notStartOfRecord: notStartOfRecord, currentRecord: currentRecord] _ LogBasic.OpenRecordStreamFromWord[checkpointWord ! LogBasic.InvalidPage => GOTO failReturn ]; IF notStartOfRecord THEN GOTO failReturn; IF LogBasic.CheckCurrentRecord[].truncated THEN GOTO failReturn; IF LogBasic.GetCurrentRecord[currentRecord, [base: @checkpointCompleteRecordBody, length: SIZE[LogRep.CheckpointCompleteRecord]]].status = destinationFull OR checkpointCompleteRecordBody.type # checkpointComplete THEN GOTO failReturn; checkpointRecord _ checkpointCompleteRecordBody.thisRecordID; startAnalysisRecord _ checkpointCompleteRecordBody.startAnalysisRecordID; ok _ TRUE; EXITS failReturn => { ok _ FALSE }; }; LogBasic.CloseRecordStream[]; RETURN [ok, checkpointRecord, startAnalysisRecord]; };--CheckpointCompleteRecordFromWord AnalyzeCommand: Commander.CommandProc -- [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] -- = { RecordTypeCount _ ALL[0]; Analyze[cmd.out]; FOR rt: LocalRecordType IN [noop .. none] DO IF RecordTypeCount[rt]#0 THEN cmd.out.PutF[ " %g: %g ", IO.rope[RecordTypeName[rt]], IO.int[RecordTypeCount[rt]] ]; ENDLOOP; }; Commander.Register[key: "AnalyzeAlpineLog", proc: AnalyzeCommand, doc: "Scan an alpine log listing the types and sizes of the records found in it."] END. ¼AnalyzeAlpineLog.mesa Scan an alpine log listing the types and sizes of the records found in it. Last Edited by: Hauser, May 6, 1985 2:55:17 pm PDT Carl Hauser, November 22, 1985 10:20:41 am PST currentRecord _ LogBasic.OpenRecordStreamFromCheckpoint[wordNumberForCheckpointCompleteRecord, checkpointRecord, startAnalysisRecord].currentRecord; -- ! IO.Error => EXIT Updates: Recover.myFileStore. Returns ok = FALSE if any error detected. Ê2˜J™J™J™2Icode™.—šÏk ˜ Jšœk˜kJ˜—šœ ˜JšœU˜\Jšœ˜Jšœ ˜Jšœ˜J˜—Jšœ'˜'J˜J˜Jšœ-˜-J˜šœ œœ˜Jšœœ˜ Jšœœ˜Jšœ˜J˜—J˜šœ˜J˜ J˜J˜—šœ!˜!Jšœœ˜Jšœœ˜Jšœœœ˜'Jšœœœ ˜*Jšœœœ˜1Jšœœœ ˜4Jšœœœ˜)Jšœœœ ˜,Jšœ˜J˜J˜—š Ïnœœœœœ˜*Jšœ{˜{JšœI˜IJšœ#˜#JšœG˜Gšœ'œ˜0J˜"Jšœ—˜—J˜J˜—J˜J˜1Jšœ™˜™Jšœ”™”Jšœi˜iš˜Jšœ,˜,JšœJ˜JJšœQ˜QšœŠ˜ŠJšœœ ™Jšœ˜—šœ˜šœ˜Jšœ"˜"JšœVœB˜œJšœ˜Jšœ œ˜Ÿšœœ˜J˜6J˜—Jšœ2˜6Jšœ˜—šœ˜Jšœ'˜'JšœVœG˜¡Jšœf˜fJšœ œf˜všœœ˜J˜6J˜—Jšœ2˜6J˜Jšœ˜—Jšœœ˜—˜Jšœ ˜ Jšœv˜vJšœw˜wJ˜—J˜Jš˜—Jšœ˜Jšœ=˜=J˜J˜—šÏbœœ"œ&œ˜fJ˜*J˜!˜GJšœ>œ˜E—Jšœœœ˜(Jšœ'˜-J˜J˜—Jšœœ©˜¾J˜JšœœœœÒ˜„J˜Jšœœœ˜.J˜šŸ œœ$œ'˜dšœ ˜Jšœ˜Jšœ5˜5Jšœ;˜;Jšœ7˜7JšœI˜IJšœA˜AJšœA˜AJšœ=˜=Jšœ-˜-Jšœ-˜-Jšœ7˜7Jšœ3˜3Jšœ+˜+Jšœ5˜5Jšœ%˜%Jšœ#˜#Jšœ#˜#Jšœ1˜1Jšœ'˜'Jšœ˜"—J˜J˜—šž œœœ˜MJšœœH˜PJšœ™šœ)™)J˜J˜>Jšœœ˜J˜"˜D˜JJšœ˜——Jšœœœ ˜)Jšœ)œœ ˜@šœO˜QJšœœ=˜KJšœ7œœ ˜L—J˜=J˜IJšœœ˜ š˜Jšœœ˜—J˜—J˜Jšœ-˜3JšœÏc"˜$J˜—J˜•StartOfExpansionP -- [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] -- šŸœÐckOœ˜yJšœ˜J˜šœ*˜,JšœœW˜tJšœ˜—J˜J˜J–\[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL]šœ”˜”Jšœ˜——…—Z&H