Google
 

Trailing-Edge - PDP-10 Archives - BB-X117B-SB_1986 - 10,7/nml/nmlxmt.bli
There are 2 other files named nmlxmt.bli in the archive. Click here to see a list.
! UPD ID= 299, SNARK:<6.1.NML>NMLXMT.BLI.4,  27-Apr-85 17:09:57 by GLINDELL
!   Issue better error message if user does TELL 500 and node 500 is not
!   defined in the node database.
!
! UPD ID= 211, SNARK:<6.1.NML>NMLXMT.BLI.3,  10-Dec-84 15:40:42 by HALPIN
! Get MONSYM Library file out of default directory, not BLI:
!
! UPD ID= 93, SLICE:<6.1.NML>NMLXMT.BLI.2,  18-Sep-84 15:19:13 by GUNN
! WORK:<GUNN.NML>NMLXMT.BLI.2 21-Aug-84 12:13:46, Edit by GUNN
!
! Change to accomodate new LIBRARY conventions. MONSYM.L36 and JLNKG.L36
! are now explicity declared here rather than in NMULIB.
!
!  Ident 19.
!    Fix CONNECT_TO_REMOTE to return the remote version number in the.
!    request block.  Merge CHECK_VERSION into CONNECT_TO_REMOTE and
!    NML$CNV_CHECK_VERSION.  Use version number to convert the command
!    message where necessary.
!
! PH4:<PECKHAM>NMLXMT.BLI.2  8-Jun-83 07:54:14, Edit by PECKHAM
!
!  Ident 18.
!    Augghhh! Fix CHECK_VERSION again to allow version 3!
!
! PH4:<PECKHAM>NMLXMT.BLI.2  7-Jun-83 16:25:36, Edit by PECKHAM
!
!  Ident 17.
!    The previous version check disallowed us from talking to higher
!    version NMLs.  Fix CHECK_VERSION to only verify version is
!    higher than 3.
!
! PH4:<PECKHAM>NMLXMT.BLI.7 27-May-83 15:29:11, Edit by PECKHAM
!
!  Ident 16.
!    Make CHECK_VERSION check the versions between "3" and ".NMLVER"
!    for V4.0 <-> V3.0 support.
!
!    Correct response buffer length allocation in CONNECT_TO_REMOTE,
!    which was set incorrectly to 120 bytes by merge.
!
!    The other suspect code is the change around $NML$MAP_NODE_ID.
!    The changes are undocumented, but it appears that
!       1) a change was made to set CB_HOST_LENGTH *after* $NML$MAP_NODE_ID
!          instead of before.  This seems reasonable.
!       2) a change causes connect failure if the $NML$MAP_NODE_ID fails.
!          This seems reasonable for TOPS20, where the name is essential
!          in order to connect out, but not extendable.
!
!NET:<BRANDT.DEVELOP>NMLXMT.BLI.1 12-Dec-82 20:34:50, Edit by BRANDT
!
!  Ident 15.
!    In CONNECT_TO_REMOTE allocate the same size response block that
!    is required in RECEIVE_RESPONSE.
!
!NET:<BRANDT.DEVELOP>NMLXMT.BLI.1  9-Dec-82 16:39:05, Edit by BRANDT
!
!  Ident 14.
!    In RECEIVE_RESPONSE  do not allocate a new response buffer if
!    one is already allocated.  Just reuse it.
!
!NET:<BRANDT.DEVELOP>NMLXMT.BLI.1  29-Sep-82 16:29:05, Edit by BRANDT
!
!  Ident 13.
!    In RECEIVE_RESPONSE put NMU$NETWORK_READ in a loop so that if a 
!    timeout occurs, the operation can be retried several times.
!    For lengthy operations (LOOP or LOAD for example) on a remote
!    executor, the response message may be slow in coming.
!
!NET:<BRANDT.DEVELOP>NMLXMT.BLI.1  19-Jan-82 09:29:05, Edit by BRANDT
!
!    Ident 12.
!    Make error detail field of $RESPONSE message null rather than 0.
!    Allow for MEMORY_GET to fail in RECEIVE_RESPONSE.
!
! NET:<PECKHAM.DEVELOPMENT>NMLXMT.BLI.3 24-May-82 12:40:13, Edit by PECKHAM
!
! Ident 11.
! Add CHECK_VERSION routine.
! Use CHECK_VERSION in CONNECT_TO_REMOTE to abort connects to V2.0 receivers.
!
!NET:<BRANDT.DEVELOP>NMLXMT.BLI.1  19-Jan-82 09:29:05, Edit by BRANDT
!
!    Ident 10.
!    Add a call to NML$REQUEST_TERMINATE in NML$TRANSMITTER to handle
!    the situation of a read response failure while in the middle of
!    a sequence of multiple responses.
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.8  2-Nov-81 11:29:05, Edit by WEBBER
!
!    Ident 09.
!    Add recognition of the -2 NETWORK_OPEN return code ("don't retry").
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.2 21-Oct-81 10:05:41, Edit by WEBBER
!
!    Ident 08.
!    Add response buffer and its length as parameters to NETWORK_OPEN.
!    NETWORK_OPEN will build a response message on an error.
!
!NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLXMT.BLI.8  5-Aug-81 10:42:19, Edit by JENNESS
!
!    Ident 07.
!    Fix CONNECT_TO_REMOTE to retry a limited number of times and
!    then fail the request.
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.4 15-Jun-81 10:39:45, Edit by GUNN
!
!    Ident 06.
!    Fix loop caused when NMU$NETWORK_READ in RECEIVE_RESPONSE fails.
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.2 12-Jun-81 14:20:23, Edit by GUNN
!
!    Ident 05.
!    Fix call to $NML$MAP_NODE_ID in PROCESS_ENTITY_CLASS to pass 
!    address of length not literal.
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.3  6-May-81 10:34:43, Edit by JENNESS
!
!    Change TASK_ERROR ('Read failure') on response read to build a
!    operation failure response message.
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.2  3-Apr-81 17:50:34, Edit by GUNN
!
!    Add dot to second argument to $NML$MAP_NODE_ID.
!
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.3 31-Mar-81 08:01:02, Edit by GUNN
!
!    Remove 'language (common)' from module header. $NML$MAP_NODE_ID
!    expands into system specific code.
! 
!NET:<DECNET20-V3P1.NML>NMLXMT.BLI.3 11-Mar-81 09:29:35, Edit by GUNN
!
!    Change format of node name string passed to NMU$NETWORK_OPEN in the
!    Connect Block CB_HOST field to be same as NODE entity id.
!    Add code to map EXECUTOR node address to node name.
!    Update copyright date.
!
%title 'NMLXMT -- NICE Request Transmitter'
module NMLXMT (                         ! NICE request transmitter task
		ident = 'X03.19'
		) =
