-- Transport Mechanism Registration Server: cache for name lookup -- [Juniper]MS>RegCache.mesa -- Randy Gobbel 19-May-81 12:18:12 -- Andrew Birrell 25-Jun-81 16:06:05 DIRECTORY BodyDefs USING [Connect, RName, Timestamp], ObjectDirDefs USING [ObjectNumber], ProtocolDefs USING [RNameType], RegBTreeDefs USING [RegState], RegCacheDefs USING [], Storage USING [FreeString, String], String USING [ AppendString, EquivalentStrings, EquivalentSubStrings, SubStringDescriptor]; RegCache: MONITOR IMPORTS Storage, 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: STRING, b: 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: STRING, b: 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: STRING, value: NameVal, connect: BodyDefs.Connect]; NameVal: TYPE = RECORD [ knownReg: BOOLEAN, type: ProtocolDefs.RNameType, stamp: BodyDefs.Timestamp, obj: ObjectDirDefs.ObjectNumber]; CacheIndex: TYPE = [0..25); cache: ARRAY CacheIndex OF NameRec ¬ ALL[[name: NIL, value:, connect: NIL]]; 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] ¬ [ Storage.String[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 { Storage.FreeString[cache[index].name]; cache[index].name ¬ NIL}; IF cache[index].connect # NIL THEN { Storage.FreeString[cache[index].connect]; cache[index].connect ¬ NIL}; 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].connect # NIL THEN Storage.FreeString[cache[index].connect]; IF stamp = cache[index].value.stamp THEN BEGIN cache[index].connect ¬ Storage.String[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.