<> <> <> DIRECTORY BasicTime USING [Now], CrRPC USING [CreateClientHandle, DestroyClientHandle, Error, Handle], FilingP10V5 USING [Handle, Session], PFinalize USING [EnableFinalization, FinalizationQueue, FQEmpty, FQNext, Handle, HandleToObject, NewFQ], PFS USING [Error], Rope USING [ROPE], RuntimeError USING [], XNSAuth USING [Conversation, GetNextVerifier], XNSFilingOps USING [CallProtected, ContinueOp, GuardOp, LogoffOp, LogonOp, MountRootOp, ServerData], XNSFilingSession USING [ServerHandle, ServerObject]; XNSFilingSessionImpl: CEDAR MONITOR IMPORTS BasicTime, CrRPC, PFinalize, PFS, XNSAuth, XNSFilingOps EXPORTS XNSFilingSession ~ { OPEN FilingP10V5, XNSFilingOps, XNSFilingSession; ROPE: TYPE ~ Rope.ROPE; <> dfq: PFinalize.FinalizationQueue ~ PFinalize.NewFQ[--20--]; CollectLostHandles: PROC ~ { <> WHILE ( NOT PFinalize.FQEmpty[dfq] ) DO handle: PFinalize.Handle ~ PFinalize.FQNext[dfq]; object: REF ~ PFinalize.HandleToObject[handle]; mnt: ServerData ~ NARROW[object]; ReleaseState: PROC ~ { LogoffOp[mnt] }; CallProtected[mnt, ReleaseState]; ENDLOOP; }; <> XNSSweepInner: ENTRY PROC [mnt: ServerData, seconds: CARD] RETURNS [cleanUp: BOOL _ FALSE] ~ { ENABLE UNWIND => NULL; SELECT TRUE FROM ( mnt.admin.trTTL > seconds ) => { mnt.admin.trTTL _ mnt.admin.trTTL - seconds }; ( NOT mnt.admin.active ) => { mnt.admin.trTTL _ 0; cleanUp _ TRUE }; <> ENDCASE => { NULL }; }; XNSSweep: PUBLIC PROC [h: ServerHandle, seconds: CARD] ~ { mnt: ServerData ~ NARROW[h.mnt]; ReleaseState: PROC ~ { LogoffOp[mnt] }; cleanUp: BOOL ~ XNSSweepInner[mnt, seconds]; IF ( cleanUp ) THEN CallProtected[mnt, ReleaseState]; CollectLostHandles[]; }; <> TransportProblem: TYPE ~ {serverInaccessible, connectionTimedOut}; ReportTransportError: PROC [problem: TransportProblem, sH: ServerHandle] ~ { ERROR; }; GetConnection: PROC [sH: ServerHandle] RETURNS [crH: CrRPC.Handle] ~ { mnt: ServerData ~ NARROW[sH.mnt]; crH _ CrRPC.CreateClientHandle[$SPP, mnt.address ! CrRPC.Error => ReportTransportError[$serverInaccessible, sH] ]; IF ( NOT Revive[mnt, crH] ) THEN { IF ( crH # NIL ) THEN CrRPC.DestroyClientHandle[crH ! CrRPC.Error => CONTINUE]; ReportTransportError[$connectionTimedOut, sH]; }; mnt.admin.active _ TRUE; }; <> initialConnectionTTL: CARD _ 8; credentialsErrorTTL: CARD _ 30; <> BogusAddress: ERROR ~ CODE; allHandles: LIST OF PFinalize.Handle _ NIL; RememberObject: PROC [h: PFinalize.Handle] ~ { }; EstablishConnection: PROC [server: ROPE] RETURNS [mnt: ServerData _ NIL] ~ { MountFileSystem: PROC ~ { mnt _ LogonOp[server]; MountRootOp[mnt] }; hook: PFinalize.Handle; GuardOp[MountFileSystem]; mnt.admin _ [tktTTL: 10000, trTTL: initialConnectionTTL, callsOut: 0, files: 0, lastOp: BasicTime.Now[], downMsg: NIL, active: FALSE]; hook _ PFinalize.EnableFinalization[mnt, dfq]; -- dropping handle! RememberObject[hook]; }; XNSGetServer: PUBLIC PROC [server: ROPE] RETURNS [h: ServerHandle _ NIL, downMsg: ROPE _ NIL] ~ { <> <> downMsg _ "can\'t connect"; { mnt: ServerData _ EstablishConnection[server]; h _ NEW[ServerObject _ [ --flavor: myFlavor, name: server, procs: myServerProcs,-- mnt: mnt]]; downMsg _ NIL; }; }; <> XNSValidate: PUBLIC ENTRY PROC [h: ServerHandle] RETURNS [obsolete: BOOL, downMsg: ROPE] ~ { ENABLE UNWIND => NULL; mnt: ServerData ~ NARROW[h.mnt]; IF ( mnt.admin.trTTL > 0 ) THEN [] _ ReviveInternal[mnt]; -- returns 0 on errors RETURN [(mnt.admin.trTTL <= 0), NIL]; }; minStart: CARD _ 10; -- seconds to allow credentials to get down to Revive: ENTRY PROC [mnt: ServerData, crH: CrRPC.Handle _ NIL] RETURNS [ok: BOOL _ FALSE] ~ { ENABLE UNWIND => NULL; IF ( mnt.admin.trTTL < minStart ) THEN RETURN[ReviveInternal[mnt]]; mnt.session.verifier _ XNSAuth.GetNextVerifier[mnt.tkt]; mnt.admin.trTTL _ mnt.timeToLive; RETURN[TRUE]; }; ReviveInternal: INTERNAL PROC [mnt: ServerData] RETURNS [ok: BOOL _ FALSE] ~ { ENABLE PFS.Error => { GOTO GiveUp }; PokeServer: PROC ~ { ContinueOp[mnt] }; CallProtected[mnt, PokeServer]; ok _ TRUE; EXITS GiveUp => { NULL }; }; <> Init: PROC = { <> }; Init[]; }.