MakeDoReportOnFiles.Mesa
Copyright Ó 1991 by Xerox Corporation. All rights reserved.
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
Willie-s, September 27, 1991 4:44 pm PDT
Michael Plass, September 30, 1991 12:51 pm PDT
DIRECTORY
CedarProcess USING [Process],
Commander USING [CommandObject, Handle],
FS USING [ComponentPositions, Error, ExpandName, StreamOpen],
IO USING [Close, noInputStream, noWhereStream, PutF, PutFL, PutFR, PutRope, STREAM, Value],
IOClasses USING [CreateDribbleOutputStream],
List USING [AList, Assoc, DotCons, 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],
MoreIOClasses USING [CreateBuffer, SendBuffer],
Process USING [Abort, InvalidProcess],
RefTab USING [Delete],
Rope,
SimpleFeedback USING [Append];
MakeDoReportOnFiles: CEDAR MONITOR
IMPORTS FS, IO, IOClasses, List, MakeDo, MakeDoBasics, MakeDoPrivate, MoreIOClasses, Process, RefTab, Rope, SimpleFeedback
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: 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, 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;
};
CopyAList: PUBLIC PROC [old: List.AList] RETURNS [new: List.AList] ~ {
CopyAList copies the CONS cells of the list itself and also copies the DotCons cells which are the elements of the list. Because the DotCons cells are copied, one can change the key-value mappings in the new list without affecting the mappings in the old list. Because the CONS cells are copied, one can alter the list without affecting the old list.
tail: List.AList ¬ NIL;
new ¬ NIL;
UNTIL old = NIL DO
newItem: List.AList ¬ LIST[List.DotCons[key: old.first.key, val: old.first.val]];
IF tail = NIL THEN new ¬ newItem ELSE tail.rest ¬ newItem;
old ¬ old.rest;
tail ¬ newItem;
ENDLOOP;
ERROR CommanderOps.Failed["CommandTool.CopyAList is deimplemented"];
};
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];
SimpleFeedback.Append[$MakeDo, oneLiner, $info, "command execution abandoned"];
}
ELSE SimpleFeedback.Append[$MakeDo, oneLiner, $info, "command execution already finishing"];
}};
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!)";
SimpleFeedback.Append[$MakeDo, oneLiner, $info, message];
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.PutFL[format, LIST[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.