-- 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.