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: BOOL ← FALSE;
criterion: ROPE ← "*.SUM!*";
globalOutputStream: IO.STREAM;
lock: BOOLEAN ← FALSE;
Command Procs
AlgebraCmd: Commander.CommandProc ~ {
PROC [cmd: Handle] RETURNS [result: REF ← NIL, msg: ROPE ← NIL]
fullCIFFName, fullRulesFName, cellName: ROPE;
fileName: ROPE ← NIL;
ropeStream: IO.STREAM ← IO.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.STREAM ← FS.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: ROPE ← FS.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: REF ← NIL]
matchCriterion: ROPE ← NARROW[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: BOOL ← TRUE,
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.STREAM ← FS.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.STREAM ← FS.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];
};
host:
ROPE ← "parcvax:parc:xerox";
DoRemoteAlgebra:
PUBLIC
PROC [id:
ROPE, waitUntilDone:
BOOLEAN ←
TRUE]
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[host, id, line, wDir, Store, Retrieve, "~", NIL, NIL];
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;
};