-- 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]}; }.