{ 
  Desc: Master (Global) include file for AMIRTR
  File: [22,310]AMIRTR.INC
  Author: Jim Bostwick 
  Last Edit: 20-DEC-1989 23:23:17 
  History:  
	26-OCT-1989 - JMB - add proper debug code
	 9-OCT-1989 - JMB - major happy munging...
	27-JAN-1989 - JMB - Rework Link array for simplicity. 

  Note: A slight departure from past practice - this is something like
	a package file in that it includes top-level stuff (e.g., General.typ)
	and defines global data. The goal is to reduce the number of include
	files which must be opened by the compiler. Theoretically, this
	file may be turned into a true package (by pre-expanding all includes)
	as it nears completion. 

	Including external definitions which aren't referenced does no harm,
	even in an overlay situation, because the compiler doesn't generate
	the .GLOBL reference until a call to the routine is actually built.
}
{$Nolist}

{*USER*

 Global data for AMIRTR is organized around an array of 'link records',
which contain all necessary information to manage a decnet link. The array
is (obviously) fixed in size, which governs the maximum number of open links
available to the program. Constant 'Max_Links' sets this size. 
.note
This does not limit the number of 
possible nodes in the 'message net', but does potentially impact performance
due to excessive link creation and destruction. In general, specify enough
links for the expected number of 'active' connections - certainly enough
to handle all concurrently active ones. 
 At the same time, be aware of limits in decnet (NCP MAX LINKS parameter). 
Also, links take resources inside DECNET - comexec, pool, etc. 
.end note 
.hl 2
 LUNS are assigned in a block, starting with Lo_Net_LUN and proceeding until
one LUN per link plus one for the network mailbox (Max_Links + 1 LUNS) have
been assigned. User program MUST stay away from these LUNS! This means either
assigning them with 'high' numbers, or using 'low' numbers, and forcing
Pascal Opens to use higher ones. 
 Link 0 (Link[0]) is used with the net mailbox lun. Not all fields of Link 0 
are used. However, the statistics record in particular shows activity on 
the mailbox. 
 The link record also contains a couple of fields for convenience - 
notably the 'active' boolean, and node name. These duplicate information
available elsewhere in the record, but eliminate the need to dig it out
each time. 
.hl 2 EFNs
 Two global EFNs are defined. Net_EFN is the generic network activity EFN
(also used for SRDA ast notification and other things). Aux_EFN is just
a random flag which is used for 'throw-away' things - a scratch EFN if 
you will... 
 }

{*WIZARD*

.hl 2 Statistics
 Link Statistics are kept for each link in the Link_Statistics_rec, and
may be reported using router control messages. 
Link statistics are kept for two reasons. The important one is to enable
the program to determine which link to drop if more are requested than
are available. Note that this shouldn't happen too often; if it does, 
rebuild with more links available. The second reason is for debugging
and system tuning. 
.hl 3 Last Activity 
 The Last Activity timer shows roughly how long it has been since
a link passed a message (either in- or outbound). This is a high-granularity
timer (Activity_Units, Activity_Time; initial default =10sec.) to avoid 
overloading the program with timer service. 
 Each time a link is used, the Last_Activity field is zeroed. A single, 
program-wide, timer increments the field for all active links each time
it is serviced. Timer service occurs in the main loop, after all net
and message traffic has been dealt with. Thus on a buisy system (or program),
the timer will tend to 'slow down'. In any case, the (active) link with
the largest value in Last_Activity is the 'least-recently-used' link. 
.note
A better algorithm would account for volume of usage as well as time. 
For example, a link which sends a wad of messages at regular but relatively
long intervals, will get blown away if a bunch of sporadic links come
active at one time. Eventually, the low-volume guys will fade away, but
we'd like the heavy hitter to hand around. 
 One approach would be to give each new link a 'budget' at creation. The
activity timer would decrement the budget, while any activity would
increment it. By balancing the timer cost (decrement) against the 
use-reward (increment), we could keep those heavy hitters in there, while
getting rid of the 'one-shot' links that much sooner. 
.end note
.hl 3 Reads, Writes
 These real values contain the count of inbound and outbound network
traffic. Retries (if ever defined) are NOT counted. These are reals only
to allow large values - the increment is always 1.0. 
.hl 3 Connects
 This is an integer counter of the number of times this link has been 
opened since program startup. Big numbers here are generally bad - indicating
either a weak link (dropping all the time) or too few links (forcing
the program to kill off and re-incarnate constantly). 
&&&&&
 }
{[a+,b+,l-,k+,r+] Pasmat }
{$List}

