-- Copyright (C) 1981, 1984, 1985  by Xerox Corporation. All rights reserved. 
-- ServerInfo.mesa, Transport Mechanism Filestore - information about other servers --

-- HGM, 15-Sep-85  5:21:52
-- Andrew Birrell	24-Jul-81 16:00:25 --
-- Randy Gobbel		19-May-81 12:44:13 --

DIRECTORY
  BodyDefs USING [maxRNameLength, RName],
  Heap USING [systemZone],
  LocalNameDefs USING [ReadMSName],
  LogDefs USING [ShowLine],
  NameInfoDefs USING [GetConnect, NameType],
  ProtocolDefs USING [IsLocal, mailServerServerSocket],
  PupDefs USING [AppendPupAddress, GetPupAddress, PupAddress, PupNameTrouble],
  ServerDefs USING [ServerHandle, ServerName],
  SiteCacheDefs USING [SelectiveFlush],
  String USING [AppendString, EquivalentStrings];

ServerInfo: MONITOR LOCKS handle USING handle: ServerDefs.ServerHandle
  IMPORTS
    Heap, LocalNameDefs, LogDefs, NameInfoDefs, ProtocolDefs, PupDefs, SiteCacheDefs,
    String
  EXPORTS ServerDefs
  SHARES ServerDefs =
  BEGIN

  OPEN ServerDefs;

  LogUpDown: INTERNAL PROCEDURE [handle: ServerHandle, upDown: {up, down}] =
    BEGIN
    log: LONG STRING ← Heap.systemZone.NEW[StringBody[128]];
    String.AppendString[log, IF upDown = up THEN "Up"L ELSE "Down"L];
    String.AppendString[log, " server, "L];
    WITH handle.name SELECT FROM
      rName =>
        BEGIN
        String.AppendString[log, "R-Name: "L];
        String.AppendString[log, value];
        END;
      connect =>
        BEGIN
        String.AppendString[log, "Connect: "L];
        String.AppendString[log, value];
        END;
      netAddr =>
        BEGIN
        String.AppendString[log, "Net-addr: "L];
        PupDefs.AppendPupAddress[log, value];
        END;
      ENDCASE => ERROR;
    LogDefs.ShowLine[log];
    Heap.systemZone.FREE[@log];
    END;

  ServerUp: PUBLIC ENTRY PROCEDURE [handle: ServerHandle] RETURNS [BOOLEAN] =
    BEGIN RETURN[handle.up] END;

  InnerUpServer: ENTRY PROCEDURE [handle: ServerHandle] = INLINE
    BEGIN handle.up ← TRUE; LogUpDown[handle, up]; END;

  UpServer: PUBLIC PROCEDURE [handle: ServerHandle] =
    BEGIN InnerUpServer[handle]; SiteCacheDefs.SelectiveFlush[handle]; END;

  InnerDownServer: INTERNAL PROCEDURE [handle: ServerHandle] =
    BEGIN
    handle.up ← FALSE;
    WITH handle.name SELECT FROM
      rName, connect => handle.addrKnown ← FALSE;
      netAddr => NULL;
      ENDCASE => ERROR;
    LogUpDown[handle, down];
    END;

  DownServer: PUBLIC ENTRY PROCEDURE [handle: ServerHandle] =
    BEGIN InnerDownServer[handle]; END;

  ServerAddr: PUBLIC ENTRY PROCEDURE [handle: ServerHandle]
    RETURNS [addr: PupDefs.PupAddress] =
    BEGIN
    ENABLE UNWIND => IF handle.up THEN InnerDownServer[handle];
    buffer: LONG STRING ← [BodyDefs.maxRNameLength];
    IF handle.addrKnown THEN RETURN[handle.addr];
    WITH handle.name SELECT FROM
      connect => buffer ← value;
      rName =>
        BEGIN
        info: NameInfoDefs.NameType = NameInfoDefs.GetConnect[value, buffer];
        SELECT info FROM
          individual => NULL;
          allDown => ERROR ServerNotUp[];
          notFound, group => ERROR NoSuchServer;
          ENDCASE => ERROR;
        END;
      ENDCASE => ERROR;
    PupDefs.GetPupAddress[
      @addr, buffer !
      PupDefs.PupNameTrouble =>
        IF code = errorFromServer THEN ERROR NoSuchServer ELSE ERROR ServerNotUp];
    addr.socket ← ProtocolDefs.mailServerServerSocket;
    handle.addr ← addr;
    IF handle.up THEN handle.addrKnown ← TRUE;
    END;

  myMSName: BodyDefs.RName = LocalNameDefs.ReadMSName[].name;

  ServerIsLocal: PUBLIC PROCEDURE [handle: ServerHandle] RETURNS [BOOLEAN] =
    BEGIN
    ENABLE NoSuchServer, ServerNotUp => GOTO no;
    -- If server isn't up, return FALSE early, to avoid re-calculating
    -- its net address --
    RETURN[
      WITH handle.name SELECT FROM
        rName => String.EquivalentStrings[value, myMSName],
        ENDCASE => ServerUp[handle] AND ProtocolDefs.IsLocal[ServerAddr[handle]]]
    EXITS no => RETURN[FALSE]
    END;

  NoSuchServer: PUBLIC ERROR = CODE;
  ServerNotUp: PUBLIC ERROR = CODE;

  END.