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