begin
!
! COPYRIGHT (C) 1980, 1981, 1982
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS  01754
!
! THIS SOFTWARE IS FURNISHED  UNDER A LICENSE FOR USE ONLY ON A SINGLE
! COMPUTER  SYSTEM AND  MAY BE  COPIED ONLY 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
! EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE
! TERMS.  TITLE TO AND  OWNERSHIP OF THE  SOFTWARE  SHALL AT ALL TIMES
! REMAIN IN DEC.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD  NOT BE CONSTRUED  AS A COMMITMENT  BY DIGITAL  EQUIPMENT
! CORPORATION.
!
! DEC ASSUMES  NO  RESPONSIBILITY  FOR  THE USE OR  RELIABILITY OF ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
!

!++
! Facility: LSG DECnet Network Management
!
! Abstract: This task takes the next request from the request
!	    queue destined for a remote node, transmits it and
!	    waits for the response.
!
! Environment: TOPS10/TOPS20 user mode, MCB RSX task level
!
! Author: Steven M. Jenness, Creation date: 1-Dec-80
!
!--
!
! Include files
!

library 'NMLLIB';			! All needed definitions

%if $TOPS20
    %then
	library 'MONSYM';			! Monitor symbols

	library 'JLNKG';			! JSYS linkage definitions
    %fi

!
! Global routines
!

forward routine
    NML$TRANSMITTER : novalue;		! Main routine for transmitter task

!
! Local routines
!

