STPServerAuxImpl.mesa
Copyright (C) 1984, 1985 Xerox Corporation. All rights reserved.
Michael Plass, December 30, 1985 3:02:24 pm PST
Jim Gasbarro, March 8, 1985 11:39:14 am PST
Russ Atkinson (RRA) June 21, 1985 1:05:20 pm PDT
Spreitzer, September 4, 1985 4:56:26 pm PDT
Hal Murray December 9, 1985 5:14:47 pm PST
DIRECTORY
Basics USING [bytesPerWord, LongNumber, SwapHalves],
BasicTime USING [GMT, nullGMT, ToPupTime, Update],
CedarProcess USING [Abort, CheckAbort, Fork, ForkableProc, Process],
FS USING [ComponentPositions, Error, ExpandName, FileInfo],
PupDefs USING [GetHopsToNetwork, GetPupContentsBytes, PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, ReturnPup, SendErrorPup, veryLongWait],
PupTypes USING [fillInPupAddress, Pair, PupAddress, PupSocketID, PupType],
Rope USING [Cat, Find, FromRefText, Index, Length, Replace, ROPE, Substr],
RuntimeError USING [UNCAUGHT],
STPServerFileTranslation USING [FindNamedTranslator, NamedTranslator],
STPServerPrivate USING [CurrentVersion, FileName, NameMapDirection, NameMapList],
UserProfile USING [CallWhenProfileChanges, ListOfTokens, ProfileChangeReason];
STPServerAuxImpl:
CEDAR
MONITOR
IMPORTS Basics, BasicTime, CedarProcess, FS, PupDefs, Rope, RuntimeError, STPServerPrivate, UserProfile, STPServerFileTranslation
EXPORTS STPServerPrivate
~
BEGIN
OPEN STPServerPrivate;
Name Mapping
nameMaps: NameMapList ← NIL;
GMT: TYPE ~ BasicTime.GMT;
LongNumber: TYPE ~ Basics.LongNumber;
ROPE: TYPE ~ Rope.ROPE;
LOR:
TYPE ~
LIST
OF
ROPE;
BothFromOne:
PUBLIC
PROC [oneName:
ROPE, direction: NameMapDirection]
RETURNS [both: FileName] ~ {
otherName: ROPE ← oneName;
otherLength: INT ← otherName.Length[];
FOR nms: NameMapList ← nameMaps, nms.rest
WHILE nms #
NIL
DO
find:
ROPE ~
SELECT direction
FROM
localToRemote => nms.first.local,
remoteToLocal => nms.first.remote,
ENDCASE => ERROR;
repl:
ROPE ~
SELECT direction
FROM
localToRemote => nms.first.remote,
remoteToLocal => nms.first.local,
ENDCASE => ERROR;
start: INT ~ otherName.Find[s2: find, case: FALSE];
cutLength: INT ~ find.Length[];
IF start >= 0
THEN {
otherName ← otherName.Replace[start: start, len: cutLength, with: repl];
EXIT;
};
ENDLOOP;
both ←
SELECT direction
FROM
localToRemote => [local: oneName, remote: otherName],
remoteToLocal => [local: otherName, remote: oneName],
ENDCASE => ERROR;
};
RealName:
PROC [remoteName:
ROPE]
RETURNS [realName:
ROPE ←
NIL, translated:
BOOL ←
FALSE] ~ {
fullFName: ROPE ← NIL;
cp: FS.ComponentPositions;
namedTranslator: STPServerFileTranslation.NamedTranslator ← NIL;
hostNameLength: INT ← 0;
[fullFName, cp] ← FS.ExpandName[remoteName];
namedTranslator ← STPServerFileTranslation.FindNamedTranslator[fullFName, cp.dir.start, cp.dir.length];
IF namedTranslator = NIL OR cp.subDirs.length = 0 THEN RETURN [realName: BothFromOne[remoteName, remoteToLocal].local, translated: FALSE];
hostNameLength ← Rope.Index[s1: fullFName, pos1: cp.subDirs.start, s2: ">"] - cp.subDirs.start;
realName ← Rope.Cat["[", Rope.Substr[fullFName, cp.subDirs.start, hostNameLength], "]<", Rope.Substr[fullFName, cp.subDirs.start+hostNameLength+1]];
translated ← TRUE;
};
NoteProfile:
PROC [reason: UserProfile.ProfileChangeReason]
--UserProfile.ChangeProc-- ~ {
maps: LOR ← UserProfile.ListOfTokens["STPServer.NameMappings", NIL];
newMaps: NameMapList ← NIL;
FOR maps ← maps, maps.rest.rest
WHILE maps #
NIL
AND maps.rest #
NIL
DO
remote: ROPE ~ maps.first;
local: ROPE ~ maps.rest.first;
newMaps ← CONS[[local: local, remote: remote], newMaps];
ENDLOOP;
IF maps # NIL THEN ERROR;
nameMaps ← newMaps;
};
Single Packet Protocol
LookupFileType: PupTypes.PupType = LOOPHOLE[200B];
LookupFileReplyType: PupTypes.PupType = LOOPHOLE[201B];
LookupFileErrorType: PupTypes.PupType = LOOPHOLE[202B];
LookupFileSocket: PupTypes.PupSocketID = [0, 61B];
singleSocket: PupDefs.PupSocket ← NIL;
singleProcess: CedarProcess.Process ← NIL;
StartSingle:
PUBLIC
ENTRY
PROC = {
ENABLE UNWIND => NULL;
IF singleProcess =
NIL
THEN {
singleSocket ← PupDefs.PupSocketMake [local: LookupFileSocket, remote: PupTypes.fillInPupAddress, ticks: PupDefs.veryLongWait ];
singleProcess ← CedarProcess.Fork[
SinglePacketListener, NIL, [priority: foreground, usePriority: TRUE]];
};
};
StopSingle:
PUBLIC
ENTRY
PROC = {
ENABLE UNWIND => NULL;
IF singleProcess #
NIL
THEN {
CedarProcess.Abort[singleProcess];
PupDefs.PupSocketDestroy[singleSocket
! RuntimeError.UNCAUGHT => CONTINUE];
singleSocket ← NIL;
};
};
ReplyRecord: TYPE = MACHINE DEPENDENT RECORD[v: CARDINAL, c, l: LongNumber];
ReplyRecordBytes: CARDINAL = SIZE[ReplyRecord]*Basics.bytesPerWord;
SinglePacketListener: CedarProcess.ForkableProc =
TRUSTED {
ENABLE UNWIND => singleProcess ← NIL;
text: REF TEXT ← NEW[TEXT[256]];
DO
receiver: PupDefs.PupBuffer = singleSocket.get[];
replyType: PupTypes.PupType ← error;
replyBytes: CARDINAL ← 0;
IF receiver #
NIL
THEN {
addr: PupTypes.PupAddress ← receiver.source;
msWait: CARDINAL = 2000+500*MIN[8, PupDefs.GetHopsToNetwork[addr.net]];
IF receiver.pupType = LookupFileType
THEN {
id: PupTypes.Pair ← receiver.pupID;
len: INT ← PupDefs.GetPupContentsBytes[receiver];
IF len
IN [1..256]
THEN {
ENABLE RuntimeError.UNCAUGHT => GO TO dropIt;
sLen: NAT ← len;
name: ROPE ← NIL;
fileLen: INT ← 0;
fileDate: GMT ← BasicTime.nullGMT;
rPtr: LONG POINTER TO ReplyRecord = LOOPHOLE[@receiver.pupBody];
translated: BOOL ← FALSE;
text[0] ← '[; text[1] ← '];
FOR i:
NAT
IN [0 .. sLen)
DO
text[i+2] ← receiver.pupChars[i];
ENDLOOP;
text.length ← sLen+2;
name ← Rope.FromRefText[text];
[name, translated] ← RealName[name];
[fullFName: name, created: fileDate, bytes: fileLen] ←
FS.FileInfo[name: name
!
FS.Error => {
SELECT error.code
FROM
$nonCedarVolume, $unknownVolume, $unknownFile, $unknownCreatedTime, $illegalName, $patternNotAllowed => replyType ← LookupFileErrorType;
ENDCASE => NULL;
CONTINUE
};
];
IF fileDate # BasicTime.nullGMT
AND fileLen >= 0
THEN {
IF translated
THEN {
fileLen ← (fileLen+999)/1000*1000;
fileDate ← BasicTime.Update[fileDate, 1];
};
rPtr.v ← CurrentVersion[name];
rPtr.c ← Basics.SwapHalves[[lc[BasicTime.ToPupTime[fileDate]]]];
rPtr.l ← Basics.SwapHalves[[li[fileLen]]];
replyType ← LookupFileReplyType;
replyBytes ← ReplyRecordBytes;
};
};
EXITS dropIt => {};
};
receiver.pupType ← replyType;
IF replyType = error
THEN
PupDefs.SendErrorPup[receiver, noProcessPupErrorCode, "Can't lookup file"]
ELSE PupDefs.ReturnPup[receiver, replyType, replyBytes];
};
CedarProcess.CheckAbort[singleProcess];
ENDLOOP;
};