-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- RegCache.mesa: cache for name lookup -- HGM, 15-Sep-85 5:14:27 -- Randy Gobbel 19-May-81 12:18:12 -- Andrew Birrell 25-Jun-81 16:06:05 DIRECTORY BodyDefs USING [Connect, RName, Timestamp], Heap USING [systemZone], ObjectDirDefs USING [ObjectNumber], ProtocolDefs USING [RNameType], RegBTreeDefs USING [RegState], RegCacheDefs USING [], String USING [ AppendString, EquivalentStrings, EquivalentSubStrings, SubStringDescriptor]; RegCache: MONITOR IMPORTS Heap, String EXPORTS RegCacheDefs = BEGIN -- cache is extremely simple: -- Linear search for look-up, -- Round-robin replacement algorithm, -- Only keeps names in "GV" and "MS" registries. -- Doesn't keep Log-* nor Archive-* BeginsWith: PROC [s: LONG STRING, b: LONG STRING] RETURNS [BOOLEAN] = BEGIN pattern: String.SubStringDescriptor ← [b, 0, b.length]; target: String.SubStringDescriptor ← [s, 0, b.length]; RETURN[ s.length >= b.length AND String.EquivalentSubStrings[@pattern, @target]] END; EndsWith: PROC [s: LONG STRING, b: LONG STRING] RETURNS [BOOLEAN] = INLINE BEGIN pattern: String.SubStringDescriptor ← [b, 0, b.length]; target: String.SubStringDescriptor ← [s, s.length - b.length, b.length]; RETURN[ s.length >= b.length AND String.EquivalentSubStrings[@pattern, @target]] END; Interesting: PROC [name: BodyDefs.RName] RETURNS [BOOLEAN] = INLINE { RETURN[EndsWith[name, ".ms"L] OR EndsWith[name, ".GV"L]]}; NameRec: TYPE = RECORD [ name: LONG STRING ← NIL, value: NameVal, connect: LONG STRING ← NIL]; NameVal: TYPE = RECORD [ knownReg: BOOLEAN, type: ProtocolDefs.RNameType, stamp: BodyDefs.Timestamp, obj: ObjectDirDefs.ObjectNumber]; CacheIndex: TYPE = [0..25); Cache: TYPE = ARRAY CacheIndex OF NameRec; cache: LONG POINTER TO Cache ← Heap.systemZone.NEW[Cache]; rover: CARDINAL ← FIRST[CacheIndex]; AddName: PUBLIC ENTRY PROC [ name: BodyDefs.RName, knownReg: BOOLEAN, type: ProtocolDefs.RNameType, stamp: BodyDefs.Timestamp, obj: ObjectDirDefs.ObjectNumber] = BEGIN IF Interesting[name] AND NOT BeginsWith[name, "Archive-"L] AND NOT BeginsWith[name, "Log-"L] THEN BEGIN InnerFlush[name]; RemoveEntry[rover]; cache[rover] ← [ Heap.systemZone.NEW[StringBody[name.length]], [knownReg, type, stamp, obj], NIL]; String.AppendString[cache[rover].name, name]; rover ← IF rover = LAST[CacheIndex] THEN FIRST[CacheIndex] ELSE SUCC[rover]; END; END; ReadName: PUBLIC ENTRY PROC [name: BodyDefs.RName] RETURNS [ type: ProtocolDefs.RNameType, stamp: BodyDefs.Timestamp, obj: ObjectDirDefs.ObjectNumber] = BEGIN type ← notFound; IF Interesting[name] THEN FOR index: CacheIndex IN CacheIndex DO IF String.EquivalentStrings[cache[index].name, name] THEN { [, type, stamp, obj] ← cache[index].value; EXIT}; ENDLOOP; END; FlushName: PUBLIC ENTRY PROC [name: BodyDefs.RName] = { IF Interesting[name] THEN InnerFlush[name]}; TestKnownReg: PUBLIC ENTRY PROC [name: BodyDefs.RName] RETURNS [state: RegBTreeDefs.RegState] = BEGIN state ← bad; IF Interesting[name] THEN FOR index: CacheIndex IN CacheIndex DO IF String.EquivalentStrings[cache[index].name, name] THEN { state ← IF cache[index].value.knownReg THEN yes ELSE no; EXIT}; ENDLOOP; END; InnerFlush: INTERNAL PROC [name: BodyDefs.RName] = BEGIN FOR index: CacheIndex IN CacheIndex DO IF String.EquivalentStrings[cache[index].name, name] THEN { RemoveEntry[index]; EXIT}; ENDLOOP; END; RemoveEntry: INTERNAL PROC [index: CacheIndex] = BEGIN IF cache[index].name # NIL THEN Heap.systemZone.FREE[@cache[index].name]; IF cache[index].connect # NIL THEN Heap.systemZone.FREE[@cache[index].connect]; END; AddConnect: PUBLIC ENTRY PROC [ name: BodyDefs.RName, stamp: BodyDefs.Timestamp, connect: BodyDefs.Connect] = BEGIN IF Interesting[name] THEN FOR index: CacheIndex IN CacheIndex DO IF String.EquivalentStrings[cache[index].name, name] THEN BEGIN IF cache[index].name # NIL THEN Heap.systemZone.FREE[@cache[index].name]; IF stamp = cache[index].value.stamp THEN BEGIN cache[index].connect ← Heap.systemZone.NEW[StringBody[connect.length]]; String.AppendString[cache[index].connect, connect]; END ELSE cache[index].connect ← NIL; EXIT END; ENDLOOP; END; ReadConnect: PUBLIC ENTRY PROC [name: BodyDefs.RName, connect: BodyDefs.Connect] RETURNS [found: BOOLEAN] = BEGIN found ← FALSE; IF Interesting[name] THEN FOR index: CacheIndex IN CacheIndex DO IF String.EquivalentStrings[cache[index].name, name] THEN BEGIN IF cache[index].connect # NIL THEN BEGIN connect.length ← 0; String.AppendString[connect, cache[index].connect]; found ← TRUE; END; EXIT END; ENDLOOP; END; END.