LogImpl.mesa
Simple Logging output, other general utilities; support for spy log stuff.
Last modified by D. Swinehart, December 16, 1983 1:16 pm
DIRECTORY
AMEvents USING [ CallDebugger ],
Atom USING [ PutProp, GetProp, PropList ],
Commander USING [ CommandProc, GetProperty, Handle, Register ],
FS USING [ StreamOpen, Error ],
IO,
Log,
PrincOpsUtils USING [ IsBound ],
ProcessProps USING [ GetPropList ],
Rope USING [ ROPE ],
SpyLog USING [ WriteTrace ]
;
LogImpl: CEDAR MONITOR -- for CLog
IMPORTS
AMEvents,
Atom,
Commander,
FS,
IO,
ProcessProps,
PrincOpsUtils,
SpyLog
EXPORTS Log = {
OPEN IO;
Variables
pd: PUBLIC REF Log.PDNEW[Log.PD←[]];
Copies
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
ThHandle: TYPE = LONG CARDINAL;
WhereToReport: TYPE = Log.WhereToReport;
WhereProc: TYPE = Log.WhereProc;
Reporting and Suspending
WP: TYPE = REF WPRec;
WPRec: TYPE = RECORD [
proc: WhereProc,
fixedWhereData: REF,
defaultIfNotFound: Log.DNFProc←NIL
];
RegisterWhereToReport: PUBLIC PROC[
proc: WhereProc, where: WhereToReport, fixedWhereData: REF,
defaultIfNotFound: Log.DNFProc] = {
Atom.PutProp[$ReportStreams, where, NEW[WPRec←[proc: proc, fixedWhereData: fixedWhereData, defaultIfNotFound: defaultIfNotFound]]];
};
FindWhere: PUBLIC PROC[where: WhereToReport, whereData: REF] RETURNS [s: IO.STREAM] = {
wp: WP;
IF where=NIL THEN RETURN[pd.sysOut];
wp ← NARROW[Atom.GetProp[$ReportStreams, where]];
IF wp=NIL THEN RETURN[pd.sysOut];
s←wp.proc[wp.fixedWhereData, whereData];
IF s#NIL THEN RETURN[s];
RETURN[IF s#NIL THEN s ELSE IF wp.defaultIfNotFound=NIL OR wp.defaultIfNotFound[where, whereData] THEN pd.sysOut ELSE NIL];
};
Report: PUBLIC PROC[remark: ROPE, where: WhereToReport, whereData: REFNIL] = {
reportS: STREAM ← FindWhere[where, whereData];
IF remark=NIL OR reportS = NIL THEN RETURN;
reportS.PutF["%t %s\n", time[], rope[remark]]; -- wish I could affort looking up caller.
};
Problem: PUBLIC PROC[
remark: ROPE, where: WhereToReport, whereData: REF] = TRUSTED {
IF remark=NIL THEN remark←"Unspecified problem";
Report[remark, where, whereData];
IF pd.attended THEN AMEvents.CallDebugger[remark];
};
ProblemBool: PUBLIC PROC[
remark: ROPE, where: WhereToReport, bool: BOOL, whereData: REF]
RETURNS[sameBool: BOOL] = {
sameBool𡤋ool;
Problem[remark, where, whereData];
};
ProblemHandle: PUBLIC PROC[ remark: ROPE, where: WhereToReport,
handle: ThHandle, whereData: REF]
RETURNS[sameHandle: ThHandle] = {
sameHandle←handle;
Problem[remark, where, whereData];
};
CmdWhere: WhereProc = {
pl: Atom.PropList ← ProcessProps.GetPropList[];
ch: Commander.Handle;
IF pl=NIL THEN RETURN[NIL];
ch ← NARROW[Commander.GetProperty[$CommanderHandle, pl]];
IF ch=NIL THEN RETURN[NIL];
RETURN[ch.err];
};
SetAttended: Commander.CommandProc = {
pd.attended ← TRUE;
Report["Attended[TRUE]", $Cmd, NIL];
};
ClearAttended: Commander.CommandProc = {
pd.attended ← FALSE;
Report["Attended[FALSE]", $Cmd, NIL];
};
Procedures for performance monitoring and debugging
loggingGroups: PUBLIC CARDINAL𡤀
WriteData: PUBLIC PROC[info: Log.LogInfo] = TRUSTED {
SpyLog.WriteData[CODE[Log.LogInfo], SIZE[Log.LogInfo], LONG[@info]]; };
};
DoLog: PUBLIC PROC[groups: CARDINAL�] = {
loggingGroups← IF PrincOpsUtils.IsBound[SpyLog.WriteTrace] THEN groups ELSE 0; };
Noop: PUBLIC PROC = {NULL};
Command Logging, indirect execution.
Originally developed as part of ThMessageDBImpl
CLog: TYPE = Log.CLog;
MakeCLog: PUBLIC PROC[fileName: ROPE, CommandProc: PROC[CLog]←NIL]
RETURNS[cLog: CLog←NIL] = {
logStream: IO.STREAM;
logStream ← FS.StreamOpen[fileName: fileName, accessOptions: $append!
FS.Error => logStream←NIL];
IF logStream=NIL THEN RETURN[NIL];
cLog←NEW[Log.CLogBody←[logStream: logStream, CommandProc: CommandProc]];
logStream.SetIndex[0];
};
WriteCLog: PUBLIC ENTRY PROC[cLog: CLog, entry: ROPE] = {
WriteLog[cLog, entry];
};
WriteLog: INTERNAL PROC[cLog: CLog, entry: ROPE] = {
cLog.logStream.SetIndex[cLog.logReadPos𡤌Log.logStream.GetLength[]];
cLog.logStream.PutRope[entry];
cLog.logStream.Flush[];
};
DoCLog: PUBLIC ENTRY PROC[cLog: CLog, entry: ROPE] = {
WriteLog[cLog, entry];
cLog.logStream.SetIndex[cLog.logReadPos];
cLog.CommandProc[cLog];
};
RedoCLog: PUBLIC ENTRY PROC[cLog: CLog] = {
cLog.logStream.SetIndex[cLog.logReadPos𡤀];
UNTIL IO.EndOf[cLog.logStream] DO cLog.CommandProc[cLog]; ENDLOOP;
};
Initialization
pd.ch ← NARROW[Commander.GetProperty[$CommanderHandle, ProcessProps.GetPropList[]]];
IF pd.ch#NIL THEN { pd.sysIn ← pd.ch.in; pd.sysOut ← pd.ch.out; };
RegisterWhereToReport[CmdWhere, $Cmd, NIL, NIL];
Commander.Register["Attended", SetAttended, "Break on errors"];
Commander.Register["Unattended", ClearAttended, "Log on errors, then muddle on."];
}.