-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- ReadForward.mesa, Transport Mechanism Mail Server - algorithm to process forward queue -- -- HGM: 14-Sep-85 20:11:53 -- 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, Heap USING [systemZone], 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 [AppendLongDecimal, AppendString], System USING [GetGreenwichMeanTime, GreenwichMeanTime]; ReadForward: PROGRAM IMPORTS Heap, HeapDefs, LocalNameDefs, LogDefs, PolicyDefs, Process, ProtocolDefs, ServerDefs, SLDefs, String, System EXPORTS RestartDefs = 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; startTime: System.GreenwichMeanTime; seconds: LONG CARDINAL; [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 startTime ← System.GetGreenwichMeanTime[]; 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]; seconds ← System.GetGreenwichMeanTime[]-startTime; 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; LogForwarded[slHeader, outcome # ok, seconds]; SELECT outcome FROM ok => SLDefs.SLEndRead[SLhandle]; down => SLDefs.SLTransfer[SLhandle, input]; ENDCASE => ERROR; END; PolicyDefs.EndOperation[readForward]; ENDLOOP; END; LogForwarded: PROCEDURE [slHeader: SLDefs.SLHeader, failed: BOOLEAN, seconds: LONG CARDINAL] = BEGIN log: LONG STRING ← Heap.systemZone.NEW[StringBody [200]]; 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 failed THEN String.AppendString[log, ": failed"L]; IF seconds > 30 THEN { String.AppendString[log, ", "L]; String.AppendLongDecimal[log, seconds]; String.AppendString[log, " seconds"L]; }; LogDefs.WriteLogEntry[log]; Heap.systemZone.FREE[@log]; END; ReadForward1: PUBLIC PROC = BEGIN END; ReadForward2: PUBLIC PROC = 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; Process.Detach[FORK ForwardMain[]]; END; END.