-- File: NetDirFileNoDisk.mesa - last edit: -- AOF 3-Feb-88 14:47:31 -- HGM 7-Dec-85 18:49:18 -- Copyright (C) 1984, 1985, 1988 by Xerox Corporation. All rights reserved. DIRECTORY Ascii USING [CR], CmFile USING [Handle, TableError], Heap USING [systemZone], Inline USING [LowHalf], Put USING [Text], String USING [AppendChar, AppendString, WordsForString], System USING [Pulses, GetClockPulses, PulsesToMicroseconds], StringLookUp USING [noMatch], Token USING [FreeTokenString, Item], Indirect USING [Close, NextValue, OpenSection], NameServerDefs USING [ CacheEntry, nameToCacheRequest, addressToCacheRequest, hereIsCacheEntry], NetDirDefs, PupDefs USING [ AppendPupAddress, GetPupAddress, PupNameTrouble, PupRouterBroadcastThis, PupRouterSendThis, Body, PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, SecondsToTocks, SetPupContentsWords, MoveStringBodyToPupBuffer, AccessHandle, DestroyPool, GetBuffer, MakePool, ReturnBuffer], PupTypes USING [fillInPupAddress, fillInSocketID, miscSrvSoc, PupAddress], ServerHeap USING [CopyString, Node], Stats USING [StatCounterIndex, StatBump]; NetDirFileNoDisk: PROGRAM IMPORTS CmFile, Heap, Inline, Put, String, System, Token, Indirect, PupDefs, Stats, ServerHeap EXPORTS NameServerDefs = BEGIN OPEN NetDirDefs; PupAddress: TYPE = PupTypes.PupAddress; CacheEntry: TYPE = NameServerDefs.CacheEntry; verbose: BOOLEAN = TRUE; useCount: CARDINAL ¬ 0; statMsScanningFile: PUBLIC Stats.StatCounterIndex; z: UNCOUNTED ZONE = Heap.systemZone; Chain: TYPE = LONG POINTER TO ChainSlot; ChainSlot: TYPE = RECORD [ next: Chain, dest: PupTypes.PupAddress, target: LONG STRING]; helpers: Chain ¬ NIL; -- NameLookup normally times out in 20 seconds. We should try the secondary server sooner. SearchNetDirForName: PUBLIC PROCEDURE [key: LONG STRING, ce: CacheEntry] RETURNS [hit: BOOLEAN ¬ FALSE] = BEGIN OPEN PupDefs; pulses: System.Pulses ¬ System.GetClockPulses[]; pool: PupDefs.AccessHandle ¬ PupDefs.MakePool[send: 1, receive: 2]; who: PupTypes.PupAddress ¬ PupTypes.fillInPupAddress; soc: PupSocket; b: PupBuffer; body: PupDefs.Body; helper: Chain ¬ helpers; try: CARDINAL ¬ 6; IF helper # NIL THEN BEGIN who ¬ helper.dest; try ¬ 2; END; soc ¬ PupSocketMake[PupTypes.fillInSocketID, who, SecondsToTocks[5]]; UNTIL hit DO IF try = 0 THEN BEGIN IF helper = NIL THEN EXIT; helper ¬ helper.next; try ¬ 6; IF helper # NIL THEN who ¬ helper.dest; -- NIL => Broadcast END; try ¬ try - 1; b ¬ PupDefs.GetBuffer[pool, send]; body ¬ b.pup; body.pupType ¬ NameServerDefs.nameToCacheRequest; body.pupID ¬ [try, try]; MoveStringBodyToPupBuffer[b, key]; body.dest ¬ who; body.dest.socket ¬ PupTypes.miscSrvSoc; body.source ¬ soc.getLocalAddress[]; IF helper = NIL THEN PupRouterBroadcastThis[b] ELSE PupRouterSendThis[b]; UNTIL hit DO b ¬ soc.get[]; IF b = NIL THEN EXIT; body ¬ b.pup; SELECT body.pupType FROM NameServerDefs.hereIsCacheEntry => BEGIN hit ¬ TRUE; CopyCacheEntryFromPacket[ce, b]; END; nameError => BEGIN hit ¬ TRUE; CopyName[ce, key]; END; ENDCASE => NULL; PupDefs.ReturnBuffer[b]; ENDLOOP; ENDLOOP; PupSocketDestroy[soc]; PupDefs.DestroyPool[pool]; pulses ¬ System.Pulses[System.GetClockPulses[] - pulses]; Stats.StatBump[ -- This might overflow 60 serconds statMsScanningFile, Inline.LowHalf[ System.PulsesToMicroseconds[pulses]/1000]]; END; SearchNetDirForAddress: PUBLIC PROCEDURE [key: PupAddress, ce: CacheEntry] RETURNS [hit: BOOLEAN ¬ FALSE] = BEGIN OPEN PupDefs; pulses: System.Pulses ¬ System.GetClockPulses[]; pool: PupDefs.AccessHandle ¬ PupDefs.MakePool[send: 1, receive: 10]; who: PupTypes.PupAddress ¬ PupTypes.fillInPupAddress; soc: PupSocket; b: PupBuffer; body: PupDefs.Body; helper: Chain ¬ helpers; try: CARDINAL ¬ 6; temp: STRING = [100]; IF helper # NIL THEN BEGIN who ¬ helper.dest; try ¬ 2; END; soc ¬ PupSocketMake[PupTypes.fillInSocketID, who, SecondsToTocks[5]]; UNTIL hit DO IF try = 0 THEN BEGIN IF helper = NIL THEN EXIT; helper ¬ helper.next; try ¬ 6; IF helper # NIL THEN who ¬ helper.dest; -- NIL => Broadcast END; try ¬ try - 1; b ¬ PupDefs.GetBuffer[pool, send]; body ¬ b.pup; body.pupType ¬ NameServerDefs.addressToCacheRequest; body.pupID ¬ [try, try]; body.address ¬ key; SetPupContentsWords[b, SIZE[PupAddress]]; body.dest ¬ who; body.dest.socket ¬ PupTypes.miscSrvSoc; body.source ¬ soc.getLocalAddress[]; IF helper = NIL THEN PupRouterBroadcastThis[b] ELSE PupRouterSendThis[b]; UNTIL hit DO b ¬ soc.get[]; IF b = NIL THEN EXIT; body ¬ b.pup; SELECT body.pupType FROM NameServerDefs.hereIsCacheEntry => BEGIN hit ¬ TRUE; CopyCacheEntryFromPacket[ce, b]; END; nameError => BEGIN hit ¬ TRUE; CopyAddress[ce, key]; END; ENDCASE => NULL; PupDefs.ReturnBuffer[b]; ENDLOOP; ENDLOOP; PupSocketDestroy[soc]; PupDefs.DestroyPool[pool]; pulses ¬ System.Pulses[System.GetClockPulses[] - pulses]; Stats.StatBump[ -- This might overflow 60 serconds statMsScanningFile, Inline.LowHalf[ System.PulsesToMicroseconds[pulses]/1000]]; END; CopyCacheEntryFromPacket: PROCEDURE [ce: CacheEntry, b: PupDefs.PupBuffer] = BEGIN p: LONG POINTER ¬ @b.pup.pupWords; n: CARDINAL ¬ 0; version: CARDINAL; names: CARDINAL; addrs: CARDINAL; words: CARDINAL; version ¬ (p+n)­; -- File version number n ¬ n + SIZE[CARDINAL]; names ¬ (p+n)­; n ¬ n + SIZE[CARDINAL]; IF names # 0 THEN BEGIN words ¬ SIZE[LONG STRING, names]; ce.size ¬ ce.size + words; ce.names ¬ DESCRIPTOR[ServerHeap.Node[words], names]; END; FOR i: CARDINAL IN [0..names) DO s: LONG STRING = LOOPHOLE[p+n]; words: CARDINAL ¬ String.WordsForString[s.length]; ce.names[i] ¬ ServerHeap.CopyString[s]; ce.size ¬ ce.size + words; n ¬ n + words; ENDLOOP; addrs ¬ (p+n)­; n ¬ n + SIZE[CARDINAL]; IF addrs # 0 THEN BEGIN words ¬ SIZE[PupAddress, addrs]; ce.size ¬ ce.size + words; ce.addrs ¬ DESCRIPTOR[ServerHeap.Node[words], addrs]; END; FOR i: CARDINAL IN [0..addrs) DO a: LONG POINTER TO PupAddress ¬ LOOPHOLE[(p+n)]; ce.addrs[i] ¬ a­; n ¬ n + SIZE[PupAddress]; ENDLOOP; END; CopyName: PROCEDURE [ce: CacheEntry, key: LONG STRING] = BEGIN words: CARDINAL = SIZE[LONG STRING]; ce.names ¬ DESCRIPTOR[ServerHeap.Node[words], 1]; ce.names[0] ¬ ServerHeap.CopyString[key]; ce.size ¬ ce.size + words + String.WordsForString[key.length]; END; CopyAddress: PROCEDURE [ce: CacheEntry, key: PupAddress] = BEGIN words: CARDINAL = SIZE[PupAddress]; ce.addrs ¬ DESCRIPTOR[ServerHeap.Node[words], 1]; ce.addrs[0] ¬ key; ce.size ¬ ce.size + words; END; AppendPseudoString: PROCEDURE [ e: LONG STRING, p: LONG DESCRIPTOR FOR PACKED ARRAY OF CHARACTER] = BEGIN FOR i: CARDINAL IN [0..MIN[e.maxlength - e.length, LENGTH[p]]) DO String.AppendChar[e, p[i]]; ENDLOOP; END; OpenDirectoryFiles, CloseDirectoryFiles: PUBLIC PROCEDURE = BEGIN END; UpdatePicture: PUBLIC PROCEDURE = BEGIN END; ScanParameterFile: PROCEDURE = BEGIN cmFile: CmFile.Handle; Option: TYPE = {helper}; 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 ¬ [helper: "Helper"L]; cmFile ¬ Indirect.OpenSection["NameServer"L]; IF cmFile = NIL THEN RETURN; DO option: Option; option ¬ NextValue[ cmFile, DESCRIPTOR[optionTable] ! CmFile.TableError => BEGIN IF name[0] # '; THEN Message["Unrecognized parameter: ", name]; RETRY; END]; SELECT option FROM LOOPHOLE[StringLookUp.noMatch] => EXIT; helper => BEGIN text: STRING = [20]; temp: LONG STRING ¬ Token.Item[cmFile, FALSE]; new: Chain ¬ z.NEW[ChainSlot]; new­ ¬ [NIL, PupTypes.fillInPupAddress, z.NEW[StringBody[temp.length]]]; String.AppendString[new.target, temp]; [] ¬ Token.FreeTokenString[temp]; PupDefs.GetPupAddress[@new.dest, new.target ! PupDefs.PupNameTrouble => CONTINUE]; IF helpers = NIL THEN helpers ¬ new ELSE BEGIN FOR finger: Chain ¬ helpers, finger.next DO IF finger.next = NIL THEN BEGIN finger.next ¬ new; EXIT; END; ENDLOOP; END; String.AppendString[text, " ("L]; PupDefs.AppendPupAddress[text, new.dest]; String.AppendString[text, ")"L]; Message["Helper for NetDir requests is "L, new.target, text]; END; ENDCASE => ERROR; ENDLOOP; Indirect.Close[cmFile]; END; Message: PROCEDURE [one, two, three, four: LONG STRING ¬ NIL] = BEGIN text: STRING = [200]; String.AppendString[text, one]; IF two # NIL THEN String.AppendString[text, two]; IF three # NIL THEN String.AppendString[text, three]; IF four # NIL THEN String.AppendString[text, four]; LogString[text]; END; LogString: PROCEDURE [text: LONG STRING] = BEGIN String.AppendChar[text, '.]; String.AppendChar[text, Ascii.CR]; Put.Text[NIL, text]; END; ScanParameterFile[]; END.