-- Copyright (C) 1983 by Xerox Corporation. All rights reserved.
-- SloshRecv.mesa, HGM, 24-Sep-83 17:39:42
DIRECTORY
Ascii USING [CR],
Environment USING [Byte, bytesPerPage],
Inline USING [LowHalf],
Put USING [Text],
Stream USING [Delete, Handle, PutBlock],
String USING [AppendChar, AppendString, AppendLongDecimal],
System USING [GetClockPulses],
Time USING [AppendCurrent],
Volume USING [GetAttributes, InsufficientSpace, SystemID],
Window USING [Handle],
Slosh USING [RecvStatus],
EFTPDefs USING [
EFTPOpenForReceiving, EFTPAbortReceiving, EFTPGetBlock, EFTPFinishReceiving,
EFTPEndReceiving, EFTPTimeOut, EFTPTroubleReceiving, EFTPSetRecvTimeout],
PupTypes USING [PupAddress];
SloshRecv: MONITOR
IMPORTS Inline, Put, Stream, String, System, Time, Volume, EFTPDefs
EXPORTS Slosh =
BEGIN
verbose: BOOLEAN = TRUE;
RecvFile: PUBLIC ENTRY PROCEDURE [
who: Window.Handle, fileName: LONG STRING, file: Stream.Handle,
me: PupTypes.PupAddress, ask: PROCEDURE] RETURNS [status: Slosh.RecvStatus] =
BEGIN OPEN EFTPDefs;
FixThingsUp: PROCEDURE [e: LONG STRING, why: Slosh.RecvStatus] =
BEGIN message ← e; EFTPAbortReceiving[message]; status ← why; END;
buffer: PACKED ARRAY [0..Environment.bytesPerPage) OF Environment.Byte;
total: LONG CARDINAL ← 0;
message: LONG STRING ← NIL;
trouble: STRING = [100];
EFTPSetRecvTimeout[1000];
BEGIN
ENABLE
BEGIN
EFTPTroubleReceiving =>
BEGIN String.AppendString[trouble, s]; GOTO EFTPTrouble; END;
EFTPTimeOut => GOTO EFTPTimeout;
END;
pokes: CARDINAL ← 0;
bytes: CARDINAL;
[] ← EFTPOpenForReceiving[
me !
EFTPTimeOut =>
BEGIN -- We expect to get here once since we haven't asked yet
IF (pokes ← pokes + 1) > 3 THEN GOTO OpenFailed;
ask[];
RESUME
;
END];
EFTPSetRecvTimeout[60000];
-- This is a silly place to check, but it simplifies recovery
DO
bytes ← EFTPGetBlock[
@buffer, Environment.bytesPerPage ! EFTPEndReceiving => EXIT];
Stream.PutBlock[
file, [@buffer, 0, bytes] !
Volume.InsufficientSpace => GOTO TempFull];
total ← total + bytes;
ENDLOOP;
EFTPFinishReceiving[];
status ← statusStoreOk;
EXITS
OpenFailed => FixThingsUp["EFTP Open Failed"L, statusEFTPFailed];
EFTPTrouble => FixThingsUp["EFTP Trouble"L, statusEFTPFailed];
EFTPTimeout => FixThingsUp["EFTP Timeout"L, statusEFTPFailed];
TempFull =>
FixThingsUp[
"Disk Full while buffering into buffer file"L, statusDiskFull];
END;
Stream.Delete[file];
IF verbose THEN
BEGIN
text: STRING = [200];
pagesLeft: LONG CARDINAL ← Volume.GetAttributes[
Volume.SystemID[]].freePageCount;
Time.AppendCurrent[text];
IF message = NIL THEN
BEGIN
String.AppendString[text, " Got "L];
String.AppendString[text, fileName];
String.AppendString[text, " ok. Length="L];
String.AppendLongDecimal[text, total/Environment.bytesPerPage];
String.AppendChar[text, '.];
String.AppendLongDecimal[text, total MOD Environment.bytesPerPage];
END
ELSE
BEGIN
String.AppendString[text, " Recv aborted because: "L];
String.AppendString[text, message];
IF trouble.length # 0 THEN
BEGIN
String.AppendString[text, "("L];
String.AppendString[text, trouble];
String.AppendString[text, ") "L];
END;
String.AppendString[text, " after page "L];
String.AppendLongDecimal[text, total/Environment.bytesPerPage];
END;
String.AppendString[text, ", pages left="L];
String.AppendLongDecimal[text, pagesLeft];
LogString[who, text];
END;
END;
LogString: PROCEDURE [msg: Window.Handle, text: LONG STRING] =
BEGIN
String.AppendChar[text, '.];
String.AppendChar[text, Ascii.CR];
Put.Text[NIL, text];
IF msg # NIL THEN Put.Text[msg, text];
END;
RetransmissionInterval: PUBLIC PROCEDURE RETURNS [seconds: CARDINAL] =
BEGIN
RETURN[Inline.LowHalf[System.GetClockPulses[]] MOD 5*60]; -- 5 min
END;
END.