KeyNotePseudoServerImpl:
CEDAR
PROGRAM
IMPORTS Basics, FSPseudoServers, List, Rope
EXPORTS KeyNotePseudoServer = {
ROPE: TYPE = Rope.ROPE;
ServerNameReadServerList: TYPE = LIST OF ServerNameReadServerHandle;
ServerNameReadServerHandle: TYPE = REF ANY;
ServerNameReadServerHandle: TYPE = REF ServerNameReadServerObject
ServerNameReadServerObject:
TYPE =
RECORD [
name: ROPE,
readServer: ROPE
];
side effect is to update pseudo-server read list
RecomputeReadServerList:
PUBLIC
PROC [] = {
readList: ServerNameReadServerList;
LongestNamesFirst: List.CompareProc= {
RETURN[Basics.CompareInt[Rope.InlineSize[NARROW[ref2, REF ServerNameReadServerObject].readServer], Rope.InlineSize[NARROW[ref1, REF ServerNameReadServerObject].readServer]]];
};
FOR psl: FSPseudoServers.PseudoServerList ← FSPseudoServers.GetPseudoServers[], psl.rest
WHILE psl #
NIL
DO
FOR readers:
LIST
OF
ROPE ← psl.first.read, readers.rest
WHILE readers#
NIL
DO
item: REF ServerNameReadServerObject ← NEW [ ServerNameReadServerObject ← [name: psl.first.server, readServer: readers.first]];
TRUSTED {readList ← List.Nconc1[readList, LOOPHOLE[item]]; };
ENDLOOP;
ENDLOOP;
now sort List so longest items are at top
pseudoServerReadList ← List.Sort[list: readList, compareProc: LongestNamesFirst];
SubstituteLongestPrefixWithPseudoServer:
PUBLIC
PROC [fileName:
ROPE]
RETURNS [fileNameAfterShortening:
ROPE] = {
FOR psrl: ServerNameReadServerList ← pseudoServerReadList, psrl.rest
WHILE psrl #
NIL
DO
readServerPath: REF ServerNameReadServerObject ← NARROW[psrl.first];
shortened: BOOLEAN;
shortenedName: ROPE;
[shortened: shortened, shortenedName: shortenedName] ← TryToPseudoServerShortenFileName[readServerName: readServerPath.readServer, pseudoServerName: readServerPath.name, fileName: fileName];
IF shortened THEN RETURN[shortenedName];
ENDLOOP;
RETURN[fileName];
};
TryToPseudoServerShortenFileName:
PROC [readServerName:
ROPE, pseudoServerName:
ROPE, fileName:
ROPE]
RETURNS [shortened:
BOOLEAN, shortenedName:
ROPE] = {
fileName is something like '[Cedar]<CedarChest7.0>Documentation>Mumble.tioga'
readServerName is something like
'[Cyan]<CedarChest7.0>Documentation>'
pseudoServerName is something like '[Doc]'
fileNameHead: ROPE;
fileNameBody: ROPE;
readServerNameHead: ROPE;
readServerNameBody: ROPE;
[head: fileNameHead, body: fileNameBody] ← GetHeadAndBody[fileName];
[head: readServerNameHead, body: readServerNameBody] ← GetHeadAndBody[readServerName];
first check to see if the readServerNameBody is a prefix of the fileNameBody
IF Rope.IsPrefix[readServerNameBody, fileNameBody,
FALSE]
THEN {
equivalentHeads: LIST OF ROPE ← GetPseudoServers[fileNameHead];
now check to see if the readServerNameHead is the same as at least one of the equivalentHeads
FOR heads:
LIST
OF
ROPE ← equivalentHeads, heads.rest
WHILE heads#
NIL
DO
IF Rope.Equal[heads.first,BracketServerName[readServerNameHead]]
THEN
RETURN[shortened: TRUE, shortenedName: Rope.Concat[BracketServerName[pseudoServerName],
Rope.Substr[base: fileNameBody, start: Rope.Length[readServerNameBody]]
] ];
ENDLOOP;
};
RETURN[shortened: FALSE, shortenedName: NIL];
};
GetHeadAndBody:
PROC [name:
ROPE]
RETURNS [head:
ROPE, body:
ROPE] = {
endOfHead: INT ← Rope.Find[s1: name, s2: "]", pos1: 0, case: FALSE];
head ← Rope.Substr[name, 1, endOfHead-1];
body ← Rope.Substr[name, endOfHead+1];
};
BracketServerName:
PROC [name:
ROPE]
RETURNS [bracketedName:
ROPE] = {
bracketedName ← Rope.Cat[ "[", name, "]"];
};
GetPseudoServers:
PROC [name:
ROPE]
RETURNS [servers:
LIST
OF
ROPE] = {
servers ← FSPseudoServers.TranslateForRead[name];
IF Rope.Equal[servers.first, name] THEN RETURN[LIST[BracketServerName[name]]]
};
inititialize
pseudoServerReadList: ServerNameReadServerList;
RecomputeReadServerList[];