IPNameCacheImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Hal Murray June 29, 1985 3:46:01 pm PDT
John Larson, July 10, 1987 2:54:54 pm PDT
DIRECTORY
BasicTime USING [GMT, Now, Period, Update],
Rope USING [Cat, Equal, Length, Match, ROPE],
IPDefs USING [Address],
IPNameCache,
IPNameSupport USING [MakeAddressInList, MakeRopeInList];
Name to Address cache
names: LIST OF NameEntry ← NIL;
GetNames:
PUBLIC
ENTRY
PROC
RETURNS [
LIST
OF NameEntry] = {
RETURN[names]; };
NameLookup: PUBLIC ENTRY PROC [name: ROPE] RETURNS [entry: NameEntry] = {RETURN[NameLookupInternal[name]]};
NameLookupInternal:
PROC [name:
ROPE]
RETURNS [entry: NameEntry] = {
FOR list:
LIST
OF NameEntry ← names, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Equal[entry.name, name,
FALSE]
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateName:
PUBLIC
ENTRY
PROC [
name: ROPE, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: NameEntry] = {
entry ← NameLookupInternal[name];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
entry.addresses ← NIL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
RETURN[entry]; };
entry ← MakeNameEntry[source, ttl, authoritative];
entry.name ← name;
RETURN[entry]; };
MakeNameEntry:
PROC [
source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: NameEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[NameRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative ];
names ← CONS[entry, names]; };
AddAddressToName:
PUBLIC
ENTRY
PROC [entry: NameEntry, address: IPDefs.Address] = {
entry.addresses ← IPNameSupport.MakeAddressInList[entry.addresses, address]; };
Alias to Name cache
aliases: LIST OF AliasEntry ← NIL;
GetAliases:
PUBLIC
ENTRY
PROC
RETURNS [
LIST
OF AliasEntry] = {
RETURN[aliases]; };
AliasLookup: PUBLIC ENTRY PROC [alias: ROPE] RETURNS [entry: AliasEntry] = {RETURN[AliasLookupInternal[alias]]};
AliasLookupInternal:
PROC [alias:
ROPE]
RETURNS [entry: AliasEntry] = {
FOR list:
LIST
OF AliasEntry ← aliases, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Equal[entry.alias, alias,
FALSE]
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateAlias:
PUBLIC
ENTRY
PROC [
alias: ROPE, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: AliasEntry] = {
entry ← AliasLookupInternal[alias];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
entry.name ← NIL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
RETURN[entry]; };
entry ← MakeAliasEntry[source, ttl, authoritative];
entry.alias ← alias;
RETURN[entry]; };
MakeAliasEntry:
PROC [
source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: AliasEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[AliasRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative ];
aliases ← CONS[entry, aliases]; };
AddNameToAlias:
PUBLIC
ENTRY
PROC [entry: AliasEntry, name:
ROPE] = {
entry.name ← name; };
MX cache
mxList: LIST OF MXEntry ← NIL;
GetMXList:
PUBLIC
ENTRY
PROC
RETURNS [
LIST
OF MXEntry] = {
RETURN[mxList]; };
MXLookup: PUBLIC ENTRY PROC [name: ROPE] RETURNS [entry: MXEntry] = {RETURN[MXLookupInternal[name]]};
MXLookupInternal:
PROC [name:
ROPE]
RETURNS [entry: MXEntry] = {
FOR list:
LIST
OF MXEntry ← mxList, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Equal[entry.name, name,
FALSE]
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateMX:
PUBLIC
ENTRY
PROC [
name: ROPE, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: MXEntry] = {
entry ← MXLookupInternal[name];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
entry.mxHosts ← NIL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
RETURN[entry]; };
entry ← MakeMXEntry[source, ttl, authoritative];
entry.name ← name;
RETURN[entry]; };
MakeMXEntry:
PROC [
source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: MXEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[MXRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative ];
mxList ← CONS[entry, mxList]; };
AddHostToMX:
PUBLIC
ENTRY
PROC [entry: MXEntry, hostInfo: MXHostInfo] = {
IF ~AlreadyInMXList[entry.mxHosts, hostInfo]
THEN
entry.mxHosts ← CONS[hostInfo, entry.mxHosts]; };
AlreadyInMXList:
PROC[mxHosts:
LIST
OF MXHostInfo, hostInfo: MXHostInfo]
RETURNS[BOOL] = {
FOR list:
LIST
OF MXHostInfo ← mxHosts, list.rest
UNTIL list =
NIL
DO
IF Rope.Equal[list.first.host, hostInfo.host, FALSE] AND list.first.preference = hostInfo.preference THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
Bogus Name cache
bogusNames: LIST OF BogusNameEntry ← NIL;
GetBogusNames:
PUBLIC
ENTRY
PROC
RETURNS [
LIST
OF BogusNameEntry] = {
RETURN[bogusNames]; };
BogusNameLookup: PUBLIC ENTRY PROC [bogus: ROPE] RETURNS [entry: BogusNameEntry] = {RETURN[BogusNameLookupInternal[bogus]]};
BogusNameLookupInternal:
PROC [bogus:
ROPE]
RETURNS [entry: BogusNameEntry] = {
FOR list:
LIST
OF BogusNameEntry ← bogusNames, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Equal[entry.bogus, bogus,
FALSE]
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateBogusName:
PUBLIC
ENTRY
PROC [
bogus: ROPE, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: BogusNameEntry] = {
entry ← BogusNameLookupInternal[bogus];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
NULL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
RETURN[entry]; };
entry ← MakeBogusName[source, ttl, authoritative];
entry.bogus ← bogus;
RETURN[entry]; };
MakeBogusName:
PROC [
source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: BogusNameEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[BogusNameRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative ];
bogusNames ← CONS[entry, bogusNames]; };
Down Name cache
downNames: LIST OF DownNameEntry ← NIL;
GetDownNames: PUBLIC ENTRY PROC RETURNS [LIST OF DownNameEntry] = {
DownNameLookup:
PUBLIC
ENTRY
PROC [name:
ROPE]
RETURNS [entry: DownNameEntry] = {
entry ← DownNameLookupInternal[name];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN RETURN[NIL];}; -- Don't show expired items
RETURN[entry]};
DownNameLookupInternal:
PROC [name:
ROPE]
RETURNS [entry: DownNameEntry] = {
FOR list:
LIST
OF DownNameEntry ← downNames, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Equal[entry.name, name,
FALSE]
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateDownName:
PUBLIC
ENTRY
PROC [
name: ROPE, ttl: INT]
RETURNS [entry: DownNameEntry] = {
entry ← DownNameLookupInternal[name];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl > -10 THEN RETURN[NIL];
-- Discard old info
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
RETURN[entry]; };
entry ← MakeDownName[ttl];
entry.name ← name;
RETURN[entry]; };
MakeDownName:
PROC [ttl:
INT]
RETURNS [entry: DownNameEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[DownNameRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl ];
downNames ← CONS[entry, downNames]; };
Address to Name cache
addresses: LIST OF AddressEntry ← NIL;
GetAddresses: PUBLIC ENTRY PROC RETURNS [LIST OF AddressEntry] = { RETURN[addresses]; };
AddressLookup: PUBLIC ENTRY PROC [address: IPDefs.Address] RETURNS [entry: AddressEntry] = {RETURN[AddressLookupInternal[address]]};
AddressLookupInternal:
PROC [address: IPDefs.Address]
RETURNS [entry: AddressEntry] = {
FOR list:
LIST
OF AddressEntry ← addresses, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF entry.address = address
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateAddress:
PUBLIC
ENTRY
PROC [
address: IPDefs.Address, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: AddressEntry] = {
entry ← AddressLookupInternal[address];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
entry.names ← NIL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
RETURN[entry]; };
entry ← MakeAddressEntry[source, ttl, authoritative];
entry.address ← address;
RETURN[entry]; };
MakeAddressEntry:
PROC [
source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: AddressEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[AddressRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative];
addresses ← CONS[entry, addresses]; };
AddNameToAddress:
PUBLIC
ENTRY
PROC [entry: AddressEntry, name:
ROPE] = {
entry.names ← IPNameSupport.MakeRopeInList[entry.names, name]; };
Bogus Address cache
bogusAddresses: LIST OF BogusAddressEntry ← NIL;
GetBogusAddresses:
PUBLIC
ENTRY
PROC
RETURNS [
LIST
OF BogusAddressEntry] = {
RETURN[bogusAddresses]; };
BogusAddressLookup: PUBLIC ENTRY PROC [bogus: IPDefs.Address] RETURNS [entry: BogusAddressEntry] = {RETURN[BogusAddressLookupInternal[bogus]]};
BogusAddressLookupInternal:
PROC [bogus: IPDefs.Address]
RETURNS [entry: BogusAddressEntry] = {
FOR list:
LIST
OF BogusAddressEntry ← bogusAddresses, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF entry.bogus = bogus
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateBogusAddress:
PUBLIC
ENTRY
PROC [
bogus: IPDefs.Address, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: BogusAddressEntry] = {
entry ← BogusAddressLookupInternal[bogus];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
NULL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
RETURN[entry]; };
entry ← MakeBogusAddress[source, ttl, authoritative];
entry.bogus ← bogus;
RETURN[entry]; };
MakeBogusAddress:
PROC [
source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: BogusAddressEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[BogusAddressRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative,
bogus: TRASH ];
bogusAddresses ← CONS[entry, bogusAddresses]; };
Down Address cache
downAddresses: LIST OF DownAddressEntry ← NIL;
GetDownAddresses:
PUBLIC
ENTRY
PROC
RETURNS [
LIST
OF DownAddressEntry] = {
RETURN[downAddresses]; };
DownAddressLookup:
PUBLIC
ENTRY
PROC [address: IPDefs.Address]
RETURNS [entry: DownAddressEntry] = {
entry ← DownAddressLookupInternal[address];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN RETURN[NIL];}; -- Don't show expired items
RETURN[entry]};
DownAddressLookupInternal:
PROC [address: IPDefs.Address]
RETURNS [entry: DownAddressEntry] = {
FOR list:
LIST
OF DownAddressEntry ← downAddresses, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF entry.address = address
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateDownAddress:
PUBLIC
ENTRY
PROC [address: IPDefs.Address, ttl:
INT]
RETURNS [entry: DownAddressEntry] = {
entry ← DownAddressLookupInternal[address];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl > -10 THEN RETURN[NIL];
-- Discard old info
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
RETURN[entry]; };
entry ← MakeDownAddress[ttl];
entry.address ← address;
RETURN[entry]; };
MakeDownAddress:
PROC [ttl:
INT]
RETURNS [entry: DownAddressEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[DownAddressRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
address: TRASH ];
downAddresses ← CONS[entry, downAddresses]; };
downServers: LIST OF DownServerEntry ← NIL;
GetDownServers: PUBLIC ENTRY PROC RETURNS [LIST OF DownServerEntry] = {
DownServerLookup:
PUBLIC
ENTRY
PROC [address: IPDefs.Address]
RETURNS [entry: DownServerEntry] = {
entry ← DownServerLookupInternal[address];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN RETURN[NIL];}; -- Don't show expired items
RETURN[entry]};
DownServerLookupInternal:
PROC [address: IPDefs.Address]
RETURNS [entry: DownServerEntry] = {
FOR list:
LIST
OF DownServerEntry ← downServers, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF entry.address = address
THEN {
entry.referenced ← BasicTime.Now[];
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateDownServer:
PUBLIC
ENTRY
PROC [
address: IPDefs.Address, ttl: INT]
RETURNS [entry: DownServerEntry] = {
entry ← DownServerLookupInternal[address];
IF entry #
NIL
THEN {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT = BasicTime.Period[from: now, to: entry.expires];
IF thisTtl > -10 THEN RETURN[NIL];
-- Discard old info
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
RETURN[entry]; };
entry ← MakeDownServer[ttl];
entry.address ← address;
RETURN[entry]; };
MakeDownServer:
PROC [ttl:
INT]
RETURNS [entry: DownServerEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[DownServerRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
address: TRASH ];
downServers ← CONS[entry, downServers]; };
Zone to Server cache
zones: LIST OF ZoneEntry ← NIL;
GetZones: PUBLIC ENTRY PROC RETURNS [LIST OF ZoneEntry] = { RETURN[zones]; };
GetZone:
PUBLIC
ENTRY
PROC [name:
ROPE]
RETURNS [entry: ZoneEntry] = {
bestEntry: ZoneEntry ← NIL;
FOR list:
LIST
OF ZoneEntry ← zones, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Match[Rope.Cat["*", entry.zone], name, FALSE] THEN {
IF bestEntry =
NIL
THEN bestEntry ← entry
ELSE
IF Rope.Length[bestEntry.zone] < Rope.Length[entry.zone] THEN bestEntry ← entry};
ENDLOOP;
IF bestEntry # NIL THEN bestEntry.zoneLookup ← bestEntry.zoneLookup + 1;
RETURN[bestEntry]; };
ZoneLookup:
PUBLIC
ENTRY
PROC [zone:
ROPE]
RETURNS [entry: ZoneEntry] = {
RETURN[ZoneLookupInternal[zone]]; };
ZoneLookupInternal:
PROC [zone:
ROPE]
RETURNS [entry: ZoneEntry] = {
FOR list:
LIST
OF ZoneEntry ← zones, list.rest
UNTIL list =
NIL
DO
entry ← list.first;
IF Rope.Equal[entry.zone, zone,
FALSE]
THEN {
entry.zoneLookup ← entry.zoneLookup + 1;
RETURN; };
ENDLOOP;
RETURN[NIL]; };
UpdateZone:
PUBLIC
ENTRY
PROC [
name: ROPE, source: IPDefs.Address, ttl: INT, authoritative: BOOL]
RETURNS [entry: ZoneEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
thisTtl: INT;
entry ← ZoneLookupInternal[name];
IF entry #
NIL
THEN {
thisTtl ← BasicTime.Period[from: now, to: entry.expires];
IF thisTtl < -10 THEN entry.authoritative ← FALSE;
IF entry.authoritative AND ~authoritative THEN RETURN[NIL];
IF ~entry.authoritative
AND authoritative
THEN {
Discard old info
entry.servers ← NIL; };
entry.source ← source;
entry.loaded ← now;
entry.referenced ← now;
entry.expires ← BasicTime.Update[now, ttl];
entry.ttl ← ttl;
entry.authoritative ← authoritative;
entry.zone ← name;
RETURN[entry]; };
entry ← MakeZoneEntry[source, ttl, authoritative];
entry.zone ← name;
RETURN[entry]; };
AddServer:
PUBLIC
ENTRY
PROC [entry: ZoneEntry, server:
ROPE] = {
entry.servers ← IPNameSupport.MakeRopeInList[entry.servers, server]; };
MakeZoneEntry:
PROC [source: IPDefs.Address, ttl:
INT, authoritative:
BOOL]
RETURNS [entry: ZoneEntry] = {
now: BasicTime.GMT ← BasicTime.Now[];
expires: INT ← ttl;
IF expires = 0 THEN expires ← ttlDefault;
entry ← NEW[ZoneRecord];
entry^ ← [
loaded: now,
referenced: now,
expires: BasicTime.Update[now, expires],
ttl: ttl,
source: source,
authoritative: authoritative ];
zones ← CONS[entry, zones]; };
histograms: LIST OF HistogramEntry ← NIL;
GetHistograms: PUBLIC ENTRY PROC RETURNS [LIST OF HistogramEntry] = { RETURN[histograms]; };
AddToCacheHits:
PUBLIC
ENTRY
PROC [server: IPDefs.Address, type: IPNameCache.CacheType] = {
histogram: HistogramEntry ← FindHistogram[server];
histogram.cacheHits[type] ← histogram.cacheHits[type].SUCC; };
AddToProbes:
PUBLIC
ENTRY
PROC [server: IPDefs.Address, type: IPNameCache.ProbeType] = {
histogram: HistogramEntry ← FindHistogram[server];
histogram.probes[type] ← histogram.probes[type].SUCC; };
AddToLost:
PUBLIC
ENTRY
PROC [server: IPDefs.Address] = {
histogram: HistogramEntry ← FindHistogram[server];
histogram.lost ← histogram.lost.SUCC; };
AddToCounter:
PUBLIC
ENTRY
PROC [server: IPDefs.Address, ms:
INT] = {
histogram: HistogramEntry ← FindHistogram[server];
index: INT;
ms ← ms + IPNameCache.histogramSlotSize - 1;
index ← ms/IPNameCache.histogramSlotSize;
IF index >= IPNameCache.histogramSlots THEN index ← IPNameCache.histogramSlots-1;
histogram.counters[index] ← histogram.counters[index].SUCC; };
FindHistogram:
PROC [server: IPDefs.Address]
RETURNS[ histogram: HistogramEntry] = {
FOR list:
LIST
OF HistogramEntry ← histograms, list.rest
UNTIL list =
NIL
DO
histogram ← list.first;
IF histogram.server = server THEN EXIT;
REPEAT
FINISHED => {
histogram ← NEW[HistogramRecord];
histogram^ ← [
server: server,
counters: ALL[0] ];
histograms ← CONS[histogram, histograms]; };
ENDLOOP; };
END.