-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. -- NetDirFileNoDisk.mesa, HGM, 7-Dec-85 18:49:18 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], Buffer USING [AccessHandle, DestroyPool, GetBuffer, MakePool, ReturnBuffer], Indirect USING [Close, NextValue, OpenSection], NameServerDefs USING [ CacheEntry, nameToCacheRequest, addressToCacheRequest, hereIsCacheEntry], NetDirDefs, PupDefs USING [ AppendPupAddress, GetPupAddress, PupNameTrouble, PupRouterBroadcastThis, PupRouterSendThis, PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, SecondsToTocks, SetPupContentsWords, MoveStringBodyToPupBuffer], PupTypes USING [fillInPupAddress, fillInSocketID, miscSrvSoc, PupAddress], ServerHeap USING [CopyString, Node], Stats USING [StatCounterIndex, StatBump]; NetDirFileNoDisk: PROGRAM IMPORTS CmFile, Heap, Inline, Put, String, System, Token, Buffer, 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: Buffer.AccessHandle ← Buffer.MakePool[send: 1, receive: 2]; who: PupTypes.PupAddress ← PupTypes.fillInPupAddress; soc: PupSocket; b: PupBuffer; 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 ← Buffer.GetBuffer[pup, pool, send]; b.pup.pupType ← NameServerDefs.nameToCacheRequest; b.pup.pupID ← [try, try]; MoveStringBodyToPupBuffer[b, key]; b.pup.dest ← who; b.pup.dest.socket ← PupTypes.miscSrvSoc; b.pup.source ← soc.getLocalAddress[]; IF helper = NIL THEN PupRouterBroadcastThis[b] ELSE PupRouterSendThis[b]; UNTIL hit DO b ← soc.get[]; IF b = NIL THEN EXIT; SELECT b.pup.pupType FROM NameServerDefs.hereIsCacheEntry => BEGIN hit ← TRUE; CopyCacheEntryFromPacket[ce, b]; END; nameError => BEGIN hit ← TRUE; CopyName[ce, key]; END; ENDCASE => NULL; Buffer.ReturnBuffer[b]; ENDLOOP; ENDLOOP; PupSocketDestroy[soc]; Buffer.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: Buffer.AccessHandle ← Buffer.MakePool[send: 1, receive: 10]; who: PupTypes.PupAddress ← PupTypes.fillInPupAddress; soc: PupSocket; b: PupBuffer; 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 ← Buffer.GetBuffer[pup, pool, send]; b.pup.pupType ← NameServerDefs.addressToCacheRequest; b.pup.pupID ← [try, try]; b.pup.address ← key; SetPupContentsWords[b, SIZE[PupAddress]]; b.pup.dest ← who; b.pup.dest.socket ← PupTypes.miscSrvSoc; b.pup.source ← soc.getLocalAddress[]; IF helper = NIL THEN PupRouterBroadcastThis[b] ELSE PupRouterSendThis[b]; UNTIL hit DO b ← soc.get[]; IF b = NIL THEN EXIT; SELECT b.pup.pupType FROM NameServerDefs.hereIsCacheEntry => BEGIN hit ← TRUE; CopyCacheEntryFromPacket[ce, b]; END; nameError => BEGIN hit ← TRUE; CopyAddress[ce, key]; END; ENDCASE => NULL; Buffer.ReturnBuffer[b]; ENDLOOP; ENDLOOP; PupSocketDestroy[soc]; Buffer.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.