Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/nml/nmlevt.bli
There are no other files named nmlevt.bli in the archive.
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 28-Sep-82 11:49:03, Edit by PECKHAM
!
! Ident 22.
!  Fix dot bug introduced by #21.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2  8-Sep-82 09:46:56, Edit by PECKHAM
!
! Ident 21.
!  Add code in GET_LOCAL_EVENTS to set the EXECUTOR IDENTIFICATION
!  from the NMX access control information block.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 29-Jun-82 09:59:30, Edit by PECKHAM
!
! Ident 20.
! Change SS$EVR reference into $NMU_NMX_READ_EVENT reference.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.6 27-Jun-82 01:46:10, Edit by PECKHAM
!
! Ident 19.
! Fix the TOPS20 EVENT TIME figured in GET_EVENT_BUFFER.  It was not
! being set relative to 1-JAN-77.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 25-Jun-82 11:57:31, Edit by PECKHAM
!
! Ident 18.
! Fix GET_LOCAL_EVENTS to recognize access control message from NMX
! and copy data into UN$xxx areas for use by NMUNET.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2  1-Jun-82 13:43:01, Edit by PECKHAM
!
! Ident 17.
! New event message format from NMX/MCB.
!
!NET:<BRANDT.DEVELOPMENT>NMLEVT.BLI.2 4-May-82 16:23:09, Edit by BRANDT
!
! Ident 16.
! Put external declaration for NML$DLW_CALL under MCB conditional.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 22-Apr-82 08:23:09, Edit by PECKHAM
!
! Ident 15.
! Change configuration switch naming.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 26-Mar-82 08:42:52, Edit by PECKHAM
!
! Ident 14.
! Utilize new MCB time block.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.57 24-Mar-82 08:33:15, Edit by PECKHAM
!
! Ident 13.
! Fix event queues to work properly (avoid consecutive lost event events).
! Use configuration switches from NMLCOM.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2  2-Mar-82 09:47:35, Edit by PECKHAM
!
! Ident 12.
! Fix bug in NML$EVENT_RECORDER that caused SYSERR code to go away.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 19-Feb-82 08:29:21, Edit by PECKHAM
!
! Ident 11.
! Add direct access to time routines, thus making EV_ETM unnecessary.
! Add LOGGING FILE state maintenance for TOPS20.
! Remove LW_EVT (DLW routines now call NML$DECLARE_EVENT directly).
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 17-Feb-82 12:41:38, Edit by PECKHAM
!
! Ident 10.
! Reduce task stack size by half.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.3  5-Feb-82 15:40:30, Edit by PECKHAM
!
! Ident 09.
! The PROCESSED_QUEUE must be a scheduled queue!
! Also change PROCESSED_QUEUE size from 3 to 6.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.3  5-Feb-82 13:04:17, Edit by PECKHAM
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2  5-Feb-82 09:19:00, Edit by GROSSMAN
!
! Ident 08.
! Decrement PROCESSED_QUEUE_COUNT each time an item is removed from the
! PROCESSED_QUEUE. This allows NML to pass more than 3 events.
! Change PROCESSED_QUEUE from quota queue to regular queue.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 22-Jan-82 13:00:18, Edit by PECKHAM
!
! Ident 07.
! Make declared events in a TOPSxx system RT$LOCAL in DECLARE_EVENT.
! Fix HOST_ID length in EVENT_INITIALIZE.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.3 20-Jan-82 17:17:47, Edit by PECKHAM
!
! Ident 06.
! Fix NML$DECLARE_EVENT to figure entity-id string length
! instead of requiring caller to supply it.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.2 18-Jan-82 20:33:29, Edit by PECKHAM
!
! Ident 05.
! Modify LW_EVT to satisfy both NMLDLW 36 & 16 needs.
!
!NET:<PECKHAM.DEVELOPMENT>NMLEVT.BLI.22 16-Jan-82 17:29:18, Edit by PECKHAM
!
! Ident 04.
! Update copyright date.
! Add NML$DECLARE_EVENT support and review event queue handling.
! Note : all event times are being assigned at NML level as of now.
! Note : the current time cannot be obtained from here due to lack of NMULIB;
!        The routine EV_ETM will be put in a module which uses NMULIB.
! Get proper host node id for events.
! Remove EVENT_TIME routine.
! Temporary LW_EVT routine for NMLDLW to log events (until it uses NMLLIB)
! I am putting EV_ETM into NMLDLW for now.
!
!NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLEVT.BLI.10 12-Oct-81 10:22:21, Edit by PECKHAM
!
! Ident 03.
! Correct bug introduced in ident 01 in GET_LOCAL_EVENT.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLEVT.BLI.8 11-Oct-81 16:36:35, Edit by PECKHAM
!
! Ident 01.
! Add recognition of maintenance requests to GET_LOCAL_EVENT to call
! the Data Link Watcher.
!
!<DECNET20-V3P1.BASELEVEL-2.MCB>NMLEVT.BLI.2 26-Jun-81 13:26:36, Edit by SROBINSON
!
! Fix NODE_E Event Logging Address Bug using GETW
!
!<DECNET20-V3P1.BASELEVEL-2.MCB>NMLEVT.BLI.2 11-Jun-81 11:38:14, Edit by SROBINSON
!   Add Quota Checked Queues
!
module NMLEVT (					! Event Processing Module
		ident = 'X00.22'
		) =
