-- File: AddressCacheImpl.mesa - last edit:
-- AOF 31-Aug-86 18:11:17
-- BGY 21-Aug-84 20:15:57
-- Copyright (C) 1984, 1986 by Xerox Corporation. All rights reserved.
DIRECTORY
AddressCache,
Heap,
NSName,
NSString,
String,
System;
AddressCacheImpl: MONITOR
IMPORTS Heap, NSName, NSString, String
EXPORTS AddressCache = {
Handle: TYPE = LONG POINTER TO Object;
Object: TYPE = RECORD[
name: LONG STRING ← NIL,
addr: System.NetworkAddress ← System.nullNetworkAddress,
next: Handle ← NIL];
root, free: Handle ← NIL;
cacheSize, inCache: CARDINAL ← 0;
avail, hits, accesses: CARDINAL ← 0;
zone: UNCOUNTED ZONE ← Heap.Create[
initial: 5, increment: 5, largeNodeThreshold: 256];
GetSize: PUBLIC ENTRY PROC RETURNS[size: CARDINAL] = {size ← cacheSize};
SetSize: PUBLIC ENTRY PROC[size: CARDINAL] = {
Remove: PROC[this: Handle] RETURNS [Handle]= {
IF this.next # NIL THEN this.next ← Remove[this.next];
IF size = cacheSize THEN RETURN[this];
zone.FREE[@this.name];
zone.FREE[@this];
inCache ← inCache - 1;
cacheSize ← cacheSize - 1;
RETURN[this];
};
IF size = cacheSize THEN RETURN
ELSE IF size < cacheSize THEN {
-- remove from free list, then cache
IF free # NIL THEN free ← Remove[free];
IF size < cacheSize THEN root ← Remove[root]}
ELSE { -- add to free list
delta: CARDINAL ← size - cacheSize;
THROUGH [0..delta) DO free ← zone.NEW[Object ← [next: free]] ENDLOOP;
cacheSize ← size;
};
};
Flush: PUBLIC ENTRY PROC = {
-- remove from cache to free list
this: Handle ← NIL;
FOR this ← root, root UNTIL this = NIL DO
root ← this.next;
zone.FREE[@this.name];
this↑ ← [
name: NIL,
addr: System.nullNetworkAddress,
next: free];
free ← this;
ENDLOOP;
inCache ← 0;
};
AddNSName: PUBLIC PROC[name: NSName.Name, addr: System.NetworkAddress] = {
qualified: LONG STRING ← [NSName.maxFullNameLength];
string: NSString.String ← NSString.StringFromMesaString[qualified];
string ← NSName.AppendNameToString[string, name, TRUE];
qualified.length ← string.length;
AddEntry[qualified, addr];
};
AddEntry: PUBLIC ENTRY PROC[name: LONG STRING, addr: System.NetworkAddress] = {
IF cacheSize = 0 THEN RETURN;
IF free # NIL THEN { -- take from free list to cache
new: Handle ← free;
free ← new.next;
new↑ ← [
name: String.CopyToNewString[name, zone],
addr: addr, next: root];
root ← new;
inCache ← inCache + 1;
}
ELSE { -- have to remove least recently used entry
last: Handle ← root;
lru: Handle ← root;
IF root = NIL THEN RETURN;
FOR i: Handle ← root, i.next UNTIL i = NIL DO
IF i.next # NIL THEN last ← i ELSE lru ← i;
ENDLOOP;
last.next ← NIL;
zone.FREE[@lru.name];
lru↑ ← [
name: String.CopyToNewString[name, zone],
addr: addr, next: root];
root ← lru;
};
};
Enumerate: PUBLIC ENTRY PROC[
proc: PROC[name: LONG STRING, addr: System.NetworkAddress]] = {
FOR i: Handle ← root, i.next UNTIL i = NIL DO
proc[i.name, i.addr];
ENDLOOP;
};
LookupNSName: PUBLIC PROC[name: NSName.Name]
RETURNS [addr: System.NetworkAddress, hit: BOOLEAN] = {
qualified: LONG STRING ← [NSName.maxFullNameLength];
string: NSString.String ← NSString.StringFromMesaString[qualified];
string ← NSName.AppendNameToString[string, name, TRUE];
qualified.length ← string.length;
[addr, hit] ← Lookup[qualified];
};
Lookup: PUBLIC ENTRY PROC[name: LONG STRING]
RETURNS [addr: System.NetworkAddress, hit: BOOLEAN] = {
accesses ← accesses + 1;
hit ← FALSE; addr ← System.nullNetworkAddress;
IF cacheSize = 0 THEN RETURN;
FOR i: Handle ← root, i.next UNTIL i = NIL DO
IF (String.Compare[name, i.name, TRUE] = 0) THEN {
hits ← hits + 1; RETURN[i.addr, TRUE]};
ENDLOOP;
};
GetStatistics: PUBLIC PROC RETURNS[CARDINAL, CARDINAL, CARDINAL] = {
RETURN[inCache, hits, accesses]};
}.