-- Copyright (C) 1981, 1984 by Xerox Corporation. All rights reserved.
-- ReadForward.mesa, Transport Mechanism Mail Server - algorithm to process forward queue --
-- HGM: 15-Dec-84 22:46:03
-- Randy Gobbel 19-May-81 11:57:02 --
-- Andrew Birrell 29-Dec-81 14:53:38 --
-- Hankins 30-Jul-84 14:22:52 Klamath update (BufferDefs)
DIRECTORY
BodyDefs USING [RName],
Buffer,
HeapDefs USING [
ObjectNumber, HeapReadData, HeapStartRead, ReaderHandle, HeapEndRead,
SendObj],
LocalNameDefs USING [ReadMSName],
LogDefs USING [WriteLogEntry],
PolicyDefs USING [EndOperation, WaitOperation],
Process USING [Detach],
ProtocolDefs USING [
AppendTimestamp, CreateStream, DestroyStream, Failed, Handle, Password,
ReceiveAck, SendRName, SendTimestamp],
RestartDefs USING [],
ServerDefs USING [
ServerAddr, ServerHandle, ServerNotUp, ServerUp, DownServer, NoSuchServer],
SLDefs USING [
GetCount, SLHeader, SLStartRead, SLReadHandle, SLEndRead, SLTransfer],
String USING [AppendString];
ReadForward: PROGRAM
IMPORTS
HeapDefs, LocalNameDefs, LogDefs, PolicyDefs, Process, ProtocolDefs,
ServerDefs, SLDefs, String
EXPORTS RestartDefs --PROGRAM-- =
BEGIN
NoRecipients: ERROR = CODE; --not caught; should not occur--
ForwardMain: PROCEDURE =
BEGIN
-- multiple instantiations of this procedure are allowed --
DO
BEGIN
str: ProtocolDefs.Handle ← NIL;
SLobj: HeapDefs.ReaderHandle;
SLhandle: SLDefs.SLReadHandle;
bodyObj: HeapDefs.ObjectNumber;
slHeader: SLDefs.SLHeader;
outcome: {ok, down} ← ok;
[SLhandle, bodyObj, SLobj] ← SLDefs.SLStartRead[forward];
PolicyDefs.WaitOperation[readForward];
BEGIN
-- read SL header --
ended: BOOLEAN;
used: CARDINAL;
[ended, used] ← HeapDefs.HeapReadData[
SLobj, [@slHeader, SIZE[SLDefs.SLHeader]]];
IF ended THEN ERROR NoRecipients[];
END;
IF NOT ServerDefs.ServerUp[slHeader.server] THEN {
HeapDefs.HeapEndRead[SLobj]; outcome ← down}
ELSE
BEGIN
str ← ProtocolDefs.CreateStream[
ServerDefs.ServerAddr[
slHeader.server !
ServerDefs.ServerNotUp, ServerDefs.NoSuchServer => GOTO noAddr] !
ProtocolDefs.Failed => GOTO noStr];
BEGIN
ENABLE
ProtocolDefs.Failed => {HeapDefs.HeapEndRead[SLobj]; GOTO wentDown};
myName: BodyDefs.RName;
myKey: ProtocolDefs.Password;
[name: myName, key: myKey, password:] ← LocalNameDefs.ReadMSName[];
ProtocolDefs.SendRName[str, myName];
ProtocolDefs.SendTimestamp[str, slHeader.created];
END;
BEGIN
ENABLE ProtocolDefs.Failed => GOTO wentDown;
HeapDefs.SendObj[SLobj, str];
HeapDefs.SendObj[HeapDefs.HeapStartRead[bodyObj], str];
ProtocolDefs.ReceiveAck[str];
END;
ProtocolDefs.DestroyStream[str];
EXITS
noAddr => {HeapDefs.HeapEndRead[SLobj]; outcome ← down};
noStr =>
BEGIN
HeapDefs.HeapEndRead[SLobj];
ServerDefs.DownServer[slHeader.server];
outcome ← down;
END;
wentDown =>
BEGIN
ProtocolDefs.DestroyStream[str];
ServerDefs.DownServer[slHeader.server];
outcome ← down;
END;
END;
BEGIN
log: STRING = [128];
String.AppendString[log, "Forwarded "L];
ProtocolDefs.AppendTimestamp[log, slHeader.created];
String.AppendString[log, " to "L];
WITH slHeader.server.name SELECT FROM
rName => String.AppendString[log, value];
ENDCASE;
IF outcome # ok THEN String.AppendString[log, ": failed"L];
LogDefs.WriteLogEntry[log];
END;
SELECT outcome FROM
ok => SLDefs.SLEndRead[SLhandle];
down => SLDefs.SLTransfer[SLhandle, input];
ENDCASE => ERROR;
END;
PolicyDefs.EndOperation[readForward];
ENDLOOP;
END;
ForwardRestart: PROCEDURE =
BEGIN
-- on restart, must transfer everything to input, since ServerHandles
-- are no longer valid --
THROUGH [0..SLDefs.GetCount[forward]) DO
handle: SLDefs.SLReadHandle;
body: HeapDefs.ObjectNumber;
SL: HeapDefs.ReaderHandle;
[handle, body, SL] ← SLDefs.SLStartRead[forward];
HeapDefs.HeapEndRead[SL];
SLDefs.SLTransfer[handle, input];
ENDLOOP;
END;
ForwardRestart[];
Process.Detach[FORK ForwardMain[]];
END.