<> <> DIRECTORY BasicTime USING [GMT, Now], Booting, FingerLog, FingerOps, FingerSimpleOps, Idle USING [IdleReason, IdleHandler, RegisterIdleHandler], Process USING [Detach], RemoteFingerOps, RemoteFingerOpsRpcControl, Rope USING [ROPE], RPC, RPCLupineExtras, ThisMachine USING [Address, Name], UserCredentials USING [Get], UserProfile; FingerSimpleOpsImpl: CEDAR MONITOR IMPORTS BasicTime, Booting, FingerLog, Idle, Process, RemoteFingerOps, RemoteFingerOpsRpcControl, RPC, ThisMachine, UserCredentials, UserProfile EXPORTS FingerOps, FingerSimpleOps = BEGIN OPEN FingerOps, FingerLog; idle: BOOL _ FALSE; <> <> thisMachine: Rope.ROPE _ ThisMachine.Name[$Pup]; <> serverMachine: Rope.ROPE; stateLog: LIST OF LogEntry _ NIL; bound: BOOL _ FALSE; ImportPlayProc: PROC [host: Rope.ROPE _ NIL] ~ { success: BOOL _ TRUE; <> RemoteFingerOpsRpcControl.ImportInterface[interfaceName: [instance: IF host = NIL THEN serverMachine ELSE host] ! RPC.ImportFailed => { success _ FALSE; CONTINUE }]; bound _ success; }; PlayLog: INTERNAL PROC[] ~ { IF (stateLog # NIL) THEN { IF NOT bound THEN ImportPlayProc[]; IF bound THEN { ENABLE RPC.CallFailed => {bound _ FALSE; CONTINUE}; IF RemoteFingerOps.PlayLog[stateLog] THEN { <> stateLog _ NIL; FingerLog.FlushLog[] }; }; }; }; AttemptToPlayLog: PUBLIC ENTRY PROC[] = { ENABLE UNWIND => NULL; PlayLog[] }; RegisterLoginOrLogout: ENTRY Idle.IdleHandler = TRUSTED BEGIN ENABLE UNWIND => NULL; idle _ reason = becomingIdle; InternalPutStateChange[IF idle THEN $logout ELSE $login, BasicTime.Now[]]; Process.Detach[FORK AttemptToPlayLog[]] END; PutStateChange: PUBLIC ENTRY PROC [change: FingerOps.StateChange, time: BasicTime.GMT] ~ { <> ENABLE UNWIND => NULL; InternalPutStateChange[change, time]; IF NOT idle THEN PlayLog[] }; InternalPutStateChange: INTERNAL PROC [change: FingerOps.StateChange, time: BasicTime.GMT] ~ { name: Rope.ROPE = UserCredentials.Get[].name; DoLog[logEntry: NEW[StateChange LogEntryObject _ [StateChange[event: change, user: name, time: time, machine: thisMachine]]]]; }; DoLog: INTERNAL PROC[ logEntry: LogEntry ] = TRUSTED { <> FingerLog.Log[ logEntry ]; IF stateLog = NIL THEN stateLog _ LIST[logEntry] ELSE { log: LIST OF LogEntry _ stateLog; WHILE log.rest # NIL DO log _ log.rest ENDLOOP; log.rest _ LIST[logEntry] } }; Log: PUBLIC ENTRY PROC [logEntry: LogEntry] ~ { DoLog[logEntry]; }; ParseLog: INTERNAL PROC[] ~ { stateLog _ FingerLog.ParseLog[] }; GetLogAndLoginUser: ENTRY PROC[] ~ { ENABLE UNWIND => NULL; ParseLog[]; InternalPutStateChange[$login, BasicTime.Now[]]; TRUSTED { Process.Detach[FORK AttemptToPlayLog[]] } }; OpenUp: Booting.RollbackProc = TRUSTED { bound _ FALSE; Process.Detach[FORK GetLogAndLoginUser[]] }; ProfileChanged: UserProfile.ProfileChangedProc = { serverMachine _ UserProfile.Token["Finger.RemoteHost", "Ebbetts"]; }; IF thisMachine = NIL THEN thisMachine _ ThisMachine.Address[$Pup]; IF thisMachine = NIL THEN thisMachine _ "Unknown"; UserProfile.CallWhenProfileChanges[proc: ProfileChanged]; ImportPlayProc[]; Booting.RegisterProcs[r: OpenUp]; GetLogAndLoginUser[]; [] _ Idle.RegisterIdleHandler[handler: RegisterLoginOrLogout] END.