TSRemoteFormatImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bob Hagmann, November 22, 1985 7:49:20 am PST
Rick Beach, June 3, 1985 2:48:04 pm PDT
DIRECTORY
Commander USING [CommandObject, Handle],
CommandTool USING [CurrentWorkingDirectory, Run],
ComputeServerClient USING [RemoteSuccess, StartService],
ComputeServerServer USING [Lookup, RegisteredProcHandle],
Convert USING [Error, RealFromRope],
IO USING [CreateStream, CreateStreamProcs, EndOfStream, STREAM, StreamProcs],
PieViewers USING [Set],
Process USING [InitializeCondition, SecondsToTicks],
PseudoCursors USING [Set],
Rope USING [Cat, Concat, Fetch, FromChar, IsEmpty, Length, ROPE, Substr],
TSFormat USING [],
TSViewer USING [Tool],
ViewerTools USING [SetContents];
TSRemoteFormatImpl: CEDAR MONITOR
IMPORTS CommandTool, ComputeServerClient, ComputeServerServer, Convert, IO, PieViewers, Process, PseudoCursors, Rope, ViewerTools
EXPORTS TSFormat
= BEGIN OPEN TSViewer;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
outBufStreamData: TYPE = REF outBufStreamDataObject;
ThirtyTwoChars: TYPE = PACKED ARRAY [0..32) OF CHAR;
outBufStreamDataObject: TYPE = RECORD [
token: ROPENIL,
bits: REF ThirtyTwoChars ← NEW[ThirtyTwoChars],
bitsIndex: INT ← 0,
tool: Tool ← NIL,
errMsg: ROPENIL,
eof: BOOLFALSE
];
inBufStreamData: TYPE = REF inBufStreamDataObject;
inBufStreamDataObject: TYPE = RECORD [
token: ROPENIL,
charsAvail: CONDITION,
eof: BOOLFALSE
];
inStreamProcs: REF IO.StreamProcs ← IO.CreateStreamProcs[
variety: $input,
class: $TSetterIn,
getChar: InBufGetChar,
charsAvail: InCharsAvail
];
outStreamProcs: REF IO.StreamProcs ← IO.CreateStreamProcs[
variety: $output,
class: $TSetterOut,
putChar: OutBufPutChar
];
OutBufPutChar: PROC [self: STREAM, char: CHAR] = {
data: outBufStreamData = NARROW[self.streamData];
IF data.token # NIL AND data.token.Fetch[0] = 'b THEN {
data.bits[data.bitsIndex] ← char;
data.bitsIndex ← data.bitsIndex + 1;
IF data.bitsIndex = 32 THEN TRUSTED {
PseudoCursors.Set[data.tool.miniDisplay, LOOPHOLE[data.bits]];
data.token ← NIL;
data.bitsIndex ← 0;
};
}
ELSE {
IF char # '$ THEN data.token ← data.token.Concat[Rope.FromChar[char]]
ELSE {
IF ~data.token.IsEmpty[] THEN {
SELECT data.token.Fetch[0] FROM
'c => {
PseudoCursors.Set[data.tool.miniDisplay, NIL];
};
'p => {
realRope: ROPE = data.token.Substr[1];
pieSize: REAL ← 0.0;
pieSize ← Convert.RealFromRope[realRope ! Convert.Error => CONTINUE;];
PieViewers.Set[data.tool.pie, 100.0-pieSize];
};
'm => {
msg: ROPE = data.token.Substr[1];
ShowMessage[data.tool, msg];
};
'e => {
data.errMsg ← data.token;
};
ENDCASE;
};
data.token ← NIL;
};
};
};
InCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT] = {
data: inBufStreamData = NARROW[self.streamData];
RETURN[data.token.Length[]];
};
InBufGetChar: ENTRY PROC [self: STREAM] RETURNS [ch: CHAR] = {
ENABLE UNWIND => NULL;
data: inBufStreamData = NARROW[self.streamData];
WHILE data.token.Length[] <= 0 AND ~ data.eof DO WAIT data.charsAvail ENDLOOP;
IF data.eof THEN ERROR IO.EndOfStream[self];
ch ← data.token.Fetch[0];
data.token ← data.token.Substr[1];
};
BufferInChar: INTERNAL PROC [data: inBufStreamData, ch: CHAR] = {
ENABLE UNWIND => NULL;
data.token ← data.token.Concat[Rope.FromChar[ch]];
NOTIFY data.charsAvail;
};
ShowMessage: PROCEDURE [tool: Tool, msg: ROPE] = {
tool.messageLog ← msg ← tool.messageLog.Cat["\n", msg];
ViewerTools.SetContents[tool.messageBox, msg];
[] ← tool.messageBox.class.scroll[tool.messageBox, thumb, 100];
};
FormatOneOutputFile: PUBLIC PROCEDURE [tool: Tool, names: LIST OF ROPE] = {
found: BOOL;
success: ComputeServerClient.RemoteSuccess;
remoteMsg: ROPENIL;
msg: ROPENIL;
nameList: ROPENIL;
inStream: IO.STREAMNIL;
inData: inBufStreamData;
outData: outBufStreamData;
outStream: IO.STREAMNIL;
stopProcess: PROCESS;
tryRemote: BOOL ← tool.remoteState # localOnly;
finished: BOOLFALSE;
retries: INT ← 0;
FOR n:LIST OF ROPE ← names, n.rest UNTIL n = NIL DO
IF nameList = NIL THEN nameList ← n.first
ELSE nameList ← Rope.Cat[nameList, " ", n.first];
ENDLOOP;
IF tool.tempPress THEN nameList ← Rope.Concat["-t ", nameList];
inStream ← IO.CreateStream[streamProcs: inStreamProcs,
streamData: inData ← NEW[inBufStreamDataObject ← []]];
outStream ← IO.CreateStream[streamProcs: outStreamProcs,
streamData: outData ← NEW[outBufStreamDataObject ← [tool: tool]]];
stopProcess ← FORK StopProcess[inData, outData, tool];
WHILE tryRemote AND ~finished AND retries < 4 DO
retries ← retries + 1;
IF tool.stop THEN EXIT;
inStream ← IO.CreateStream[streamProcs: inStreamProcs,
streamData: inData ← NEW[inBufStreamDataObject ← []]];
outStream ← IO.CreateStream[streamProcs: outStreamProcs,
streamData: outData ← NEW[outBufStreamDataObject ← [tool: tool]]];
stopProcess ← FORK StopProcess[inData, outData, tool];
[found: found, success: success, remoteMsg: remoteMsg] ← ComputeServerClient.StartService[service: "RemoteTSetter", cmdLine: nameList, in: inStream, out: outStream];
SELECT TRUE FROM
~found OR success = false OR success = cantImportController OR success = cantImportServer OR success = communicationFailure OR success = commandNotFound OR success = clientNotRunning => {
tryRemote ← FALSE;
};
success = aborted => {
tool.stop ← TRUE;
finished ← TRUE;
};
success = timeOut OR success = serverTooBusy => {
LOOP;
};
found AND success = true => {
finished ← TRUE;
};
ENDCASE;
SetDone[inData, outData];
TRUSTED {JOIN stopProcess;};
ENDLOOP;
IF ~tryRemote THEN {
lookupProcData: ComputeServerServer.RegisteredProcHandle;
errMsg: ROPENIL;
runError: BOOLFALSE;
IF tool.remoteState = remoteOnly THEN {
ShowMessage[tool," Failed to perform remote TSet and remoteOnly is requested"];
}
ELSE {
lookupProcData ← ComputeServerServer.Lookup["RemoteTSetter", NIL];
IF lookupProcData = NIL THEN {
[errMsg: errMsg, error: runError] ← CommandTool.Run[bcdName: runDir.Concat["RemoteTSetter.bcd"], runEvenIfAlreadyRun: FALSE, runEvenIfUnbound: FALSE];
lookupProcData ← ComputeServerServer.Lookup["RemoteTSetter", NIL];
};
IF lookupProcData = NIL THEN {
ShowMessage[tool," Failed to start up RemoteTSetter.bcd on the workstation"];
}
ELSE {
result: REF ANY;
myCmd: Commander.Handle;
inStream ← IO.CreateStream[streamProcs: inStreamProcs,
streamData: inData ← NEW[inBufStreamDataObject ← []]];
outStream ← IO.CreateStream[streamProcs: outStreamProcs,
streamData: outData ← NEW[outBufStreamDataObject ← [tool: tool]]];
stopProcess ← FORK StopProcess[inData, outData, tool];
myCmd ← NEW[Commander.CommandObject ← [
in: inStream,
out: outStream,
err: outStream,
commandLine: nameList ,
command: "RemoteTSetter ",
propertyList: NIL,
procData: NIL
]];
[result: result, msg: remoteMsg] ← lookupProcData.commanderProcHandle.proc[myCmd ! ABORTED => CONTINUE;];
IF result = $Failure AND remoteMsg.IsEmpty[] THEN
remoteMsg ← "Failed to Run local TSetter";
SetDone[inData, outData];
TRUSTED {JOIN stopProcess;};
};
};
};
SetDone[inData, outData];
TRUSTED {JOIN stopProcess;};
IF remoteMsg # NIL THEN ShowMessage[tool, remoteMsg];
IF NOT tool.debug THEN msg ← tool.pressName ELSE msg ← NIL;
IF tool.stop THEN msg ← msg.Concat[" aborted"]
ELSE msg ← msg.Concat[" completed"];
ShowMessage[tool, msg];
};
SetDone: ENTRY PROC[ inData: inBufStreamData, outData: outBufStreamData] = {
ENABLE UNWIND => NULL;
inData.eof ← TRUE;
outData.eof ← TRUE;
NOTIFY inData.charsAvail;
};
StopProcess: PROC [ inData: inBufStreamData, outData: outBufStreamData, tool: Tool] = {
TRUSTED {Process.InitializeCondition[@inData.charsAvail, Process.SecondsToTicks[1]];};
StopInner[inData, outData, tool];
};
StopInner: ENTRY PROC [ inData: inBufStreamData, outData: outBufStreamData, tool: Tool] = {
ENABLE UNWIND => NULL;
sentStop: BOOLFALSE;
WHILE ~inData.eof DO
WAIT inData.charsAvail;
IF tool.stop AND ~sentStop THEN {
BufferInChar[inData, 's];
sentStop ← TRUE;
};
ENDLOOP;
};
runDir: ROPE ← CommandTool.CurrentWorkingDirectory[];
END.
Bob Hagmann May 20, 1985 12:45:44 pm PDT
created from TSVIewerImpl
Bob Hagmann August 7, 1985 9:09:52 am PDT
modified the stop code: added enable unwinds, and self deadlocks
changes to: InBufGetChar, BufferInChar, SetDone, StopProcess, StopInner, FormatOneOutputFile
Bob Hagmann November 21, 1985 4:57:05 pm PST
added processing for the local/remote options
changes to: FormatOneOutputFile