CONST
    Max_Links = 4; 	{ maximum number of concurrently open net links }
    Lo_Net_LUN = 7; 	{ will allocate LUNS 7 and up NS: 		}
    Mbx_LUN = Lo_Net_LUN;   	{ a handy synonym 			}
    Net_EFN = f15;  	{ make group global to be nice, global for easy debug }
    Aux_EFN = f16; 	{ generic EFN 					}
    Activity_Units = seconds; 	{ time units for activity timer 	}
    Activity_Count = 10; 	{ e.g, 10 sec. activity timer		}
    Activity_EFN = f14; 	{ flag set when timer expires 		}

    Null_Task_String = CH6('0','0','0','0','0','0');
				{ Don't care parameter for some calls  	}
  
TYPE

    { Define link control and status flags }
    Link_Flag_typ = (Link_Active, Link_Shutdown);

    { Define some pointer types }
    Connect_Block_Ptr = ^Net_Connect_Block;
    Request_Block_Ptr = ^Net_Request_Block;

    { Define Link Statistics Record }
    Link_Statistics_rec = RECORD;
	Last_Activity: integer;		{ time units since active 	}
	Reads,Writes: Real;		{ count of traffic in, out	}
	Connects: Integer;		{ count of network opens 	}
	END;  { Link_Statistics_rec }

    { Define master link database record }
    Link_Record = RECORD		{ the master link record    	}
	LUN : Integer;			{ LUN used by this link    	}
	Read_IOSB: IO_Status_Block; 	{ network read IOSB for this link }
	Node: CH6; 			{ Copy of remote node name      }
    	Task: CH16;			{ copy of remote task name 	}
	Read_Dat: CH16; 		{ net (mbx) message inbound 	}
  	Msg: Message_rec;		{ the net message 		}
	Stats: Link_Statistics_rec;	{ link activity numbers 	}
	Link_Flags: Set of Link_Flag_typ; { link status flags		}
	Active: Boolean; 		{ TRUE if link in use    	}
	END; 	{ Link_Record }


VAR
    I: Integer; 		{ every program needs a generic integer!}
    Status: Integer; 		
    L: 0..Max_Links; 		{ global link index 			}
    Crash_Request: Boolean;	{ TRUE if we're dead but don't know it 	}
    Exit_Request: Boolean; 	{ TRUE if we've been asked to quit	}	
    Log_file: Text;		{ log file 				}

    Null_IOSB: IO_Status_Block;  { dummy for use in SIGNAL calls 	}
    IOSB: IO_Status_Block; 	{ generic status block			}
    MyName: Rad56; 		{ "AMIRTR" in RAD-50			}

    MyNode: CH6;		{ node name currently executing on 	}
    Trademark: str40;		{ node::name> 	for logging 		}
    Loc_Msg: Message_rec;	{ message buffer for GETMSG 		}
    Conb: Net_Connect_Block;	{ for use with inbound requests		}
    ReqB: Net_Request_Block;	{ for use in outbound link requests	}

    Link: Array [0..Max_Links] of Link_Record; { the master link database }
					       { link[0] is net mailbox   }
{ Debugging stuff. We can debug at various levels. Output can be to 
    a file or tt:, via messages, or both. }

    Debugging: Boolean;		{ TRUE if DEBUG enabled at some level   }
    Debug_to_file: Boolean; 	{ TRUE if debug output to file or tt:   }
    Debug_to_msg: Boolean; 	{ TRUE if debug output via messages	}
    Debug_level: Integer;	{ Level we're debugging at, meaningless
    				  if DEBUG is FALSE 			}
    Debug_flags: Message_packet_sub_set;
    				{ Experiment: are enough of these useful? }
    Debug_Msg: Message_rec;	{ Message for debug out put via message }
    Debug_width:Integer;	{ Width of debug output		   	} 
    Debug_file: Text;		{ File for debug output to file or tt:  }
    Debug_file_name: CH40;	{ Filespec for debug output		}
    Debug_task:Ch6;		{ Task name for debug output via msg	}
    Debug_node:Ch6;		{ Node debug sink task lives on 	}

