-- Transport Mechanism Filestore - information about other servers --

-- [Juniper]<Grapevine>MS>ServerInfo.mesa

-- Andrew Birrell	24-Jul-81 16:00:25 --
-- Randy Gobbel		19-May-81 12:44:13 --

DIRECTORY
   BodyDefs		USING[ maxRNameLength, RName ],
   LocalNameDefs	USING[ ReadMSName ],
   LogDefs		USING[ WriteChar, WriteLogEntry ],
   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 LocalNameDefs, LogDefs, NameInfoDefs, ProtocolDefs, PupDefs,
           SiteCacheDefs, String
   EXPORTS ServerDefs
   SHARES  ServerDefs =
BEGIN

OPEN ServerDefs;

LogUpDown: INTERNAL PROCEDURE[handle: ServerHandle, upDown: {up,down} ] =
   BEGIN
   log: STRING = [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.WriteLogEntry[log];
   LogDefs.WriteChar[IF upDown = up THEN 'U ELSE 'D];
   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: 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 ];
   SELECT handle.type FROM
     mail =>         addr.socket ← ProtocolDefs.mailServerServerSocket;
     foreign =>      NULL -- NLS should provide socket number --;
   ENDCASE => ERROR;
   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.