RemoteAlgebraImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Christian Le Cocq April 29, 1987 5:58:45 pm PDT
Last Edited by: Ross March 20, 1987 5:23:14 pm PST
Arnon May 13, 1987 8:21:50 am PDT
See:
[cyan]<DATools7.0>EcadOps>EcadOps.mesa
[cyan]<DATools7.0>EcadOps>EcadOpsImpl.mesa
[Cyan]<DATools7.0>SpiceOps>SpiceCDCmds.mesa
DIRECTORY
Ascii,
BridgeFTPOps USING [StoreFile, RetrieveFile],
BridgeSubmit USING [TransferProc, Register],
BridgeDriver,
CedarProcess,
Commander,
RemoteAlgebra,
FS,
FSExtras,
FSBackdoor,
IO,
Rope,
SymTab USING [Ref, Create, Fetch, Store, Delete],
TerminalIO,
UserCredentials,
TiogaMenuOps,
ThisMachine;
RemoteAlgebraImpl: CEDAR MONITOR
IMPORTS Ascii, BridgeDriver, CedarProcess, Commander, FS, FSBackdoor, IO, Rope, UserCredentials, TiogaMenuOps, ThisMachine
IMPORTS Ascii, BridgeDriver, CedarProcess, FS, FSExtras, FSBackdoor, IO, Rope, UserCredentials, ThisMachine, BridgeFTPOps, BridgeSubmit, SymTab, TerminalIO
EXPORTS RemoteAlgebra
~ BEGIN
ROPE: TYPE = Rope.ROPE;
waitingProcess: CedarProcess.Process;
stop: BOOLFALSE;
criterion: ROPE ← "*.SUM!*";
globalOutputStream: IO.STREAM;
lock: BOOLEANFALSE;
Command Procs
AlgebraCmd: Commander.CommandProc ~ {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: ROPENIL]
fullCIFFName, fullRulesFName, cellName: ROPE;
fileName: ROPENIL;
ropeStream: IO.STREAMIO.RIS[cmd.commandLine];
IF lock THEN {
msg ← "\nWait for the previous Remote Algebra to finish !\nJob not sent.\n";
RETURN;
};
lock ← TRUE;
fileName ← FSExpandFromStream[ropeStream];
fullRulesFName ← FSExpandFromStream[ropeStream];
cellName ← IO.GetTokenRope[ropeStream, IO.IDProc ! IO.EndOfStream => CONTINUE].token;
msg ← ExecuteRemoteAlgebra[fileName];
IF msg#NIL THEN lock ← FALSE; -- n.b. releases the lock if error from BridgeDriver.StartSession
};
ExecuteRemoteAlgebra: PUBLIC PROC [fileName: ROPE] RETURNS [errmsg: ROPE] ~ {
name, password, machine, algebraCmd, CIFFName, RulesFName: ROPE;
magicString: ROPE ← "RBatch\ncd /user/csl/arnon; csh .login; cd /user/csl/arnon/Sturgis; /user/csl/arnon/Sturgis/algebra ";
name, password, machine, algebraCmd: ROPE;
[name, password] ← UserCredentials.Get[];
name ← Rope.Substr[name, 0, Rope.Index[name, 0, "."]]; -- get rid of the ".pa"
name ← Rope.Translate[base: name, translator: MyLower];
machine ← Rope.Cat[ThisMachine.Name[], " "];
CIFFName ← PrepareFFName[fullCIFFName];
RulesFName ← PrepareFFName[fullRulesFName];
algebraCmd ← Rope.Cat[magicString, machine, CIFFName, RulesFName, cellName];
algebraCmd ← Rope.Cat[magicString, machine, PrepareFFName[fileName] ];
errmsg ← BridgeDriver.StartSession["vaxc", name, password, algebraCmd];
};
SAC2PolynomialBinaryOp: PUBLIC PROC [varSeq, firstArg, secondArg: ROPE] RETURNS [result: IO.STREAM] ~ {
errmsg: ROPE;
name, password, machine, algebraCmd: ROPE;
magicString: ROPE ← "RBatch\ncd /user/csl/arnon; csh .login; cd /user/csl/arnon/INTRPTR; /user/csl/arnon/INTRPTR/RunInterpreter ";
intialScript: ROPE ← "V \n #v \n E \n #1 $ \n E \n #2 $ \n G 1 2 \n W \n L 3 \n \n H \n Q \n";
fileName: ROPE ← "SacPolyBinaryOp.inData";
out: IO.STREAMFS.StreamOpen[fileName: fileName, accessOptions: $create,wDir: FSExtras.GetWDir[] ]; -- also could use CommandTool.FileNames interface; in any event, FSExtras.GetWDir seems to just be returning /// as WD, i.e. trivial effect. Probably result of call not coming from a Commander.CommandProc
fullFName: ROPEFS.ExpandName[fileName].fullFName;
finalScript: ROPE ← intialScript;
position: INT ← -1;
position ← Rope.Find[finalScript, "#v"];
finalScript ← Rope.Replace[base: finalScript, start: position, len: Rope.Length["#v"], with: varSeq];
position ← Rope.Find[finalScript, "#1"];
finalScript ← Rope.Replace[base: finalScript, start: position, len: Rope.Length["#1"], with: firstArg];
position ← Rope.Find[finalScript, "#2"];
finalScript ← Rope.Replace[base: finalScript, start: position, len: Rope.Length["#2"], with: secondArg];
out.PutRope[finalScript];
out.Close[];
[name, password] ← UserCredentials.Get[];
name ← Rope.Substr[name, 0, Rope.Index[name, 0, "."]]; -- get rid of the ".pa"
name ← Rope.Translate[base: name, translator: MyLower];
machine ← Rope.Cat[ThisMachine.Name[], " "];
fullFName ← StripExtension[fullFName, ".inData"];
algebraCmd ← Rope.Cat[magicString, machine, PrepareFFName[fullFName] ];
UNTIL lock=FALSE DO ENDLOOP; -- wait until previous request finishes
lock ← TRUE;
errmsg ← BridgeDriver.StartSession["vaxc", name, password, algebraCmd];
IF errmsg#NIL THEN {
lock ← FALSE; -- n.b. releases the lock if error from BridgeDriver.StartSession
RETURN[NIL];
};
UNTIL lock=FALSE DO ENDLOOP; -- wait
RETURN[globalOutputStream];
};
MyLower: Rope.TranslatorType ~ {RETURN[Ascii.Lower[old]]};
StartWatching: PUBLIC PROC ~ {
IF waitingProcess=NIL OR CedarProcess.GetStatus[waitingProcess]#busy THEN
waitingProcess ← CedarProcess.Fork[WaitForListings, criterion];
};
Internal Utilities
FSExpandFromStream: PROC [s: IO.STREAM] RETURNS [fullFName: ROPE] ~ {
fName: ROPE;
index: INT;
fName ← IO.GetTokenRope[s, IO.IDProc ! IO.EndOfStream => CONTINUE].token;
index ← Rope.Find[fName, ".inData", 0, FALSE];
IF index#-1 THEN fName ← Rope.Substr[fName, 0, index]; -- toss ".inData" if present
fullFName ← FS.ExpandName[fName].fullFName;
};
StripExtension: PROC [inName: ROPE, extension: ROPE] RETURNS [fName: ROPE] ~ {
index: INT;
index ← Rope.Find[inName, extension, 0, FALSE];
IF index#-1 THEN fName ← Rope.Substr[inName, 0, index]; -- toss extension if present
fullFName ← FS.ExpandName[fName].fullFName;
};
PrepareFFName: PROC [fullFName: ROPE] RETURNS [arg: ROPE] ~ {
arg ← Rope.Cat["\"", fullFName, "\" "];
};
WaitForListings: CedarProcess.ForkableProc ~ {
PROC [data: REF] RETURNS [results: REFNIL]
matchCriterion: ROPENARROW[data];
event: REF READONLY FSBackdoor.CreateEvent ← NIL;
UNTIL stop DO
event ← FSBackdoor.NextCreateEvent[event];
IF Rope.Match[pattern: matchCriterion, object: event.fName, case: FALSE] THEN {
viewer: TiogaMenuOps.Viewer ← TiogaMenuOps.Open[event.fName];
lock ← FALSE;
};
IF Rope.Match[pattern: matchCriterion, object: event.fName, case: FALSE] THEN {
globalOutputStream ← FS.StreamOpen[event.fName, $read];
lock ← FALSE;
};
ENDLOOP;
};
New Stuff
msgStream: IO.STREAM ← TerminalIO.TOS[];
keyTable: SymTab.Ref ← SymTab.Create[];
Key: TYPE = REF KeyRec;
KeyRec: TYPE = RECORD [
msg: ROPE,
locked: BOOLTRUE,
unlocked: CONDITION
];
Waiting: PUBLIC ERROR = CODE;
SAC2PolynomialBinaryOp: PUBLIC PROC [varSeq, firstArg, secondArg: ROPE] RETURNS [result: IO.STREAM] ~ {
errmsg: ROPE;
intialScript: ROPE ← RopeFromFile["SACScript"];
fileName: ROPE ← "SACIn";
outputFileName: ROPE;
out: IO.STREAMFS.StreamOpen[fileName: fileName, accessOptions: $create, wDir: FSExtras.GetWDir[] ]; -- also could use CommandTool.FileNames interface; in any event, FSExtras.GetWDir seems to just be returning /// as WD, i.e. trivial effect. Probably result of call not coming from a Commander.CommandProc
finalScript: ROPE ← intialScript;
position: INT ← -1;
position ← Rope.Find[finalScript, "#v"];
finalScript ← Rope.Replace[base: finalScript, start: position, len: Rope.Length["#v"], with: varSeq];
position ← Rope.Find[finalScript, "#1"];
finalScript ← Rope.Replace[base: finalScript, start: position, len: Rope.Length["#1"], with: firstArg];
position ← Rope.Find[finalScript, "#2"];
finalScript ← Rope.Replace[base: finalScript, start: position, len: Rope.Length["#2"], with: secondArg];
out.PutRope[finalScript];
out.Close[];
[outputFileName, errmsg] ← DoRemoteAlgebra["SAC"];
IF errmsg#NIL THEN ERROR Waiting;
globalOutputStream ← FS.StreamOpen[outputFileName, $read];
RETURN[globalOutputStream];
};
Store: BridgeSubmit.TransferProc ~ {
PROC [id, wDir: ROPE, s: IO.STREAM] RETURNS [msg: ROPE]
localName : ROPE ← Rope.Cat[wDir, id, "In"];
remoteDir: ROPE ← RopeFromFile[Rope.Cat[id, "Directory"] ];
remoteName: ROPE ← Rope.Cat[remoteDir, id, "In"];
msg ← BridgeFTPOps.StoreFile[s, remoteName, localName, msgStream];
IF msg#NIL THEN { OK[id, msg]; RETURN[msg]};
};
Retrieve: BridgeSubmit.TransferProc ~ {
PROC [id, wDir: ROPE, s: IO.STREAM] RETURNS [msg: ROPE]
localName : ROPE ← Rope.Cat[wDir, id, "Out"];
remoteDir: ROPE ← RopeFromFile[Rope.Cat[id, "Directory"] ];
remoteName: ROPE ← Rope.Cat[remoteDir, id, "Out"];
msg ← BridgeFTPOps.RetrieveFile[s, remoteName, localName, msgStream];
IF msg#NIL THEN { OK[id, msg]; RETURN[msg]};
OK[id, NIL];
};
RopeFromFile: PROC [filename: ROPE] RETURNS [ROPE] ~ {
stream: IO.STREAMFS.StreamOpen[filename, $read];
rope: ROPE ← "";
c: CHAR ← stream.GetChar[]; -- toss first newline
WHILE NOT stream.EndOf[] DO
c ← stream.GetChar[];
IF ~stream.EndOf[] THEN rope ← rope.Cat[Rope.FromChar[c] ]; ENDLOOP; -- toss last newline
RETURN[rope];
};
DoRemoteAlgebra: PUBLIC PROC [id: ROPE, waitUntilDone: BOOLEANTRUE] RETURNS [outputFileName: ROPE, msg: ROPE] ~ {
id is expected to be flavorRope, e.g. "Reduce", "SAC", "SMP"
line: ROPE ← RopeFromFile[Rope.Cat[id, "Line"] ];
wDir: ROPE ← FSExtras.GetWDir[];
key: Key ← GetKey[id];
outputFileName ← Rope.Cat[wDir, id, "Out"];
IF key=NIL THEN RETURN[outputFileName, Rope.Cat["Remotealgebra -> The rope: '", id, "' is already in use"]];
msg ← BridgeSubmit.Register[id, line, wDir, Store, Retrieve];
IF msg=NIL AND waitUntilDone THEN msg ← WaitForOk[key];
RETURN[outputFileName, msg];
};
GetKey: PROC [id: ROPE] RETURNS[key: Key] ~ {
IF SymTab.Fetch[keyTable, id].found THEN RETURN [NIL];
key ← NEW[KeyRec];
[] ← SymTab.Store[keyTable, id, key];
};
WaitForOk: ENTRY PROC [key: Key] RETURNS [msg: ROPE] ~ {
ENABLE UNWIND => NULL;
WHILE key.locked DO WAIT key.unlocked ENDLOOP;
RETURN [key.msg];
};
OK: PROC [id, msg: ROPE] ~ {
key: Key ← NARROW[SymTab.Fetch[keyTable, id].val];
IF key=NIL THEN RETURN;
[] ← SymTab.Delete[keyTable, id];
key.msg ← msg;
Unlock[key];
};
Unlock: ENTRY PROC [key: Key] ~ {
ENABLE UNWIND => NULL;
key.locked ← FALSE;
BROADCAST key.unlocked;
};
Initialization
Commander.Register[key: "RemoteAlgebra", proc: AlgebraCmd, doc: "RemoteAlgebra CIFfileName rulesFileName TopLevelCellName\nSends CIF to Dracula"];
Commander.Register[key: "RemoteAlgebra", proc: AlgebraCmd, doc: "RemoteAlgebra dataFile\nSends Algebra to Vax"];
StartWatching[];
TerminalIO.PutRope["Begin TerminalIO\n"];
END.