-- Copyright (C) 1984 by Xerox Corporation. All rights reserved.
-- NetDirFileNoDisk.mesa, HGM, 15-Jul-84 0:40:56
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;
-- Don't try broadcasting if all helpers timeout or you might get an answer from a D0.
-- 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;
IF helper = NIL THEN EXIT;
who ← helper.dest;
try ← 6;
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]];
RETURN[LENGTH[ce.names] # 0];
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;
IF helper = NIL THEN EXIT;
who ← helper.dest;
try ← 6;
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]];
IF LENGTH[ce.addrs] # 0 THEN RETURN[TRUE];
[] ← SearchNetDirForName[temp, ce];
RETURN[LENGTH[ce.names] # 0];
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.