begin
!
!                    COPYRIGHT (c) 1980, 1981, 1982
!                    DIGITAL EQUIPMENT CORPORATION
!                        Maynard, Massachusetts
!
!     This software is furnished under a license and may  be  used
!     and copied only in accordance with the terms of such license
!     and with the inclusion of the above copyright notice.   This
!     software  or any other copies thereof may not be provided or
!     otherwise made available to any other person.  No  title  to
!     and ownership of the software is hereby transferred.
!
!     The information  in  this  software  is  subject  to  change
!     without  notice  and should not be construed as a commitment
!     by DIGITAL EQUIPMENT CORPORATION.
!
!     DIGITAL assumes no responsibility for the use or reliability
!     of  its  software  on  equipment  which  is  not supplied by
!     DIGITAL.
!

!++
! Facility: LSG DECnet Network Management
!
! Abstract: This module provides the routines that control the
!           Event Queueing system within the NML task. It also contains
!	    the Event Recorder and Processor.
!
! Environment: TOPS10/TOPS20 user mode, MCB RSX task level
!
! Author: Scott G. Robinson, Creation date: 24-Mar-81
!	  From NMLQUE by Steven M. Jenness
!	  From NMLNIC by Dale C. Gunn
!
!--

!<BLF/SYNONYM $FIELD=FIELD>
!<BLF/SYNONYM %UNQUOTE =>
!<BLF/PAGE>
!
! Include files
!

library 'NMLLIB';                       ! All needed definitions

!
! Global routines
!

forward routine
    NML$EVENT_MANAGER,                  ! Define global entry points
    NML$LOGGING_FILE : novalue;         ! LOGGING FILE event handler

forward routine
    EMPTY_QUEUE_CHECK,                  ! Check if a queue is empty
    GET_EVENT_BUFFER,                   ! Allocate and format event block
    GET_LOCAL_EVENT : novalue;          ! Local Event Reader

!
! Local routines
!

!
! Logging values
!

    macro
         C_STRING [ ] =                 ! Counted string
             %if not $MCB
             %then
             C_CHAR(%char(%charcount(%remaining)),%explode(%remaining)) 
             %else
             %string(%char(%charcount(%remaining)),%remaining)
             %fi % ;

    %if not $MCB
    %then
    macro
         C_CHAR [B1,B2,B3,B4] =
             ((%C B1 ^ (%bpval-8))
              %if not %null(B2)
              %then
                   or (%C B2 ^ (%bpval-16))
              %if not %null(B3)
              %then
                   or (%C B3 ^ (%bpval-24))
              %if not %null(B4)
              %then
                   or (%C B4 ^ (%bpval-32))
              %fi %fi %fi) %;
    %else
    macro
         C_CHAR [] =
             (%string (%remaining)) %;
    %fi

%if NML$CFG_LOGGING_FILE
%then
    bind
        LOGGING_FILE_PTR = ch$ptr (uplit (%char (FILE_))),
        LOGGING_NAME_ADR = uplit (C_STRING ('ERROR.SYS'));
%fi

    literal
        LOGGING_STATE = 0,
        STATE_ON = 0,
        STATE_OFF = 1,
        STATE_HOLD = 2,
        LOGGING_NAME = 100;

!
! Own storage
!

own
%if NML$CFG_LOGGING_FILE
%then
    FILE_QUEUE : EVENT_QUEUE,           ! LOGGING FILE event queue
%fi
%if NML$CFG_LOGGING_TRANSMITTER
%then
    HOST_TRANSMITTER : TRANSMITTER_QUEUE, ! Event transmitter queue for host
