-- File: SloshSend.mesa,  Last Edit: HGM  October 5, 1980  12:34 AM

DIRECTORY
  Inline USING [LongDivMod],
  Put USING [Line],
  String USING [AppendLongDecimal, AppendChar, AppendString],
  Storage USING [Node, Free],
  System USING [GetGreenwichMeanTime],
  Time USING [AppendCurrent],
  Window USING [Handle],

  File USING [Capability],
  George USING [
    CreateInputStream, Destroy, GetByte, GetLength, GetWords, Handle, SetIndex],
  Lock USING [LockDiskAndWait, UnlockDisk],
  Slosh USING [SendStatus],
  EFTPDefs USING [
    EFTPAbortSending, EFTPFinishSending, EFTPOpenForSending, EFTPSendBlock,
    EFTPSetSendTimeout, EFTPTimeOut, EFTPTroubleSending],
  PupDefs USING [AppendHostName, FastPath],
  PupTypes USING [PupAddress];

SloshSend: PROGRAM
  IMPORTS
    Inline, Put, String, Storage, System, Time, George, Lock, EFTPDefs, PupDefs
  EXPORTS Slosh =
  BEGIN

  verbose: BOOLEAN = TRUE;

  SendFile: PUBLIC PROCEDURE [
    who: Window.Handle, fileName: STRING, file: File.Capability,
    him: PupTypes.PupAddress] RETURNS [what: Slosh.SendStatus] =
    BEGIN OPEN EFTPDefs;
    sh: George.Handle ← George.CreateInputStream[file];
    words: CARDINAL = 256;
    page, pages, bytes: CARDINAL;
    buffer: POINTER TO PACKED ARRAY OF [0..377B];
    message: STRING;
    trouble: STRING = [100];
    seconds: LONG CARDINAL;
    slowly: BOOLEAN ← ~PupDefs.FastPath[him];
    Lock.LockDiskAndWait[fileName, read];
    seconds ← System.GetGreenwichMeanTime[];
    -- Yetch, at 2400 baud it takes 2 sec/page
    IF slowly THEN EFTPSetSendTimeout[6000, 10] ELSE EFTPSetSendTimeout[2000, 10];
    -- Argh, the Mesa 5 Gateways timeout after 15 seconds.
    -- Remove these 3 lines after they have all gone away.
    IF slowly THEN EFTPSetSendTimeout[3000, 10];
    BEGIN
    EFTPOpenForSending[
      him, FALSE ! EFTPTimeOut, EFTPTroubleSending => GOTO NeverStarted];
    [pages, bytes] ← Inline.LongDivMod[George.GetLength[sh], words*2];
    George.SetIndex[sh, 0];
    buffer ← Storage.Node[words];
    FOR page IN [0..pages) DO
      [] ← George.GetWords[sh, buffer, words];
      EFTPSendBlock[
	buffer, words*2 !
	EFTPTimeOut =>
	  BEGIN message ← "Timeout while sending "L; GOTO Trouble; END;
	EFTPTroubleSending =>
	  BEGIN
	  message ← "Troubles while sending "L;
	  String.AppendString[trouble, s];
	  GOTO Trouble;
	  END];
      ENDLOOP;
    [] ← George.GetWords[sh, buffer, bytes/2];
    IF (bytes MOD 2) # 0 THEN buffer[bytes - 1] ← George.GetByte[sh];
    EFTPSendBlock[
      buffer, bytes !
      EFTPTimeOut => BEGIN message ← "Timeout while sending "L; GOTO Trouble; END;
      EFTPTroubleSending =>
	BEGIN
	message ← "Troubles while sending "L;
	String.AppendString[trouble, s];
	GOTO Trouble;
	END];
    EFTPFinishSending[
      !
      EFTPTimeOut =>
	BEGIN message ← "Timeout while finishing "L; GOTO Trouble; END;
      EFTPTroubleSending =>
	BEGIN
	message ← "Troubles while finishing "L;
	String.AppendString[trouble, s];
	GOTO Trouble;
	END];
    Storage.Free[buffer];
    seconds ← System.GetGreenwichMeanTime[] - seconds;
    message ← "Sent "L;
    what ← ok;
    EXITS
      Trouble =>
	BEGIN
	EFTPAbortSending[message];
	Storage.Free[buffer];
	seconds ← System.GetGreenwichMeanTime[] - seconds;
	what ← troubles;
	END;
      NeverStarted =>
	BEGIN
	message ← "Never started sending "L;
	EFTPAbortSending[message];
	seconds ← System.GetGreenwichMeanTime[] - seconds;
	what ← neverStarted;
	END;
    END;
    Lock.UnlockDisk[fileName];
    George.Destroy[sh];
    IF verbose THEN
      BEGIN OPEN String;
      text: STRING = [150];
      Time.AppendCurrent[text];
      AppendString[text, "  "L];
      AppendString[text, message];
      IF trouble.length # 0 THEN
	BEGIN
	AppendString[text, "("L];
	AppendString[text, trouble];
	AppendString[text, ") "L];
	END;
      AppendString[text, fileName];
      AppendString[text, " to "L];
      PupDefs.AppendHostName[text, him];
      IF what # ok AND what # neverStarted THEN
	BEGIN AppendString[text, ", page="L]; AppendLongDecimal[text, page]; END;
      AppendString[text, ", sec="L];
      AppendLongDecimal[text, seconds];
      IF slowly THEN AppendString[text, " (slowly)"L];
      AppendChar[text, '.];
      LogString[who, text];
      END;
    END;

  LogString: PROCEDURE [msg: Window.Handle, text: STRING] =
    BEGIN IF msg # NIL THEN Put.Line[msg, text]; Put.Line[NIL, text]; END;

  END.