-- 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.