forward routine
    LOCK_REMOTE_NODE : novalue,    ! Place lock to insure request sequentiality
    CONNECT_TO_REMOTE,             ! Make connection to remote NICE process
    RECEIVE_RESPONSE,              ! Read next response message
    UNLOCK_REMOTE_NODE : novalue;  ! Unlock node

!
! External references
!

external routine
    NML$CNV_CHECK_VERSION,         ! Check if supported version
    NML$CNV_COMMAND,               ! Convert V4 command to earlier version
    NML$REQUEST_MANAGER,           ! Central NICE request handler
    NMU$NETWORK_UTILITIES,         ! DECnet logical link interface
    NMU$MEMORY_MANAGER,            ! Memory management routines
    NMU$SCHED_MANAGER;             ! Scheduler interface

external
    NMLVER,                        ! Version of Network Management
    DECECO,                        ! Digital's ECO number
    USRECO;                        ! User's ECO number

!
! Equated symbols
!

literal
    FIVE_SECONDS = 5,
    TEN_SECONDS = 10,
    NICE_BUFFER_LENGTH = 300,					! Bytes
    NICE_BUFFER_SIZE = ch$allocation (NICE_BUFFER_LENGTH, 8),   ! Words
    NICE_BUFFER_ALLOCATION = NICE_BUFFER_SIZE * %upval;         ! Units

!
! Own variables
!

own
   XMTR_RETRIES : initial (5);
%global_routine ('NML$TRANSMITTER', TB, TR) : novalue =

!++
! Functional description:
!
!	This task runs forever (almost) removing remote requests
!	from the request queue and sending them to the appropriate
!	remote node for processing.
!
! Formal parameters:
!
!	.TB	Task block address
!	.TR	Task resource address
!
! Routine value: none
! Side effects: none
!
!--

    begin

    while $true do
	begin

        local
            REQ : ref REQUEST_BLOCK,
            LINK_ID;

!
! Get next request to send to the remote node
!
	REQ = NML$REQUEST_NEXT (RT$REMOTE);
!
! Lock node to guarantee command sequentiality
!
	LOCK_REMOTE_NODE (.REQ);
!
! Connect to remote NICE processor.
!

	if (LINK_ID = CONNECT_TO_REMOTE (.REQ)) gtr 0
        then
            begin

            !
            ! Convert command to earlier version if necessary
            !

            NML$CNV_COMMAND (.REQ);

            !
            ! Send the request
            !

            NMU$NETWORK_WRITE (.LINK_ID, $true,
                               .REQ [RB_NICE_LENGTH],
                               ch$ptr (.REQ [RB_NICE],, 8));
            !
            ! Receive all response messages to the request
            !

            do
              begin
              if not RECEIVE_RESPONSE (.LINK_ID, .REQ)
              then
                  begin
                  if not NML$REQUEST_FINISH (.REQ)
                  then NML$REQUEST_TERMINATE (.REQ) ; ! If not done, Abort it
                  exitloop;
                  end;
              end
            until NML$REQUEST_FINISH (.REQ);

            !
            ! Discard the link (done with the request)
            !

            NMU$NETWORK_CLOSE (.LINK_ID, 0, 0);
            end
        else
            !
            ! Finish off request that failed to connect
            !

            NML$REQUEST_FINISH (.REQ);

        !
        ! Unlock node to allow other requests to be sent
        ! to the node.
        !

        UNLOCK_REMOTE_NODE (.REQ);
        end;
    end;					! End of NML$TRANSMITTER

%routine ('LOCK_REMOTE_NODE', REQUEST : ref REQUEST_BLOCK) : novalue =

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

    begin
	$true
    end;					! End of LOCK_REMOTE_NODE
%routine ('UNLOCK_REMOTE_NODE', REQUEST : ref REQUEST_BLOCK) : novalue =

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

    begin
	$true
    end;					! End of UNLOCK_REMOTE_NODE
%routine ('CONNECT_TO_REMOTE', REQUEST : ref REQUEST_BLOCK) =

