DIRECTORY Basics USING [FWORD, Card32FromF, Card16FromH], BasicTime USING [FromPupTime, GMT, Now, nullGMT, Period], FSBackdoor USING [Version], FSRemoteFileBackdoor USING [ServerHandle], Process USING [Detach, Ticks, SecondsToTicks], Pup USING [Address], PupBuffer USING [Buffer], PupHop USING [InitialTimeout], PupName USING [NameLookup, Error], PupSocket USING [AllocBuffer, CopyRope, CreateEphemeral, Destroy, FreeBuffer, Get, GetUniqueID, Send, SetNoErrors, Socket], PupType USING [fileLookup, fileLookupError, fileLookupReply], PupWKS USING [fileLookup], Rope USING [Equal, ROPE], RuntimeError USING [UNCAUGHT], STPFSRemoteFile USING [LookupResult, ServerData] ; STPFSRemoteLookupImpl: CEDAR MONITOR IMPORTS Basics, BasicTime, Process, PupHop, PupName, PupSocket, Rope, RuntimeError EXPORTS STPFSRemoteFile = { CARD: TYPE = LONG CARDINAL; GMT: TYPE = BasicTime.GMT; ROPE: TYPE = Rope.ROPE; Lookup: PUBLIC PROC [h: FSRemoteFileBackdoor.ServerHandle, file: ROPE] RETURNS [result: STPFSRemoteFile.LookupResult, version: FSBackdoor.Version, create: GMT, count: INT] = { sI: REF ServerInfo; [result, sI] _ FindServer[h]; IF result = ok THEN { [result, version, create, count] _ DoFileLookup[sI.addr, file]; SetState[sI, result]; }; }; serverList: REF ServerInfo _ NIL; -- list of known servers; keepingList: BOOL _ TRUE; packetCount: CARD _ 0; -- outgoing; also used as pup id ServerInfo: TYPE = RECORD [ name: ROPE, addr: Pup.Address, state: STPFSRemoteFile.LookupResult, -- can be noResponse, noSuchPort, or ok timeOK: GMT, -- GMT of last ok timeErr: GMT, -- GMT of last error next: REF ServerInfo]; FindServer: ENTRY PROC [h: FSRemoteFileBackdoor.ServerHandle] RETURNS [result: STPFSRemoteFile.LookupResult, info: REF ServerInfo] = TRUSTED { ENABLE UNWIND => NULL; server: ROPE _ h.name; result _ ok; FOR info _ serverList, info.next UNTIL info = NIL DO IF Rope.Equal[info.name, server, FALSE] THEN {result _ info.state; RETURN}; ENDLOOP; { data: STPFSRemoteFile.ServerData ~ NARROW[h.data]; name: ROPE _ data.serverPupName; addr: Pup.Address; addr _ PupName.NameLookup[name, PupWKS.fileLookup ! PupName.Error => { SELECT code FROM errorFromServer => result _ noSuchServer; ENDCASE => result _ noResponse; CONTINUE } ]; IF result # noSuchServer THEN { time: GMT _ BasicTime.Now[]; info _ NEW [ServerInfo _ [ name: server, addr: addr, state: result, timeOK: IF result = ok THEN time ELSE BasicTime.nullGMT, timeErr: IF result # ok THEN time ELSE BasicTime.nullGMT, next: serverList]]; IF serverList = NIL THEN Process.Detach[FORK ServerCollector[]]; IF keepingList THEN serverList _ info; }; }; }; DoFileLookup: PROC [addr: Pup.Address, file: ROPE] RETURNS [result: STPFSRemoteFile.LookupResult, version: FSBackdoor.Version, create: GMT, count: INT] = TRUSTED { tries: CARDINAL = 4; msWait: CARDINAL _ PupHop.InitialTimeout[addr.net, 2000]; id: Basics.FWORD _ PupSocket.GetUniqueID[]; socket: PupSocket.Socket; result _ noResponse; -- assume result IF msWait = 0 THEN RETURN; socket _ PupSocket.CreateEphemeral[remote: addr, getTimeout: msWait]; PupSocket.SetNoErrors[socket]; FOR i: NAT IN [0..tries) DO b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; b.type _ PupType.fileLookup; b.id _ id; PupSocket.CopyRope[b, file]; PupSocket.Send[socket, b, addr]; b _ PupSocket.Get[socket]; IF b = NIL THEN LOOP; -- no response yet IF b.id # id THEN { PupSocket.FreeBuffer[b]; LOOP; }; SELECT b.type FROM PupType.fileLookupReply => { result _ ok; version _ [Basics.Card16FromH[b.fileLookupReply.version]]; create _ BasicTime.FromPupTime[Basics.Card32FromF[b.fileLookupReply.createTime] ! RuntimeError.UNCAUGHT => {create _ BasicTime.nullGMT; CONTINUE}]; count _ Basics.Card32FromF[b.fileLookupReply.length]; }; PupType.fileLookupError => result _ noSuchFile; error => SELECT b.error.code FROM noSocket => result _ noSuchPort; cantGetThere => NULL; ENDCASE => { PupSocket.FreeBuffer[b]; LOOP; }; ENDCASE => { PupSocket.FreeBuffer[b]; LOOP; }; PupSocket.FreeBuffer[b]; EXIT; ENDLOOP; PupSocket.Destroy[socket]; }; SetState: ENTRY PROC [info: REF ServerInfo, state: STPFSRemoteFile.LookupResult] = { ENABLE UNWIND => NULL; time: GMT _ BasicTime.Now[]; IF state = ok THEN info.timeOK _ time ELSE info.timeErr _ time; SELECT state FROM noResponse, noSuchPort => info.state _ state; ENDCASE; }; pollingInterval: NAT _ 5; okTimeout: NAT _ 1800; noResponseTimeout: NAT _ 30; noSuchPortTimeout: NAT _ 30; errorTimeout: NAT _ 30; ServerCollector: ENTRY PROC = { ENABLE UNWIND => NULL; UNTIL serverList = NIL DO last: REF ServerInfo _ NIL; forPolling: CONDITION _ [Process.SecondsToTicks[pollingInterval]]; WAIT forPolling; FOR info: REF ServerInfo _ serverList, info.next UNTIL info = NIL DO time: GMT = BasicTime.Now[]; ageOK: INT = BasicTime.Period[info.timeOK, time]; ageErr: INT = BasicTime.Period[info.timeErr, time]; { SELECT info.state FROM ok => IF ageOK > okTimeout THEN GO TO Splice; noResponse => IF ageErr > noResponseTimeout THEN GO TO Splice; noSuchPort => IF ageErr > noSuchPortTimeout THEN GO TO Splice; ENDCASE => IF ageErr > errorTimeout THEN GO TO Splice; last _ info; EXITS Splice => IF last=NIL THEN serverList _ info.next ELSE last.next _ info.next; }; ENDLOOP; ENDLOOP; }; }. xSTPFSRemoteLookupImpl.mesa Copyright Σ 1984, 1985, 1986 by Xerox Corporation. All rights reserved. Schroeder, November 8, 1983 1:53 pm Levin, June 24, 1983 5:38 pm Russ Atkinson, March 18, 1985 10:41:54 pm PST Bob Hagmann November 14, 1986 8:23:59 am PST Hal Murray, June 3, 1986 4:33:20 pm PDT Doug Wyatt, December 12, 1986 3:00:45 pm PST Demers, October 27, 1987 0:46:09 am PST Exported to STPFSRemoteFile This really ought to be fixed to use the server cache in STPFSRemoteFileImpl. For now it does its own cacheing of server names and states. FileLookup protocol implementation keepingList => cache responses to try to reduce name lookup traffic and useless traffic when a server is obviously down Didn't find an entry, so make one DKW: formerly IF state = noSuchPort THEN info.state _ noSuchPort; seconds to wait before polling seconds to wait before having a cached OK server evaporate seconds to wait before having a noResponse evaporate seconds to wait before having a noSuchPort evaporate seconds to wait before having any other error evaporate Bob Hagmann April 29, 1985 10:25:49 am PDT changes to: DIRECTORY, FindServer Κ‚˜šœ™JšœH™HJ™#J™J™-Icode™,K™'K™,K™'—code1šΟk ˜ Lšœœœ˜/Lšœ œœ˜9Lšœ œ ˜Lšœœ˜*Lšœœ!˜.Lšœœ ˜Lšœ œ ˜Lšœœ˜Lšœœ˜"Lšœ œl˜{Lšœœ0˜=Lšœœ˜Lšœœ œ˜Lšœ œœ˜Lšœœ˜0L˜—šΟnœœ˜$LšœK˜RLšœ˜Lšœ˜L˜Lšœœœœ˜Lšœœ œ˜Lšœœœ˜—™Icode2™‹šžœœœ.œœMœ œ˜―Mšœœ ˜Mšœ˜šœ œ˜Mšœ?˜?Mšœ˜Mšœ˜—Mšœ˜——™"Mšœ œœΟcœ˜;šœ œœ˜Mšœw™w—Mšœ œŸ ˜7šœ œœ˜Mšœœ˜ Mšœ˜Mšœ%Ÿ'˜LMšœœŸ˜Mšœ œŸ˜"Mšœœ ˜—š ž œœœ(œ.œœ˜ŽMšœœœ˜Mšœœ ˜Mšœ ˜ šœœœ˜4Mšœœœœ˜KMšœ˜—M™!šœ˜Mšœ#œ ˜2Mšœœ˜ Mšœ˜šœ1˜1šœ˜šœ˜Mšœ)˜)Mšœ˜—Mšœ˜ ——šœœ˜Mšœœ˜šœœ˜Mšœ(˜(Mšœœ œœ˜8Mšœ œ œœ˜9Mšœ˜—Mšœœœœ˜@Mšœ œ˜&Mšœ˜—Mšœ˜—Mšœ˜—šž œœœœMœ œœ˜£Mšœœ˜Mšœœ)˜9Mšœ œ˜+Mšœ˜MšœŸ˜%Mšœ œœ˜MšœE˜EKšœ˜šœœœ ˜Mšœ4˜4Mšœ˜Mšœ ˜ Mšœ˜Mšœ ˜ Mšœ˜Mš œœœœŸ˜(Mšœ œœ˜5šœ˜šœ˜Mšœ ˜ Mšœ:˜:šœO˜OMšœœ!œ˜C—Mšœ8˜8—Mšœ/˜/šœ œ˜!Mšœ ˜ Mšœœ˜Mšœœ˜.—Mšœœ˜.—Mšœ˜Mšœ˜Mšœ˜—Mšœ˜Mšœ˜—šžœœœœ5˜TMšœœœ˜Mšœœ˜Mšœ œœ˜?šœ˜Mšœ-˜-Mšœ˜—Mšœœœ™AMšœ˜M˜—šœœ˜Mšœ™—šœ œ˜Mšœ:™:—šœœ˜Mšœ4™4—šœœ˜Mšœ4™4—šœœ˜Mšœ7™7—šžœœœ˜Mšœœœ˜šœœ˜Mšœœœ˜Mšœ  œ-˜BMšœ ˜š œœ$œœ˜DMšœœ˜Mšœœ'˜1Mšœœ(˜3Mšœ˜šœ ˜Mš œœœœœ˜-Mš œœœœœ˜>Mš œœœœœ˜>Mš œœœœœ˜6—Mšœ ˜ šœ ˜Mšœœœœ˜F—Mšœ˜—Mšœ˜—Mšœ˜——Lšœ˜K™K™™*Kšœ Οr™!—K™K™J˜—…—H B