-- Copyright (C) 1984 by Xerox Corporation. All rights reserved. -- PupDirServerNoDisk.mesa, HGM, 1-Jul-84 2:01:01 -- We don't have a copy of the file, but we keep a BIG cache of things we find -- on other servers so we can pass the service on to clients on adjacent nets. -- This module watches the directory version on the net, and flushes the cache -- so it will get reloaded with current information. DIRECTORY Ascii USING [CR], Process USING [Detach, SetTimeout, MsecToTicks], Put USING [Text], String USING [AppendChar, AppendString, AppendDecimal], Time USING [AppendCurrent], Buffer USING [AccessHandle, DestroyPool, GetBuffer, MakePool, ReturnBuffer], MiscServerDefs USING [PupMiscServerOn, SetDirectoryServer], NameServerDefs USING [ lockDirRequest, lockDirReply, unlockDirRequest, unlockDirReply, FlushWholeCache, PupNameServerOn, BumpCacheSize], PupDefs USING [ AppendHostName, GetPupContentsBytes, PupBuffer, PupRouterBroadcastThis, PupSocket, PupSocketDestroy, PupSocketID, PupSocketMake, SecondsToTocks, SetPupContentsWords, ReturnPup, UniqueLocalPupSocketID], PupTypes USING [fillInPupAddress, miscSrvSoc, PupAddress], Stats USING [StatCounterIndex, StatIncr]; PupDirServerNoDisk: MONITOR IMPORTS Process, Put, String, Time, Buffer, MiscServerDefs, NameServerDefs, PupDefs, Stats EXPORTS NameServerDefs = BEGIN OPEN Stats, NameServerDefs, PupDefs; dirRunning, probing, sending: PUBLIC BOOLEAN ← FALSE; useCount: CARDINAL ← 0; pleaseStop: BOOLEAN ← FALSE; probePeriod: CARDINAL ← 60; -- in minutes tries: CARDINAL ← 0; delay: CONDITION; lock: BOOLEAN ← FALSE; verbose: BOOLEAN = TRUE; currentVersion: CARDINAL ← 0; oldVersionAround: BOOLEAN ← TRUE; fileName: STRING = "Pup-Network.directory"; statVers, statSend: PUBLIC StatCounterIndex; GetNewDirectoryVersion, GetOldDirectoryVersion: PUBLIC PROCEDURE RETURNS [CARDINAL, BOOLEAN] = BEGIN RETURN[currentVersion, FALSE]; END; PupDirServerOn: PUBLIC PROCEDURE = BEGIN IF (useCount ← useCount + 1) = 1 THEN BEGIN dirRunning ← TRUE; Starter[]; END; END; Starter: PROCEDURE = BEGIN pleaseStop ← FALSE; MiscServerDefs.PupMiscServerOn[]; MiscServerDefs.SetDirectoryServer[PupDirServer]; Process.Detach[FORK ProbeGovenor[]]; END; CountTries: ENTRY PROCEDURE = BEGIN tries ← tries + 1; END; KickProber: PUBLIC ENTRY PROCEDURE = BEGIN IF tries > 3 THEN RETURN; StartProbing[]; END; StartProbingForDirectory: PUBLIC ENTRY PROCEDURE = BEGIN StartProbing[]; END; StartProbing: INTERNAL PROCEDURE = BEGIN IF pleaseStop OR probing THEN RETURN; probing ← TRUE; Process.Detach[FORK Probe[]]; END; ProbeGovenor: ENTRY PROCEDURE = BEGIN n: CARDINAL ← 1; -- probe 1 min after startup Process.SetTimeout[@delay, Process.MsecToTicks[60000]]; UNTIL pleaseStop DO WAIT delay; -- one minute IF probing THEN BEGIN n ← probePeriod; LOOP; END; IF (n ← n - 1) = 0 THEN BEGIN tries ← 0; StartProbing[]; WHILE probing DO WAIT delay; ENDLOOP; n ← probePeriod; END; ENDLOOP; END; Probe: PROCEDURE = BEGIN b: PupBuffer; from: PupSocketID ← UniqueLocalPupSocketID[]; pool: Buffer.AccessHandle; soc: PupSocket; bestSoFar: CARDINAL; where: PupTypes.PupAddress; sawOldVersion: BOOLEAN ← FALSE; bestSoFar ← currentVersion; pool ← Buffer.MakePool[send: 1, receive: 10]; soc ← PupSocketMake[from, PupTypes.fillInPupAddress, SecondsToTocks[1]]; THROUGH [0..5) UNTIL bestSoFar > currentVersion DO b ← Buffer.GetBuffer[pup, pool, send]; b.pup.source.socket ← from; b.pup.dest.socket ← PupTypes.miscSrvSoc; b.pup.pupType ← netDirVersion; b.pup.pupWords[0] ← 0; b.pup.pupWords[1] ← 0; SetPupContentsWords[b, 2]; PupRouterBroadcastThis[b]; UNTIL b = NIL DO b ← soc.get[]; IF b # NIL THEN BEGIN IF b.pup.pupType = netDirVersion THEN BEGIN SELECT b.pup.pupWords[0] FROM > bestSoFar => BEGIN bestSoFar ← b.pup.pupWords[0]; where ← b.pup.source; END; < currentVersion => sawOldVersion ← TRUE; ENDCASE => NULL; IF GetPupContentsBytes[b] > 2 THEN BEGIN SELECT b.pup.pupWords[1] FROM > bestSoFar => BEGIN bestSoFar ← b.pup.pupWords[0]; where ← b.pup.source; END; < currentVersion => sawOldVersion ← TRUE; ENDCASE => NULL; END; END; Buffer.ReturnBuffer[b]; END; ENDLOOP; ENDLOOP; PupSocketDestroy[soc]; Buffer.DestroyPool[pool]; IF bestSoFar > currentVersion THEN BEGIN IF verbose THEN BEGIN OPEN String; text: STRING = [100]; Time.AppendCurrent[text]; AppendString[text, " Saw "L]; AppendString[text, fileName]; AppendString[text, "!"L]; AppendDecimal[text, bestSoFar]; AppendString[text, " on "L]; AppendHostName[text, where]; LogString[text]; END; FlushWholeCache[]; currentVersion ← bestSoFar; probing ← FALSE; RETURN; END; IF sawOldVersion OR oldVersionAround THEN BEGIN oldVersionAround ← sawOldVersion; FlushWholeCache[]; END; probing ← FALSE; END; PupDirServer: PUBLIC PROCEDURE [b: PupBuffer] = BEGIN IF ~(lock OR pleaseStop) OR b.pup.pupType = unlockDirRequest THEN SELECT b.pup.pupType FROM netDirVersion => BEGIN StatIncr[statVers]; SELECT b.pup.pupWords[0] FROM = currentVersion => NULL; -- we have the same ones > currentVersion => KickProber[]; -- he has a newer one < currentVersion => NULL; -- Don't respond since we can't send it ENDCASE => ERROR; END; sendNetDir => NULL; lockDirRequest => BEGIN lock ← TRUE; ReturnPup[b, lockDirReply, 0]; FlushWholeCache[]; RETURN; END; unlockDirRequest => BEGIN wasLocked: BOOLEAN ← lock; lock ← FALSE; ReturnPup[b, unlockDirReply, 0]; tries ← 0; KickProber[]; RETURN; END; ENDCASE; Buffer.ReturnBuffer[b]; END; LogString: PROCEDURE [text: LONG STRING] = BEGIN String.AppendChar[text, '.]; String.AppendChar[text, Ascii.CR]; Put.Text[NIL, text]; END; -- initialization PupDirServerOn[]; NameServerDefs.PupNameServerOn[]; NameServerDefs.BumpCacheSize[2000]; END.