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.
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: BOOL ← FALSE;
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 [
BOOL ←
TRUE] ~ {
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];