%fi
    LOST_EVENTS,                        ! Lost events due to full queue
    ALLOCATION_FAILURES;                ! Lost events due to insufficient memory

!
! External references
!

external routine
%if $MCB
%then
    NML$DLW_CALL,                       ! Notify Data Link Watcher
%fi
%if NML$CFG_LOGGING_TRANSMITTER
%then
    NML$EVENT_TRANSMITTER,              ! Event Transmitter
%fi
%if NML$CFG_LOGGING_RECEIVER
%then
    NML$EVENT_RECEIVER,                 ! Event Receiver
%fi
    NMU$QUEUE_MANAGER,                  ! Generalized queue management routines
    NMU$SCHED_MANAGER,                  ! Scheduler
    NMU$MEMORY_MANAGER,                 ! Memory management routines
    NML$GET_VDB_PARAMETER,              ! Extract data for specific parameter
    NML$SET_VDB_PARAMETER,              ! Set parameter in Volatile DB
    NMU$TABLE_ROUTINES,                 ! Table handling routines
    NMU$NETWORK_UTILITIES;              ! Network interface
%global_routine ('NML$DECLARE_EVENT', REB : ref RAW_EVENT_BLOCK) : novalue =

!++
! Functional description:
!
!       This routine accepts a raw event block and gives it to the
!       event processor for filtering and transmitting.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--

    begin
    NML$EVENT_PROCESSOR (.REB);
    end;					! End of NML$DECLARE_EVENT
%global_routine ('NML$EQUEUE_INSERT', EQ: ref EVENT_QUEUE, EB : ref EVENT_BUFFER) : novalue =

!++
! Functional description:
!
!       None
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--

    begin

    if .EQ [EQ_COUNT] eql .EQ [EQ_LENGTH]
    then
        begin
        NMU$MEMORY_RELEASE (.EB, .EB [EB_ALLOCATION]);
        return;
        end;

    EQ [EQ_COUNT] = .EQ [EQ_COUNT] + 1;

    if .EQ [EQ_COUNT] eql .EQ [EQ_LENGTH]
    then
        begin

        local
            LNG,
            PTR;

        PTR = ch$ptr (EB [EB_BUFFER], 2, 8);

        if (ch$rchar (.PTR) eql 0) and
           (ch$rchar (ch$plus (.PTR, 1)) eql 0)
        then                            ! Last event is lost event
            begin
            EQ [EQ_COUNT] = .EQ [EQ_COUNT] - 1;
            NMU$MEMORY_RELEASE (.EB, .EB [EB_ALLOCATION]);
            return;
            end;
        !
        ! Turn current event into 'lost event' event
        !
        ch$wchar_a (0, PTR);
        ch$wchar_a (0, PTR);
        PTR = ch$plus (.PTR, 6 + 2);
        LNG = ch$rchar_a (PTR);
        PTR = ch$plus (.PTR, .LNG);
        ch$wchar_a (NO_ENTITY_ and %o'377', PTR);
        ch$wchar_a (NO_ENTITY_^-8 and %o'377', PTR);
        EB [EB_LENGTH] = PTR = ch$diff (.PTR, ch$ptr (EB [EB_BUFFER],, 8));
        end;

    NMU$SQUEUE_INSERT (.EQ, .EB);
    end;					! End of NML$EQUEUE_INSERT
%global_routine ('NML$EQUEUE_REMOVE', EQ: ref EVENT_QUEUE) =

!++
! Functional description:
!
!       None
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--

    begin

    local
        EB;

    EB = NMU$SQUEUE_REMOVE (.EQ);
    EQ [EQ_COUNT] = .EQ [EQ_COUNT] - 1;
    .EB
    end;					! End of NML$EQUEUE_REMOVE
%global_routine ('NML$EQUEUE_RESET', EQ: ref EVENT_QUEUE, LENGTH) : novalue =

!++
! Functional description:
!
!       None
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--

    begin
    NMU$SQUEUE_RESET (.EQ);
    EQ [EQ_COUNT] = 0;
    EQ [EQ_LENGTH] = .LENGTH;
    end;					! End of NML$EQUEUE_RESET
%global_routine ('NML$EVENT_INITIALIZE') : novalue =

!++
! Functional description:
!
!       This routine initializes the entire event system including
!	creation of the Event Listener, Event Transmitter, Event Recorder,
!	and Event Processor. All queues are cleared.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--

    begin
!
! Create the tasks for Event Handling
!
%if $MCB
%then
    NMU$SCHED_CREATE (GET_LOCAL_EVENT, 100, 0, ch$asciz ('GET-LOCAL-EVENTS'));
