MakeDoReportOnFiles.Mesa
Last tweaked by Mike Spreitzer on April 26, 1990 9:57:00 am PDT
Carl Hauser, April 11, 1985 3:43:34 pm PST
Eduardo Pelegri-Llopart March 20, 1989 9:51:55 am PST
JKF January 11, 1989 10:32:27 am PST
DIRECTORY
CedarProcess USING [Process],
Commander USING [CommandObject, Handle],
CommandTool USING [CopyAList],
FS USING [ComponentPositions, Error, ExpandName, StreamOpen],
IO USING [Close, noInputStream, noWhereStream, PutF, PutFR, PutRope, STREAM, Value],
IOClasses USING [CreateDribbleOutputStream],
List USING [Assoc, PutAssoc],
MakeDo USING [ActionRep, EnumerateResults, NodeClassRep, NodeRep, PublicPartsOfNode, UncurrentProducer],
MakeDoBasics USING [CheckIn, EndFork, Execution, InnerSuspectNodeChange, NeedToFinish, RegisterReporter, Reporter, ReporterRep, SetES],
MakeDoPrivate USING [ActionRep, AddFailedCmd, NodeClassRep, NodeRep],
MessageWindow USING [Append],
MoreIOClasses USING [CreateBuffer, SendBuffer],
Process USING [Abort, InvalidProcess],
RefTab USING [Delete],
Rope;
MakeDoReportOnFiles: CEDAR MONITOR
IMPORTS CommandTool, FS, IO, IOClasses, List, MakeDo, MakeDoBasics, MakeDoPrivate, MessageWindow, MoreIOClasses, Process, RefTab, Rope
EXPORTS MakeDo, MakeDoBasics
EXPORTS MakeDo
INVARIANT
The integrity of the aux box data structure.
=
BEGIN OPEN MakeDo, MakeDoPrivate, MakeDoBasics;
ROPE: TYPE = Rope.ROPE;
NodeRep: PUBLIC TYPE = MakeDoPrivate.NodeRep;
ActionRep: PUBLIC TYPE = MakeDoPrivate.ActionRep;
NodeClassRep: PUBLIC TYPE = MakeDoPrivate.NodeClassRep;
Viewer Manipulation
reporterOnFiles: MakeDoBasics.Reporter ~ NEW [MakeDoBasics.ReporterRep ← [
destroyAuxBox: DestroyAuxBox,
auxBoxDestroyed: AuxBoxDestroyed,
buffer: Buffer,
msg: Msg,
flush: Flush
]];
AuxBox: TYPE ~ LIST OF FileExecutionViewer;
auxBox: AuxBox ← NIL;
FileExecutionViewer: TYPE ~ REF FileExecutionViewerRep;
FileExecutionViewerRep: TYPE ~ RECORD [
logFileName: ROPE,
logStream: IO.STREAM
];
bufKey: ATOM = $MakeDoBuffer;
logFilePrefix: ROPE ← ".makeLog.";
auxBoxOccupancy: INT ← 0;
monitor: BOOLFALSE;
DestroyAuxBox: -- PUBLIC -- PROC ~ {
FOR auxRest: AuxBox ← auxBox, auxRest.rest WHILE auxRest # NIL DO
exView: FileExecutionViewer ~ auxRest.first;
exView.logStream.Close[];
ENDLOOP;
auxBox ← NIL;
};
AuxBoxDestroyed: -- PUBLIC -- PROC RETURNS [BOOLTRUE] ~ {
RETURN [auxBox = NIL];
};
Buffer: -- PUBLIC -- ENTRY PROC [e: Execution] = {
ENABLE UNWIND => NULL;
InnerBuffer[e];
RETURN};
InnerBuffer: INTERNAL PROC [e: Execution] = {--structure contorted to avoid Cirio blind spots
ch: Commander.Handle ~ e.ch;
bufout: IO.STREAM = MoreIOClasses.CreateBuffer[];
gname, verless, logFileName, fmterr: ROPE;
logStream: IO.STREAM;
IF AuxBoxDestroyed[] THEN {
auxBoxOccupancy ← 0;
};
auxBoxOccupancy ← auxBoxOccupancy + 1;
e.bch ← NEW [Commander.CommandObject ← [
commandLine: "Shouldn't care",
propertyList: List.PutAssoc[bufKey, bufout, CommandTool.CopyAList[ch.propertyList]]
]];
gname ← MakeDo.PublicPartsOfNode[e.goal].name;
{lgname: ROPE ~ gname;
fullName: ROPE;
cp: FS.ComponentPositions;
[fullName, cp, ] ← FS.ExpandName[lgname !FS.Error => GOTO Genit];
verless ← Rope.Substr[base: fullName, start: 0, len: cp.ext.start+cp.ext.length];
logFileName ← Rope.Replace[verless, cp.base.start, 0, logFilePrefix];
EXITS Genit => {
logFileName ← IO.PutFR["%gAction%g", [rope[logFilePrefix]], [integer[actionCount ← actionCount.SUCC]]];
ch.err.PutF["Log for making %g going to %g\n", [rope[gname]], [rope[logFileName]] ]};
};
e.bch.in ← IO.noInputStream;
{llogFileName: ROPE ~ logFileName;
llogStream: IO.STREAM;
llogStream ← FS.StreamOpen[fileName: llogFileName, accessOptions: create !FS.Error => {
fmterr ← IO.PutFR["FS.Error[%g, %g]", [atom[error.code]], [rope[error.explanation]] ];
GOTO Complain}];
logStream ← llogStream;
EXITS Complain => {
ch.err.PutF["%g when trying to create command log %g; output will not be logged.\n", [rope[fmterr]], [rope[logFileName]] ];
logStream ← IO.noWhereStream}
};
{exView: FileExecutionViewer ~ NEW [FileExecutionViewerRep ← [logFileName: logFileName, logStream: logStream]];
this: LIST OF FileExecutionViewer ~ LIST[exView];
e.view ← exView;
IF auxBox = NIL
THEN auxBox ← this
ELSE { this.rest ← auxBox; auxBox ← this };
};
e.bch.err ← e.bch.out ← IOClasses.CreateDribbleOutputStream[bufout, logStream];
e.es ← buffered;
};
actionCount: INT ← 0;
Abandonit: PROC [e: Execution] ~ {
{OPEN e;
IF NeedToFinish[e] THEN {
ENABLE UNWIND => {
EndFork[e.resources];
Flush[e, TRUE, TRUE, a.cmd];
[] ← job.processes.Delete[process];
};
IF forked THEN Flush[e, TRUE, TRUE, a.cmd];
a.fails ← true;
AddFailedCmd[job, a];
EnumerateResults[a, InnerSuspectNodeChange];
CheckIn[job, goal, a, e.process];
SetES[e, final];
UncurrentProducer[goal];
MessageWindow.Append[message: "command execution abandoned", clearFirst: TRUE];
}
ELSE MessageWindow.Append[message: "command execution already finishing", clearFirst: TRUE];
}};
Stopit: PROC [e: Execution] = {
message: ROPE ← "command execution ABORTed";
IF e.process # NIL AND e.process.status = busy
THEN TRUSTED {Process.Abort[e.process.process !Process.InvalidProcess => {
message ←
IF process#e.process.process THEN "Zowie! Bug 6 encountered!"
ELSE IF e.process.status=busy THEN "Wow! CedarProcess bug observed!"
ELSE "Already gone!";
CONTINUE;
}]}
ELSE message ← IF e.process = NIL
THEN "Can't ABORT because it's not gotten started yet"
ELSE SELECT e.process.status FROM
done => "Can't ABORT because it's already done",
aborted => "Can't ABORT because it's already ABORTED",
debugging => "Won't ABORT because it's being debugged",
busy => "Wouldn't ABORT because it was not busy a few microseconds ago",
invalid => "Won't ABORT because it's invalid",
ENDCASE => "Won't ABORT because status unrecognized (I'm suffering software rot!)";
MessageWindow.Append[message: message, clearFirst: TRUE];
RETURN};
Gushit: PROC [e: Execution] = {
e.gushMe ← TRUE;
};
Msg: -- PUBLIC -- ENTRY PROC [ch: Commander.Handle, format: ROPE, v1, v2, v3, v4, v5: IO.Value ← [null[]]] = {
ENABLE UNWIND => NULL;
ch.out.PutF[format, v1, v2, v3, v4, v5];
};
Flush: --PUBLIC-- ENTRY PROC [e: Execution, long, abandon: BOOL, asRope: ROPE] = {
ENABLE UNWIND => NULL;
exView: FileExecutionViewer ~ NARROW[e.view];
bch: Commander.Handle ~ e.bch;
ch: Commander.Handle ~ e.ch;
buffer: IO.STREAM = NARROW[List.Assoc[bufKey, bch.propertyList]];
last: LIST OF FileExecutionViewer ← NIL;
IF abandon THEN {
ch.out.PutF["%lAbandoning %g%l\n", [rope["be"]], [rope[asRope]], [rope["BE"]]];
MoreIOClasses.SendBuffer[buffer, ch.out, FALSE];
ch.out.PutRope["\n"];
}
ELSE IF long THEN MoreIOClasses.SendBuffer[buffer, ch.out, TRUE]
ELSE ch.out.PutF["%lDone with %g%l\n", [rope["e"]], [rope[asRope]], [rope["E"]]];
IF AuxBoxDestroyed[] THEN {
auxBoxOccupancy ← 0;
}
ELSE FOR cur: LIST OF FileExecutionViewer ← auxBox, cur.rest WHILE cur # NIL DO
IF cur.first = exView THEN {
IF last # NIL THEN last.rest ← cur.rest ELSE auxBox ← cur.rest;
cur.first.logStream.Close[];
auxBoxOccupancy ← auxBoxOccupancy - 1;
EXIT;
};
last ← cur;
ENDLOOP;
};
MakeDoBasics.RegisterReporter[$FILES, reporterOnFiles];
END.