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
Hal Murray, June 18, 1986 7:08:45 pm PDT
DIRECTORY
BasicTime USING [GMT, nullGMT, ToPupTime, Update],
CedarProcess USING [Fork, ForkableProc, Process],
Endian USING [FFromCard],
FS USING [ComponentPositions, Error, ExpandName, FileInfo],
PupBuffer USING [Buffer, FileLookupReply],
PupSocket USING [CreateServer, Destroy, ExtractRope, FreeBuffer, Get, ReturnToSender, SetUserHWords, SetUserSize, Socket, waitForever],
PupType USING [fileLookup, fileLookupError, fileLookupReply],
PupWKS USING [fileLookup],
Rope USING [Cat, Find, Index, Length, Replace, ROPE, Substr],
STPServerFileTranslation USING [FindNamedTranslator, NamedTranslator],
STPServerPrivate USING [CurrentVersion, FileName, NameMapDirection, NameMapList],
UserProfile USING [CallWhenProfileChanges, ListOfTokens, ProfileChangeReason];
STPServerAuxImpl: CEDAR MONITOR
IMPORTS BasicTime, CedarProcess, Endian, FS, PupSocket, Rope, STPServerPrivate, UserProfile, STPServerFileTranslation
EXPORTS STPServerPrivate
~ BEGIN OPEN STPServerPrivate;
Name Mapping
nameMaps: NameMapList ← NIL;
GMT: TYPE ~ BasicTime.GMT;
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: ROPENIL, translated: BOOLFALSE] ~ {
fullFName: ROPENIL;
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
socket: PupSocket.Socket ← NIL;
singleProcess: CedarProcess.Process ← NIL;
StartSingle: PUBLIC ENTRY PROC = {
IF singleProcess = NIL THEN {
socket ← PupSocket.CreateServer[
local: PupWKS.fileLookup,
recvBuffers: 5,
getTimeout: PupSocket.waitForever ];
singleProcess ← CedarProcess.Fork[
SinglePacketListener, NIL, [priority: foreground, usePriority: TRUE]];
};
};
StopSingle: PUBLIC ENTRY PROC = {
IF singleProcess # NIL THEN {
PupSocket.Destroy[socket];
socket ← NIL;
};
};
SinglePacketListener: CedarProcess.ForkableProc = TRUSTED {
ENABLE UNWIND => singleProcess ← NIL;
DO
b: PupBuffer.Buffer = PupSocket.Get[socket];
IF b = NIL THEN EXIT;
SELECT b.type FROM
PupType.fileLookup => {
name: ROPE ← Rope.Cat["[]", PupSocket.ExtractRope[b]];
fileLen: INT ← 0;
fileDate: GMT ← BasicTime.nullGMT;
translated: BOOLFALSE;
[name, translated] ← RealName[name];
[fullFName: name, created: fileDate, bytes: fileLen] ← FS.FileInfo[name: name
! FS.Error => {
b.type ← PupType.fileLookupError;
b.hWord[0] ← error.group.ORD;
PupSocket.SetUserHWords[b, 1];
CONTINUE;
};
];
IF fileDate # BasicTime.nullGMT AND fileLen >= 0 THEN {
IF translated THEN {
fileLen ← (fileLen+999)/1000*1000;
fileDate ← BasicTime.Update[fileDate, 1]; };
b.fileLookupReply.version ← CurrentVersion[name];
b.fileLookupReply.createTime ← Endian.FFromCard[BasicTime.ToPupTime[fileDate]];
b.fileLookupReply.length ← Endian.FFromCard[fileLen];
b.type ← PupType.fileLookupReply;
PupSocket.SetUserSize[b, SIZE[PupBuffer.FileLookupReply]];
};
PupSocket.ReturnToSender[b]; };
ENDCASE => PupSocket.FreeBuffer[b];
ENDLOOP;
singleProcess ← NIL;
};
Initialization
Init: PROC ~ {
UserProfile.CallWhenProfileChanges[NoteProfile];
};
Init[];
END.