%fi
%if NML$CFG_LOGGING_TRANSMITTER
%then
    begin                               ! Set up with host node for now.

    macro
        TRANSMITTER_TO_ = 'TRANSMITTER-TO-' %;

    psect plit = $own$;
    bind
        TRANSMITTER_NAME_PTR = ch$asciz (TRANSMITTER_TO_, 'xxxxx'),
        HOST_ID = HOST_TRANSMITTER [TQ_SINK_NODE];
    psect plit = $plit$;

    NML$EQUEUE_RESET (HOST_TRANSMITTER, 6);
    $NML$GET_HOST_ID (uplit (NODE_ID_BUFFER_LENGTH), ch$ptr (HOST_ID,, 8));
    begin
    local NUMBER, PTR;
    linkage
        LNKG = JSR (register = 0, register = 1, register = 2; register = 0) :
                   nopreserve (1,2);
    external routine
        $CBDMG : LNKG novalue;
    NUMBER = ch$ptr (HOST_TRANSMITTER [TQ_SINK_NODE],, 8);
    NUMBER = GETW (NUMBER);
    $CBDMG (ch$plus (TRANSMITTER_NAME_PTR, %charcount (TRANSMITTER_TO_)),
            .NUMBER, 0; PTR);
    ch$wchar (0, .PTR);
    end;
    HOST_TRANSMITTER [TQ_TRANSMITTER_TASK] =
        NMU$SCHED_CREATE (NML$EVENT_TRANSMITTER, 300, 0, TRANSMITTER_NAME_PTR);
    end;
%fi
%if NML$CFG_LOGGING_RECEIVER
%then
    NMU$SCHED_CREATE (NML$EVENT_RECEIVER, 250, 0,
                      ch$asciz ('EVENT-LISTENER'));
%fi
%if NML$CFG_LOGGING_FILE
%then
    NML$SET_VDB_PARAMETER (LOGGING_,
                           LOGGING_FILE_PTR,
                           LOGGING_NAME,
                           uplit (LOGGING_NAME_ADR));
    NML$SET_VDB_PARAMETER (LOGGING_,
                           LOGGING_FILE_PTR,
                           LOGGING_STATE,
                           uplit (STATE_ON));
    NML$EQUEUE_RESET (FILE_QUEUE, 6);
    NMU$SCHED_CREATE (NML$LOGGING_FILE, 100, 0, ch$asciz ('EVENT-FILE'));
%fi
    end;					! End of NML$EVENT_INITIALIZE
%global_routine ('NML$EVENT_PROCESSOR', REB : ref RAW_EVENT_BLOCK) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin

    local
        OLD_TB,
        TB : TIME_BLOCK;

    OLD_TB = .REB [REB_TIME_BLOCK];
    TIME_CURRENT (0, TB);
    REB [REB_TIME_BLOCK] = TB;
    REB [REB_SOURCE_POINTER] = NMU$NETWORK_LOCAL ();
%if NML$CFG_LOGGING_RECEIVER
%then
    !
    ! This is for SINK NODE EXECUTOR
    !
    REB [REB_SINK_FLAGS] = 0;
    !
    ! Pass if through the event filters
    !
    REB [REB_FILE] = 1;                 ! Hard coded for FILE
    !
    ! If there is a taker, pass it along
    !
    if .REB [REB_SINK_FLAGS] neq 0
    then
        NML$EVENT_RECORDER (.REB);
%fi
%if NML$CFG_LOGGING_TRANSMITTER
%then
    !
    ! This is for the other SINK NODEs
    !
    REB [REB_SINK_FLAGS] = 0;
    !
    ! Pass if through the event filters
    ! of SINK NODE 'HOST_TRANSMITTER [TQ_SINK_NODE]'.
    !
    REB [REB_FILE] = 1;                 ! Hard coded for FILE
    !
    ! If there is a taker, pass it along
    !
    if .REB [REB_SINK_FLAGS] neq 0
    then
        begin

        local
            EB : ref EVENT_BUFFER;

        if (EB = GET_EVENT_BUFFER (.REB)) neqa 0
        then
            NML$EQUEUE_INSERT (HOST_TRANSMITTER, .EB);

        end;
%fi

    REB [REB_TIME_BLOCK] = .OLD_TB;
    end;                                !End of NML$EVENT_PROCESSOR
