PhRegisterImpl.mesa
Copyright Ó 1990, 1992 by Xerox Corporation. All rights reserved.
Vin, September 25, 1990 5:40 pm PDT
Swinehar, October 1, 1992 4:09 pm PDT
DIRECTORY
IO USING [ atom, rope ],
PhSmarts USING [ lock, PhoenixInfo, PhoenixInfoBody, phoenixInfo, pd, SHHH ],
Process USING [ Detach, SecondsToTicks, SetTimeout ],
Rope USING [ Equal, ROPE ],
ThParty,
ThPartySunRPControl USING [ ReportProblem, ReportState, ThrushConnect, ThrushDisconnect, ThrushReportState ],
Thrush,
ThSmartsSunExport USING [ ExportInterface ],
UserProfile USING [ Token ],
VoiceUtils USING [ CurrentRName, CurrentPasskey, OwnNetAddress, Problem, ProblemFR, Report, RopeFromSunAddr ]
;
~
BEGIN
OPEN PhSmarts;
NB: TYPE = Thrush.NB;
ROPE: TYPE = Rope.ROPE;
uniqueSuffix: CARD ¬ 0;
InitPhoenixSmarts:
PUBLIC
ENTRY
PROC [
thrushInstance: Thrush.ROPE¬NIL
] = {
ENABLE UNWIND => NULL;
problem: ROPE¬NIL; nb: NB¬$serverDown;
prevInfo: PhSmarts.PhoenixInfo ¬ PhSmarts.phoenixInfo;
IF phoenixInfo#NIL AND phoenixInfo.connected THEN UnInitPhoenixSmartsInt[];
phoenixInfo ¬ NEW[PhSmarts.PhoenixInfoBody]; -- Dump any old one!
IF prevInfo#NIL THEN NOTIFY prevInfo.pollCondition;
phoenixInfo.conversations ¬ NIL;
phoenixInfo.connected ¬ FALSE;
thrushInstance ¬
SELECT
TRUE
FROM
thrushInstance#NIL => thrushInstance,
prevInfo#NIL AND prevInfo.prevThrushInstance#NIL => prevInfo.prevThrushInstance,
ENDCASE=> UserProfile.Token["ThrushSunClientServerInstance", "Growler"];
phoenixInfo.prevThrushInstance ¬ thrushInstance;
uniqueSuffix ¬ ThSmartsSunExport.ExportInterface[port: uniqueSuffix];
phoenixInfo.
myName ¬ [
type: "ThSmarts.Lark",
instance: VoiceUtils.RopeFromSunAddr[port: uniqueSuffix]];
phoenixInfo.myRName ¬ VoiceUtils.CurrentRName[];
phoenixInfo.myPassword ¬ VoiceUtils.CurrentPasskey[];
Now connect to server and register with Thrush
phoenixInfo.
shh ¬ ThPartySunRPControl.ThrushConnect[
server: thrushInstance, rName: phoenixInfo.myRName, type: $telephone,
interface: phoenixInfo.myName, properties: [role: $voiceTerminal, netAddress: VoiceUtils.OwnNetAddress[]], reportState: ReportStateFromThPartyRPC, reportProblem: ReportProblemFromThPartyRPC];
TRUSTED { Process.Detach[FORK PollWaiter[phoenixInfo]]; };
};
UnInitPhoenixSmarts:
PUBLIC
ENTRY
PROC[disable:
BOOL¬
TRUE] = {
ENABLE UNWIND=>NULL;
UnInitPhoenixSmartsInt[disable];
};
UnInitPhoenixSmartsInt:
INTERNAL
PROC[disable:
BOOL¬
TRUE] = {
shhh: PhSmarts.SHHH ¬ IF phoenixInfo#NIL THEN phoenixInfo.shh ELSE NIL;
IF shhh=NIL THEN RETURN;
ThPartySunRPControl.ThrushDisconnect[shhh, disable];
IF disable THEN ThPartySunRPControl.ReleaseConversation[shhh];
That's just a cleanliness, and I'm worried about not adequately recording the last Progress and Substitution reports as they drag in. Before putting this back, analyze some typical traffic flow and see what's needed. Perhaps the previous stuff should be put on a timer, then destroyed. Worry, if ever we don't destroy phoenixInfo and create a new one, about the possibility that old reports will encounter strange credentials. DCS, September 13, 1990 11:57:37 am PDT
};
PhoenixIsRunning:
PUBLIC
PROC
RETURNS [phoenixIsEnabled: BOOL¬FALSE, phoenixIsRunning: BOOL¬FALSE] = {
IF phoenixInfo=NIL THEN RETURN;
RETURN[phoenixInfo.enabled, phoenixInfo.connected];
};
RecordSystemStateFromSmartsReport:
PUBLIC
INTERNAL
PROC[
nb: NB, remark: Rope.ROPE, connected: BOOL, enabled: BOOL, voicePath: BOOL, remoteRemark: Rope.ROPE ]
RETURNS[echoNB: NB] -- A convenience for callers -- = {
IF phoenixInfo.shh#
NIL
THEN
ThPartySunRPControl.ThrushReportState[phoenixInfo.shh, enabled, connected];
RETURN[RecSS[nb, remark, connected, enabled, voicePath, remoteRemark]];
};
nextSched:
INT ¬ pd.pollDefault;
PollWaiter:
ENTRY
PROC[myInfo: PhSmarts.PhoenixInfo] = {
ENABLE UNWIND => NULL;
nextSched ¬ pd.pollDefault;
WHILE myInfo = phoenixInfo
DO
nextSched ¬ MIN[nextSched, pd.pollDefault];
TRUSTED { Process.SetTimeout[@myInfo.pollCondition, Process.SecondsToTicks[nextSched]]; };
WAIT phoenixInfo.pollCondition;
IF myInfo#phoenixInfo THEN RETURN;
IF phoenixInfo.nextScheduledCheck#0
THEN {
nextSched ¬ phoenixInfo.nextScheduledCheck; phoenixInfo.nextScheduledCheck ¬ 0; LOOP; }
ELSE nextSched ¬ nextSched + 30;
Ordinary case: received another CheckIn report before timeout.
IF ~phoenixInfo.enabled OR ~pd.doPollingTimeouts THEN LOOP;
Timeout occurred before next CheckIn report, and either we're disconnected or we've been told to worry if we haven't heard from the server (or it's been quite a while, we've been told not to worry, and we're paranoid. Calling any ThParty function will either succeed or the failure will trigger the best available recovery activities.
[] ¬ ThParty.CheckIn[shh: phoenixInfo.shh, credentials: [
partyID: phoenixInfo.partyID, smartsID: phoenixInfo.smartsID, convID: Thrush.nullConvID]];
ENDLOOP;
};
ReportProblemFromThPartyRPC:
--already ENTRY-- ThPartySunRPControl.ReportProblem ~ {
[]¬RecSS[nb: ec, remark: expl];
};
ReportStateFromThPartyRPC:
--already ENTRY-- ThPartySunRPControl.ReportState ~ {
IF phoenixInfo#
NIL
THEN {
phoenixInfo.partyID ¬ myPartyID;
phoenixInfo.smartsID ¬ mySmartsID;
};
[]¬RecSS[connected: registered, enabled: enabled];
};
Poke:
PUBLIC
ENTRY
PROC = {
ENABLE UNWIND => NULL;
IF phoenixInfo#NIL THEN NOTIFY phoenixInfo.pollCondition; };
Polling loop will awaken immediately and if necessary (and not inhibited) try to reconnect.
Generalized reporting utility
RecSS:
--may be INTERNAL--
PROC[
nb: NB¬NIL,
remark: Rope.ROPE¬NIL,
connected: BOOL¬phoenixInfo.connected,
enabled: BOOL¬phoenixInfo.enabled,
voicePath: BOOL¬FALSE,
remoteRemark: Rope.ROPE¬NIL
]
RETURNS[echoNB: NB] -- A convenience for callers -- = {
IF nb#
NIL
OR connected#phoenixInfo.connected
OR enabled#phoenixInfo.enabled
THEN {
IF nb#NIL THEN NBProblem[remark, nb]
ELSE IF remark#NIL THEN VoiceUtils.Report[remark, $Finch];
};
phoenixInfo.connected ¬ connected;
phoenixInfo.enabled ¬ enabled;
pd.requests.QueueClientAction[ReportSystemStateToFinchClients, NIL];
IF remoteRemark#
NIL
THEN {
Relate each distinct remote remark exactly once.
IF phoenixInfo=
NIL
OR ~remoteRemark.Equal[phoenixInfo.lastRemoteRemark]
THEN VoiceUtils.Report[remoteRemark, $Finch];
IF phoenixInfo#NIL THEN phoenixInfo.lastRemoteRemark ¬ remoteRemark;
};
RETURN[nb];
};
NBProblem:
PROC[remark:
ROPE¬
NIL, nb:
NB¬
NIL] = {
IF nb=
NIL
THEN VoiceUtils.Problem[remark, $Finch]
ELSE VoiceUtils.ProblemFR["%g, reason: %g", $Finch, NIL, IO.rope[remark], IO.atom[nb]];
};