-- Copyright (C) 1984 by Xerox Corporation. All rights reserved.
-- PupNetWatcher.mesa, HGM, 11-Feb-84 16:40:17
DIRECTORY
Ascii USING [CR],
CmFile USING [Handle, TableError],
Process USING [Detach, MsecToTicks, Ticks, Pause, Yield],
Put USING [Text],
String USING [AppendChar, AppendString, AppendNumber],
StringLookUp USING [noMatch],
System USING [GreenwichMeanTime, GetGreenwichMeanTime],
Time USING [AppendCurrent],
Token USING [Boolean],
Indirect USING [Close, NextValue, OpenSection],
NameServerDefs USING [BumpCacheSize, PupDirServerOn, PupNameServerOn],
PupDefs USING [defaultNumberOfNetworks, PupAddressLookup, PupNameTrouble],
PupRouterDefs USING [
RoutingTableEntry, RoutingTableObject, GetRoutingTableEntry, maxHop];
PupNetWatcher: PROGRAM
IMPORTS
CmFile, Process, Put, String, System, Time, Token,
Indirect, NameServerDefs, PupDefs, PupRouterDefs =
BEGIN
seconds: CARDINAL ← 15;
oneSecond: Process.Ticks = Process.MsecToTicks[1000];
oldPupRouting: ARRAY [0..maxNets] OF PupRouterDefs.RoutingTableObject;
maxNets: CARDINAL = PupDefs.defaultNumberOfNetworks;
Init: PROCEDURE =
BEGIN
off: BOOLEAN ← FALSE;
cmFile: CmFile.Handle;
Option: TYPE = {disable};
NextValue: PROCEDURE [
h: CmFile.Handle, table: LONG DESCRIPTOR FOR ARRAY Option OF LONG STRING]
RETURNS [Option] = LOOPHOLE[Indirect.NextValue];
optionTable: ARRAY Option OF LONG STRING ← [disable: "Disable"L];
cmFile ← Indirect.OpenSection["PupNetWatcher"L];
IF cmFile = NIL THEN RETURN;
DO
option: Option;
text: STRING = [200];
option ← NextValue[
cmFile, DESCRIPTOR[optionTable] !
CmFile.TableError => RETRY];
SELECT option FROM
LOOPHOLE[StringLookUp.noMatch] => EXIT;
disable =>
BEGIN
off ← Token.Boolean[cmFile];
END;
ENDCASE => ERROR;
ENDLOOP;
Indirect.Close[cmFile];
IF ~off THEN Process.Detach[FORK Watch[]];
END;
Watch: PROCEDURE =
BEGIN
time: System.GreenwichMeanTime ← System.GetGreenwichMeanTime[];
Process.Pause[120*oneSecond];
InitializeThings[];
DO
WHILE (System.GetGreenwichMeanTime[] - time) < seconds DO
Process.Pause[oneSecond]; ENDLOOP;
time ← System.GetGreenwichMeanTime[];
CheckNetState[];
THROUGH [0..100) DO Process.Yield[]; ENDLOOP;
ENDLOOP;
END;
InitializeThings: PROCEDURE =
BEGIN
FOR net: CARDINAL IN (0..maxNets] DO
rte: PupRouterDefs.RoutingTableEntry ← PupRouterDefs.GetRoutingTableEntry[
[net]];
IF rte = NIL OR rte.hop > PupRouterDefs.maxHop THEN
oldPupRouting[net].network ← NIL
ELSE oldPupRouting[net] ← rte↑;
ENDLOOP;
BEGIN
wordsPerNet: CARDINAL = 20;
wordsPerPath: CARDINAL = 40;
NameServerDefs.BumpCacheSize[50*wordsPerNet + 3*wordsPerPath];
NameServerDefs.PupDirServerOn[];
NameServerDefs.PupNameServerOn[];
END;
END;
CheckNetState: PROCEDURE =
BEGIN
FOR net: CARDINAL IN (0..maxNets] DO
rte: PupRouterDefs.RoutingTableEntry ← PupRouterDefs.GetRoutingTableEntry[
[net]];
rto: PupRouterDefs.RoutingTableObject;
-- It would be nice if there were a simple way to do this atomically
IF rte # NIL THEN rto ← rte↑;
IF (rte = NIL AND oldPupRouting[net].network = NIL)
OR (rto.network = NIL AND oldPupRouting[net].network = NIL)
OR (rto.hop > PupRouterDefs.maxHop AND oldPupRouting[net].network = NIL)
OR
(oldPupRouting[net].network = rto.network
AND oldPupRouting[net].route = rto.route
AND oldPupRouting[net].hop = rto.hop) THEN LOOP;
BEGIN
text: STRING = [100];
via: STRING = [20];
Time.AppendCurrent[text];
String.AppendString[text, " "L];
BEGIN ENABLE PupDefs.PupNameTrouble =>
BEGIN
String.AppendNumber[text, net, 8];
String.AppendString[text, "##"L];
CONTINUE;
END;
PupDefs.PupAddressLookup[text, [[net], [0], [0, 0]]];
String.AppendString[text, " ("L];
String.AppendNumber[text, net, 8];
String.AppendString[text, "##)"L];
END;
String.AppendString[text, " is "L];
SELECT TRUE FROM
rte = NIL, rto.network = NIL, rto.hop > PupRouterDefs.maxHop =>
String.AppendString[text, "unreachable"L];
(rto.route = 0) => String.AppendString[text, "directly connected"L];
ENDCASE =>
BEGIN
String.AppendNumber[text, rto.hop, 10];
String.AppendString[text, " hop"L];
IF rto.hop # 1 THEN String.AppendChar[text, 's];
String.AppendString[text, " via "L];
PupDefs.PupAddressLookup[
via, [[rto.network.pupNetNumber], [rto.route], [0, 0]] !
PupDefs.PupNameTrouble =>
BEGIN
String.AppendNumber[text, rto.network.pupNetNumber, 8];
String.AppendChar[text, '#];
String.AppendNumber[text, rto.route, 8];
String.AppendChar[text, '#];
CONTINUE;
END];
String.AppendString[text, via];
END;
LogString[text];
IF rte = NIL OR rto.hop > PupRouterDefs.maxHop THEN
oldPupRouting[net].network ← NIL
ELSE oldPupRouting[net] ← rto;
END;
THROUGH [0..1000) DO Process.Yield[]; ENDLOOP; -- Wait longer if things are busy
Process.Pause[5*oneSecond];
ENDLOOP;
END;
LogString: PROCEDURE [text: LONG STRING] =
BEGIN
String.AppendChar[text, '.];
String.AppendChar[text, Ascii.CR];
Put.Text[NIL, text];
END;
-- initialization
Init[];
END.