!++
! Functional description:
!
!	This routine connects to the NICE listener on the
!	host specified in the request.  It does not return
!	until the connection is made (or determined to be
!	next to impossible).
!
! Formal parameters:
!
!	.REQUEST    Address of request block
!
! Routine value:
!
!	Link id of DECnet link to remote NICE listener
!
! Side effects: none
!
!--

    begin
    local
	CONN_BLK : CONNECT_BLOCK,
	NODE_PTR,
	DATA_PTR,
	LINK_ID,
        ATTEMPTS_LEFT,
	CONNECTED;

!
! Allocate response buffer outside of loop
!
    REQUEST [RB_RESPONSE_ALLOCATION] = NICE_BUFFER_ALLOCATION;
    if (REQUEST [RB_RESPONSE] = NMU$MEMORY_GET (.REQUEST [RB_RESPONSE_ALLOCATION])) neq 0
    then REQUEST [RB_RESPONSE_LENGTH] = NICE_BUFFER_LENGTH
    else begin
         REQUEST [RB_RESPONSE_ALLOCATION] = 0;
         REQUEST [RB_RESPONSE] = REQUEST[RB_RETURN_CODE];
         REQUEST [RB_RESPONSE_LENGTH] = 1;
         REQUEST [RB_RETURN_CODE] = NICE$_REE;
         return 0
         end;

    CONNECTED = $false;
    ATTEMPTS_LEFT = .XMTR_RETRIES;

    while not .CONNECTED
    do
	begin
        local
             LENGTH ;                   ! Length temporary for MAPping

	CONN_BLK [CB_OBJECT] = NICE_OBJECT;
	CONN_BLK [CB_DESCRIPTOR_LENGTH] = 0;
	CONN_BLK [CB_TASK_LENGTH] = 0;

	NODE_PTR = ch$ptr (.REQUEST [RB_EXECUTOR],, 8);

	!
	! Attempt to map node address to node number
	!

        LENGTH = NODE_ID_BUFFER_LENGTH ; ! Get buffer length
	begin
	    local
		TEMP;	! Holds return value from MAP function

	    TEMP = $NML$MAP_NODE_ID (LENGTH, .NODE_PTR) ;

	    if .TEMP neq NICE$_SUC then
	    begin
		REQUEST [RB_RESPONSE_LENGTH] =
		$RESPONSE (ch$ptr (.REQUEST [RB_RESPONSE],,8),
			   .TEMP,,);
		return -1
	    end;

            ! Check length to see if MAP node failed or succeeded
            if .LENGTH leq 3
            then begin
                REQUEST [RB_RESPONSE_LENGTH] =
                $RESPONSE (ch$ptr (.REQUEST [RB_RESPONSE],,8),
                           NICE$_IID,
                           ,
                           'Node address has no matching node name');
                return -1
            end;
	end;

	CONN_BLK [CB_HOST_LENGTH] = ch$rchar (ch$plus (.NODE_PTR, 2));
	CONN_BLK [CB_HOST] = .NODE_PTR;

	CONN_BLK [CB_USERID_LENGTH] = .REQUEST [RB_USER_LENGTH];
	CONN_BLK [CB_USERID] = .REQUEST [RB_USER];

	CONN_BLK [CB_ACCOUNT_LENGTH] = .REQUEST [RB_ACCOUNT_LENGTH];
	CONN_BLK [CB_ACCOUNT] = .REQUEST [RB_ACCOUNT];

	CONN_BLK [CB_PASSWORD_LENGTH] = .REQUEST [RB_PASSWORD_LENGTH];
	CONN_BLK [CB_PASSWORD] = .REQUEST [RB_PASSWORD];

	CONN_BLK [CB_DATA_LENGTH] = 3;
	DATA_PTR = ch$ptr (CONN_BLK [CB_DATA_BUFFER],, 8);
	CONN_BLK [CB_DATA] = .DATA_PTR;
	ch$wchar_a (.NMLVER, DATA_PTR);
	ch$wchar_a (.DECECO, DATA_PTR);
	ch$wchar_a (.USRECO, DATA_PTR);

        if .REQUEST [RB_RESPONSE] eqla 0    ! If no response buffer is
        then				    ! allocated yet, set one up.
            begin
            REQUEST [RB_RESPONSE_ALLOCATION] = NICE_BUFFER_ALLOCATION;
            REQUEST [RB_RESPONSE] =
              NMU$MEMORY_GET (.REQUEST [RB_RESPONSE_ALLOCATION]);
	    end;

	if (LINK_ID = NMU$NETWORK_OPEN (SOURCE_LINK, CONN_BLK, 
	    ch$ptr(.REQUEST[RB_RESPONSE],,8), REQUEST[RB_RESPONSE_LENGTH],
	    NICE$_LCF))
	lss 0
	then
            if ((.LINK_ID neq -2) and
	    ((ATTEMPTS_LEFT = .ATTEMPTS_LEFT - 1) gtr 0))
            then
                NMU$SCHED_SLEEP (TEN_SECONDS)
            else
                return 0
	else
            begin

            selectone .CONN_BLK[CB_DATA_LENGTH] of
                set
                [0] : REQUEST[RB_VERSION] = 2;
                [3] : REQUEST[RB_VERSION] = ch$rchar (.CONN_BLK[CB_DATA]);
                [otherwise] :
                    begin
                    REQUEST[RB_RESPONSE_LENGTH] = $RESPONSE (ch$ptr(.REQUEST[RB_RESPONSE],,8), $NICE$ERR_IID);
                    NMU$NETWORK_ABORT (.LINK_ID, $SC$ERR_UAB, 0, 0);
                    return 0;
                    end;
                tes;

            if not NML$CNV_CHECK_VERSION (.REQUEST[RB_VERSION])
            then begin
                 NMU$NETWORK_ABORT (.LINK_ID, $SC$ERR_UAB, 0, 0);
                 return 0;
                 end;

            CONNECTED = $true
            end;

	end;

    .LINK_ID
    end;					! End of CONNECT_TO_REMOTE
