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