%global_routine ('NML$EVENT_RECORDER', REB : ref RAW_EVENT_BLOCK) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine dequeues requests to the local node and logs
!	them to the appropriate Event Sink.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NML Event request queue.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin

    literal
        LOGGING_STATE = 0,
        STATE_ON = 0,
        STATE_OFF = 1,
        STATE_HOLD = 2;

%if NML$CFG_LOGGING_FILE
%then
    !
    ! Only the FILE sink is supported at present
    !

    if .REB [REB_FILE] neq 0            ! If directed to FILE
    then                                ! then
        begin                           ! check the STATE.

        local
            STATE;

        if not NML$GET_VDB_PARAMETER (LOGGING_,
                                      LOGGING_FILE_PTR,
                                      LOGGING_STATE,
                                      STATE)
        then STATE = STATE_OFF;         ! Not defined...

        selectone .STATE of
            set
            [STATE_OFF] :               ! Discard.
                0;
            [otherwise] :               ! Send to FILE task.

                if (STATE = GET_EVENT_BUFFER (.REB)) neqa 0 ! make a copy
                then                    ! and
                    NML$EQUEUE_INSERT (FILE_QUEUE, .STATE); ! send to task.

            tes;

        end;
%fi
%if not NML$CFG_LOGGING_RECEIVER
%then
    0                                   ! To avoid empty compound expression
%fi
    end;                                !End of NML$EVENT_RECORDER
%routine ('NML$LOGGING_FILE', TASK, RESOURCE) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine dequeues requests to the local node and logs
!	them to the appropriate Event Sink.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NML Event request queue.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin

%if NML$CFG_LOGGING_FILE
%then

    !
    ! Top level loop for Event requests
    !

    while $true do                      ! Main NML Request processing loop
	begin

        local
	    EB : ref EVENT_BUFFER;      ! Event buffer

	EB = NML$EQUEUE_REMOVE (FILE_QUEUE);
!       RTN_COD = NML$NICE_VERIFY (.REQ) ; ! Verify the Event message syntax

        selectone
            begin

            while $true do
                begin

                local
                    STATE;

                if not NML$GET_VDB_PARAMETER (LOGGING_,
                                              LOGGING_FILE_PTR,
                                              LOGGING_STATE,
                                              STATE)
                then STATE = STATE_OFF;

                if .STATE neq STATE_HOLD then exitloop .STATE;

                !
                ! Wait for state to change
                !
                NMU$SCHED_SLEEP (10);   ! Temporary hack
                end

            end
        of
            set
            [STATE_OFF]:
                NMU$MEMORY_RELEASE (.EB, .EB [EB_ALLOCATION]);
            [otherwise] :
                begin