%routine ('RECEIVE_RESPONSE', LINK_ID, REQUEST : ref REQUEST_BLOCK) =

!++
! Functional description:
!
!	This routine receives the response from a NICE processor
!	at the other end of a DECnet logical link.
!
! Formal parameters:
!
!	.LINK_ID    Identifier for DECnet logical link
!	.REQUEST    Address of request block
!
! Routine value: TRUE, if response received OK.
!                FALSE, otherwise.
! Side effects: none
!
!--

    begin
    local
	TEXT,
	TIMES;

    if .REQUEST [RB_RESPONSE] eqla 0    ! If no response buffer is
    then				! allocated yet, set one up.
        begin
        REQUEST [RB_RESPONSE_ALLOCATION] = NICE_BUFFER_ALLOCATION;
        REQUEST [RB_RESPONSE] =
            NMU$MEMORY_GET (.REQUEST [RB_RESPONSE_ALLOCATION]);
	end;

    REQUEST [RB_RESPONSE_LENGTH] = 0;

    TIMES = (if ((.REQUEST[RB_NICE_FUNCTION] eql LOAD_) or
		 (.REQUEST[RB_NICE_FUNCTION] eql TEST_))
	     then 3			! Wait longer for LOAD and LOOP
	     else 1);

    incr N from 1 to .TIMES do
	begin
	if (REQUEST [RB_RESPONSE_LENGTH] =
		NMU$NETWORK_READ (.LINK_ID,
			          NICE_BUFFER_LENGTH,
				  ch$ptr (.REQUEST [RB_RESPONSE],, 8)))
	    gtr 0
	then
	    return $TRUE;		! If read successful, all done!

	if .REQUEST [RB_RESPONSE_LENGTH] eql -1  ! Indicates timeout
	then
	    TEXT = CH$ASCIZ('Timed out waiting for response')
	else
	    begin
	    TEXT = CH$ASCIZ('Response read failed');
	    exitloop;			! Break now to signal failure
	    end;
	end;

    REQUEST [RB_RESPONSE_LENGTH] =
           $RESPONSE (ch$ptr (.REQUEST [RB_RESPONSE],, 8),
                      NICE$_OPF, , '%A', .TEXT);
    return $FALSE;
	
    end;				! End of RECEIVE_RESPONSE
end					! End of module NMLXMT

eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:0
! Comment Column:40
! Comment Rounding:+1
! End: