-- Transport Mechanism Registration Server: cache for name lookup -- [Juniper]<Grapevine>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.