RetrieveStream:
PUBLIC
PROC [nsp: NetworkStreamPair, remoteName:
ROPE, action: ActionProc, clientData:
REF ¬
NIL, msgStream:
STREAM ¬
NIL]
RETURNS [excuse:
ROPE ¬
NIL]
~ {
ENABLE {
ABORTED => {
excuse ¬ "aborted";
CONTINUE };
BridgeComm.Error => {
PutMsg[msgStream, "Communication error: %g\n", msg];
excuse ¬ "Bridge communication error";
CONTINUE };
IO.Error, NetworkStream.Error => {
PutMsg[msgStream, "I/O error\n"];
excuse ¬ "I/O error";
CONTINUE };
};
ansMsg: CHAR;
ansArg: ROPE;
ansArgNumeric: CARD;
actionProcQuit: BOOL;
PutMsg[msgStream, "Retrieving from %g ... ", remoteName];
[ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'I, remoteName]; -- Open for input.
SELECT ansMsg
FROM
'Y => NULL; -- ansArg is really aaa.bbb where aaa is the iNode and bbb is the mtime
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; -- ansArg = error like not found
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
[ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'R]; -- Read current file
SELECT ansMsg
FROM
'D => NULL; -- ansArg is the number of bytes in the file as reported by stat
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; -- stat error
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
The following tries to work around host failure to send back-to-back EOM's reliably ...
ansArgNumeric ¬ Convert.CardFromRope[ansArg
-- really bytes in the file
! Convert.Error => ansArgNumeric ¬ CARD.LAST];
IF ansArgNumeric = 0
THEN {
Process.PauseMsec[500] -- Kludge -- ; actionProcQuit ¬ FALSE;
}
ELSE {
actionProcQuit ¬ action[nsp, ansArgNumeric, NIL]; -- send the bits. Should only get ansArgNumeric (byte count)
IF actionProcQuit THEN IO.Reset[nsp.in];
};
WHILE NetworkStream.GetStreamState[nsp.in, TRUE].streamState # open DO NULL ENDLOOP;
[] ¬ BridgeComm.PutMsgWithReply[nsp, 'i]; -- close the file
PutMsg[msgStream, IF actionProcQuit THEN "aborted\n" ELSE "ok\n"];
};
StoreStream:
PUBLIC
PROC [nsp: NetworkStreamPair, remoteName:
ROPE, overwrite:
BOOL, action: ActionProc, clientData:
REF ¬
NIL, msgStream:
STREAM ¬
NIL]
RETURNS [excuse:
ROPE ¬
NIL]
~ {
ENABLE {
ABORTED => {
excuse ¬ "aborted";
CONTINUE };
BridgeComm.Error => {
PutMsg[msgStream, "Communication error: %g\n", msg];
excuse ¬ "Bridge communication error";
CONTINUE };
IO.Error, NetworkStream.Error => {
PutMsg[msgStream, "I/O error\n"];
excuse ¬ "I/O error";
CONTINUE };
};
ansMsg: CHAR;
ansArg: ROPE;
tempName: ROPE;
actionProcQuit: BOOL;
IF overwrite
THEN {
PutMsg[msgStream, "Writing %g ... ", remoteName];
[ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'O, remoteName];
SELECT ansMsg
FROM
'Y => NULL;
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] };
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
BridgeComm.PutMsg[nsp, 'W];
actionProcQuit ¬ action[nsp, -1, NIL];
NetworkStream.SendEndOfMessage[nsp.out];
[ansMsg, ansArg] ¬ BridgeComm.GetMsg[nsp];
SELECT ansMsg
FROM
'Y => NULL;
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] };
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
[] ¬ BridgeComm.PutMsgWithReply[nsp, 'o];
TODO: IF actionProcQuit then delete the file! (someday we'll have file delete?)
PutMsg[msgStream, IF actionProcQuit THEN "aborted\n" ELSE "ok\n"];
}
ELSE {
PutMsg[msgStream, "Storing to temporary ... "];
tempName ¬ MkTempName[remoteName];
[ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'N, tempName];
SELECT ansMsg
FROM
'Y => NULL;
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] };
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
BridgeComm.PutMsg[nsp, 'W];
actionProcQuit ¬ action[nsp, -1, NIL];
NetworkStream.SendEndOfMessage[nsp.out];
[ansMsg, ansArg] ¬ BridgeComm.GetMsg[nsp];
SELECT ansMsg
FROM
'Y => NULL;
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] };
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
[ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'o];
SELECT ansMsg
FROM
'Y => NULL;
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] };
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
IF actionProcQuit
THEN {
PutMsg[msgStream, "aborted\n"];
}
ELSE {
PutMsg[msgStream, "renaming temporary to %g ... ", remoteName];
[ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'M,
Rope.Cat[tempName, " ", remoteName]];
SELECT ansMsg
FROM
'Y => NULL;
'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] };
ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] };
PutMsg[msgStream, "ok\n"];
};
};
};
PutMsg:
PROC [s:
STREAM, fmt:
ROPE, msg:
ROPE ¬
NIL] ~ {
ENABLE IO.Error => CONTINUE;
IF (s # NIL) THEN IO.PutF1[s, fmt, IF msg # NIL THEN [rope[msg]] ELSE [null[]]];
};
}...