%if $TOPS20
%then
!
! This code does all processing for SYSERR logging under TOPS-20
!
                DECLARE_JSYS (GTAD, TIME, SYSGT, SYERR);

                field
                    SYSERR_FIELDS =
                        set
                        SY_COD = [0, 27, 9, 0], ! SYSERR Error Code
                        SY_T20 = [0, 18, 1, 0], ! Bit flagging TOPS-20 Made Entry
                        SY_VER = [0, 12, 6, 0], ! Header Version
                        SY_HLN = [0, 9, 3, 0], ! Header Length
                        SY_LEN = [0, 0, 9, 0], ! Data Length
                        SY_DTE = [1, 0, 36, 0], ! Date of Entry
                        SY_UPT = [2, 0, 36, 0], ! System Uptime at Time of Logging
                        SY_PSN = [3, 0, 36, 0], ! Processor Serial Number
                        SY_DAT = [4, 0, 0, 0], ! Data portion of Entry
                        SY_DTL = [4, 0, 36, 0], ! Length (in 8-bit Bytes of
                                                !  remainder of data portion
                        SY_DTS = [5, 0, 0, 0] ! Event Data String
                        tes;

                literal
                    SYSERR_HEADER_ALLOCATION = 5,
                    SYSERR_ERROR_CODE = %O'240';

                local
                    SYSERR_ENTRY : ref block field (SYSERR_FIELDS),
                    SYSERR_ALLOCATION;

!
! Allocate SYSERR Entry
!
                SYSERR_ALLOCATION = SYSERR_HEADER_ALLOCATION + ((.EB [EB_LENGTH] + 4)/4);
                SYSERR_ENTRY = NMU$MEMORY_GET (.SYSERR_ALLOCATION);
                SYSERR_ENTRY [SY_COD] = SYSERR_ERROR_CODE;
                SYSERR_ENTRY [SY_T20] = 1;
                SYSERR_ENTRY [SY_VER] = 1;
                SYSERR_ENTRY [SY_HLN] = SYSERR_HEADER_ALLOCATION - 1;
                SYSERR_ENTRY [SY_LEN] = ((.EB [EB_LENGTH] + 4)/4) + 1;
                $$GTAD (; SYSERR_ENTRY [SY_DTE]);
                begin

                local
                    MILLISECONDS;

                $$TIME (; MILLISECONDS);
                SYSERR_ENTRY [SY_UPT] = .MILLISECONDS/((1000*3600*24)/(1^18));
                                        ! Convert to Days,,Fractions of Days
                end;
                $$SYSGT (%sixbit'APRID'; SYSERR_ENTRY [SY_PSN]);
                SYSERR_ENTRY [SY_DTL] = .EB [EB_LENGTH];
                ch$move (.EB [EB_LENGTH], ch$ptr (EB [EB_BUFFER],, 8), ch$ptr (SYSERR_ENTRY [SY_DTS],, 8));
                $$SYERR (.SYSERR_ENTRY, .SYSERR_ENTRY [SY_HLN] + .SYSERR_ENTRY [SY_LEN]);
%fi
                NMU$MEMORY_RELEASE (.SYSERR_ENTRY, .SYSERR_ALLOCATION);
                NMU$MEMORY_RELEASE (.EB, .EB [EB_ALLOCATION]);
                end;
            tes;

	end;
%else
    0                                   ! To avoid empty compound expression
%fi
    end;                                !End of NML$LOGGING_FILE
%global_routine ('NML$TRANSMITTER_QUEUE_GET') =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin
%if NML$CFG_LOGGING_TRANSMITTER
%then
    !
    ! Wait on the HOST queue for an entry to be inserted
    !

    while NMU$QUEUE_SCAN (HOST_TRANSMITTER, 0, EMPTY_QUEUE_CHECK) eqla 0 do
	NMU$SCHED_WAIT (HOST_TRANSMITTER [$sub_field (TQ_QUEUE, Q_EVENT)], 0);

    HOST_TRANSMITTER                    ! Return the queue address
%else
    0
%fi
    end;                                !End of NML$TRANSMITTER_QUEUE_GET
%routine ('EMPTY_QUEUE_CHECK', ENTRY, DATA) =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin
    .ENTRY
    end;                                !End of EMPTY_QUEUE_CHECK
%routine ('GET_EVENT_BUFFER', REB : ref RAW_EVENT_BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin

    local
        EB : ref EVENT_BUFFER;          ! Event buffer

    begin

    local
        ALLOCATION;

    ALLOCATION = EVENT_BUFFER_ALLOCATION +      ! Event buffer header
                 1 +                            ! FUNCTION CODE
                 1 +                            ! SINK FLAGS
                 2 +                            ! EVENT CODE
                 2 + 2 + 2 +                    ! EVENT TIME
                 2 + 7 +                        ! SOURCE NODE
                 2 + max (0, 9, 17) +           ! EVENT ENTITY
                 .REB [REB_DATA_LENGTH];        ! EVENT_DATA

    if (EB = NMU$MEMORY_GET (.ALLOCATION)) eqla 0
    then
        return 0;                       ! No memory.

    EB [EB_ALLOCATION] = .ALLOCATION;   ! Save allocation length.
    end;

    begin                               ! Construct NICE event message

    local
        OUT_PTR;

    OUT_PTR = ch$ptr (EB [EB_BUFFER],, 8);
    ch$wchar_a (1, OUT_PTR);            ! FUNCTION CODE
    ch$wchar_a (.REB [REB_SINK_FLAGS], OUT_PTR); ! SINK FLAGS
    PUTW ((REB [REB_EVENT_CODE]), OUT_PTR); ! EVENT CODE
    begin                               ! EVENT TIME

    bind
        TB = .REB [REB_TIME_BLOCK] : TIME_BLOCK;

%if $TOPS20 or $TOPS10
%then
    local JULIAN, SECONDS;
    DECLARE_JSYS (IDCNV, ODCNV);

    $$ODCNV (.TB, 0;,,SECONDS);
    SECONDS = .SECONDS <0, 18>;         ! Seconds since midnight
    begin
    bind BASE = JULIAN;
    $$IDCNV (1977^18 + 0, 0^18, 0;,BASE); ! Get 1-JAN-77
    JULIAN = .TB - .BASE;
    JULIAN = .JULIAN <18, 18>;          ! days from then to now.
    end;
    JULIAN = .JULIAN^1;                 ! Half-days

    if .SECONDS geq 12*60*60
    then
        begin
        SECONDS = .SECONDS - 12*60*60;
        JULIAN = .JULIAN + 1;
        end;

    PUTW (JULIAN, OUT_PTR);             ! JULIAN HALF DAY
    PUTW (SECONDS, OUT_PTR);            ! SECOND
    PUTB (0, OUT_PTR);                  ! MILLISECOND
    PUTB (1^7, OUT_PTR);
%else
%if $MCB
%then
    PUTW ((TB [TIME_JULIAN]), OUT_PTR); ! JULIAN HALF DAY
    PUTW ((TB [TIME_SECOND]), OUT_PTR); ! SECOND
    PUTW ((TB [TIME_MILLISECOND]), OUT_PTR); ! MILLISECOND
%else
    PUTW (uplit (0), OUT_PTR);          ! JULIAN HALF DAY
    PUTW (uplit (0), OUT_PTR);          ! SECOND
    PUTW (uplit (0), OUT_PTR);          ! MILLISECOND
%fi
%fi
    end;
    begin                               ! SOURCE NODE

    local
        TEMP_PTR;

    TEMP_PTR = .REB [REB_SOURCE_POINTER]; ! Copy node-id in
    ch$wchar_a (ch$rchar_a (TEMP_PTR), OUT_PTR);
    ch$wchar_a (ch$rchar_a (TEMP_PTR), OUT_PTR);
                                        ! NODE ADDRESS
    OUT_PTR = ch$move (ch$rchar (.TEMP_PTR) + 1, .TEMP_PTR, .OUT_PTR);
                                        ! NODE NAME
    end;
    begin                               ! EVENT ENTITY

    local
        LENGTH;

    PUTW ((REB [REB_ENTITY_TYPE]), OUT_PTR); ! ENTITY TYPE

    selectone .REB [REB_ENTITY_TYPE] of  ! ENTITY ID
        set
        [NODE_E] :
            OUT_PTR = ch$move (2 + 1 + ch$rchar (ch$plus (.REB [REB_ENTITY_POINTER], 2)),
                               .REB [REB_ENTITY_POINTER], .OUT_PTR);
        [LINE_, CIRCUIT_, MODULE_] :
            OUT_PTR = ch$move (1 + ch$rchar (.REB [REB_ENTITY_POINTER]),
                               .REB [REB_ENTITY_POINTER], .OUT_PTR);
        [LOGGING_] :
              ch$wchar_a (ch$rchar (.REB [REB_ENTITY_POINTER]), OUT_PTR);
        [otherwise] :
            0;
        tes;

    end;
    begin                               ! EVENT DATA

    local
        LENGTH;

    if (LENGTH = .REB [REB_DATA_LENGTH]) neq 0
    then
        OUT_PTR = ch$move (.LENGTH, .REB [REB_DATA_POINTER], .OUT_PTR);

    end;
    EB [EB_LENGTH] = ch$diff (.OUT_PTR, ch$ptr (EB [EB_BUFFER],, 8));
                                        ! Insert length of message.
    end;
    .EB                                 ! Return address of buffer block.
    end;                                !End of GET_EVENT_BUFFER
%routine ('GET_LOCAL_EVENT', TASK, RESOURCE) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	None
!
!--

    begin

%if $MCB
%then

    label
        PROCESS_MESSAGE;

    literal
	EVENT_BUFFER_LENGTH = 300,
	EVENT_BUFFER_SIZE = ch$allocation (EVENT_BUFFER_LENGTH, 8),
	EVENT_BUFFER_ALLOCATION = EVENT_BUFFER_SIZE*%upval;

    external
        UN$USER : block [ch$allocation (1 + 16, 8)],
        UN$PASSWORD : block [ch$allocation (1 + 8, 8)],
        UN$ACCOUNT : block [ch$allocation (1 + 16, 8)];

    local
	RAW_BUFFER_POINTER,             ! Address of RAW Event Data
	RAW_COUNT,                      ! Length of Event Data Read
        REB : RAW_EVENT_BLOCK;          ! Event block

    RAW_BUFFER_POINTER = ch$ptr (NMU$MEMORY_GET (EVENT_BUFFER_ALLOCATION),, 8);
						! Get Single RAW Buffer
!
! Loop reading Events and copying them to Processed Buffers
!

    while $true do
PROCESS_MESSAGE:
	begin

        local
            IN_PTR;                     ! Pointer into RAW Event

!
! Read an Event and format it into the Processed Buffer
!
	IN_PTR = .RAW_BUFFER_POINTER;
        do begin
           RAW_COUNT = $NMU_NMX_READ_EVENT (.IN_PTR, EVENT_BUFFER_LENGTH);
           end
        until .RAW_COUNT gtr 0;
!
        selectoneu GETB (IN_PTR) of
            set
            [0] :                       ! Access control info
                begin

                local
                    CNT;

                ! The EXECUTOR MANAGEMENT USER

                CNT = ch$rchar (.IN_PTR) + 1;
                if .CNT gtr (1 + 16) then leave PROCESS_MESSAGE;
                ch$move (.CNT, .IN_PTR, ch$ptr (UN$USER,, 8));
                IN_PTR = ch$plus (.IN_PTR, .CNT);

                ! The EXECUTOR MANAGEMENT PASSWORD

                CNT = ch$rchar (.IN_PTR) + 1;
                if .CNT gtr (1 + 8) then leave PROCESS_MESSAGE;
                ch$move (.CNT, .IN_PTR, ch$ptr (UN$PASSWORD,, 8));
                IN_PTR = ch$plus (.IN_PTR, .CNT);

                ! The EXECUTOR MANAGEMENT ACCOUNT

                CNT = ch$rchar (.IN_PTR) + 1;
                if .CNT gtr (1 + 16) then leave PROCESS_MESSAGE;
                ch$move (.CNT, .IN_PTR, ch$ptr (UN$ACCOUNT,, 8));
                IN_PTR = ch$plus (.IN_PTR, .CNT);

                ! The EXECUTOR IDENTIFICATION

                CNT = ch$rchar (.IN_PTR);
                if .CNT gtr 32 then leave PROCESS_MESSAGE;
                NML$SET_VDB_PARAMETER (NODE_E,
                                       NMU$NETWORK_LOCAL (),
                                       100, ! IDENTIFICATION
                                       %ref(.IN_PTR));

                leave PROCESS_MESSAGE;
                end;
            [1] :                       ! Event
                ;                       ! (fall into event processing code)
            [otherwise] :               ! Undefined
                leave PROCESS_MESSAGE;
            tes;
!
	REB [REB_EVENT_CODE] = GETW (IN_PTR); ! Event Class/Type
        REB [REB_TIME_BLOCK] = 0;

	selectoneu (REB [REB_ENTITY_TYPE] = GETW (IN_PTR)) of
	    set

	    [NODE_E] : 				! Node Entity
		begin

		local
                    LENGTH,
		    TEMP_PTR;

		REB [REB_ENTITY_POINTER] = TEMP_PTR = .RAW_BUFFER_POINTER;
		ch$wchar_a (ch$rchar_a (IN_PTR), TEMP_PTR);
		ch$wchar_a (ch$rchar_a (IN_PTR), TEMP_PTR);
						! Store Node Address
		ch$wchar (0, .TEMP_PTR);        ! and set for mapping function
		LENGTH = NODE_ID_BUFFER_LENGTH;	! Maximum Length Node_ID
		$NML$MAP_NODE_ID (LENGTH, (.RAW_BUFFER_POINTER)); ! Map to Node_Id
		end;

	    [LINE_, CIRCUIT_, MODULE_] : 	! Other Entities
		begin

                local
                    LENGTH;

                REB [REB_ENTITY_POINTER] = .IN_PTR;
                LENGTH = ch$rchar (.IN_PTR) + 1;
                IN_PTR = ch$plus (.IN_PTR, .LENGTH);
		end;
	    [otherwise] : 			! No Entity
                0;
	    tes;

        REB [REB_DATA_POINTER] = .IN_PTR;
        REB [REB_DATA_LENGTH] = .RAW_COUNT - ch$diff (.IN_PTR, .RAW_BUFFER_POINTER);
!
! When we arrive here IN_PTR points at the Event Data portion of the
! Raw Event; OUT_PTR points to where the Event Data will be stored.
!

	if .REB [REB_EVENT_CODE] neq ((96 + 5)^6 + 13)
	then
	    NML$EVENT_PROCESSOR (REB)
	else
	    NML$DLW_CALL (.REB [REB_ENTITY_POINTER]);

	end;

%else
    0                                   ! To avoid empty compound expression
%fi
    end;                                ! End of GET_LOCAL_EVENT
end                                     ! End of module NMLEVT

eludom
! Local Modes:
! Mode:Bliss
! Comment Start:!
! Comment Column:40
! Comment Rounding:+1
! Auto Save Mode:2
! End: