GetFS:
PUBLIC
PROC [fs:
ROPE]
RETURNS [h: FSHandle] ~ {
Raises Error if server is down.
obsolete: BOOL;
downMsg: ROPE;
fsWithoutSuffix: ROPE;
kids: LIST OF PROCESS ¬ NIL;
response: GetFSResponse;
theRegistration: Registration;
startedPulses: Pulses;
MakeChild: ENTRY PROC [r: Registration] RETURNS [p: PROCESS] ~ --INLINE-- {
ENABLE UNWIND => NULL;
p ¬ FORK DoGetFS[r, fs, FALSE, response];
response.nRunning ¬ response.nRunning + 1;
};
WaitForResponse: ENTRY PROC ~ --INLINE-- {
ENABLE UNWIND => NULL;
set [h, downMsg] ...
WHILE (response.nRunning > 0) AND (response.handle = NIL) AND (response.downMsg = NIL) DO
sinceStarted: INT ~ PulsesToSeconds[PeriodPulses[from~startedPulses, to~NowPulses[]]];
IF sinceStarted >= waitForFSTimeout THEN EXIT;
TRUSTED { Process.SetTimeout[@response.wakeup, Process.MsecToTicks[1000*(waitForFSTimeout-sinceStarted)+500]] };
WAIT response.wakeup;
ENDLOOP;
h ¬ response.handle;
downMsg ¬ response.downMsg;
};
h ¬ NARROW[SymTab.Fetch[fsTab, fs].val];
IF h #
NIL
THEN {
[obsolete, downMsg] ¬ h.maintenanceProcs.validate[h];
IF
NOT obsolete
THEN {
IF downMsg # NIL THEN ErrorDownFS[h, downMsg];
RETURN;
};
};
response ¬ NEW [GetFSResponseObject];
FOR theRegistration ¬ registrations, theRegistration.next
WHILE theRegistration #
NIL
DO
suffixLen, pos: INT;
suffixLen ¬ Rope.Length[theRegistration.nameSuffix];
pos ¬ Rope.Length[fs] - suffixLen;
IF (pos >= 0)
AND Rope.EqualSubstrs[fs, pos, suffixLen, theRegistration.nameSuffix, 0, suffixLen,
FALSE]
THEN { fsWithoutSuffix ¬ Rope.Substr[fs, 0, pos]; EXIT };
ENDLOOP;
IF theRegistration #
NIL
THEN {
DoGetFS[theRegistration, fsWithoutSuffix, TRUE, response];
IF (h ¬ response.handle) # NIL THEN h.name ¬ fs;
downMsg ¬ response.downMsg;
};
ELSE {
startedPulses ¬ NowPulses[];
TRUSTED { Process.EnableAborts[@response.wakeup] };
FOR each: Registration ¬ registrations, each.next WHILE each # NIL DO
kids ¬ CONS [MakeChild[each], kids];
ENDLOOP;
WaitForResponse[];
FOR kid: LIST OF PROCESS ¬ kids, kid.rest WHILE kid # NIL DO
TRUSTED { Process.Abort[kid.first] };
TRUSTED { Process.Detach[kid.first] };
ENDLOOP;
};
IF h =
NIL
THEN {
IF downMsg =
NIL
THEN {
downMsg ¬ "unknown fs";
h ¬ MakeDownFS[fs, $serverNotKnown, downMsg];
}
ELSE {
h ¬ MakeDownFS[fs, $serverNotAvailable, downMsg];
};
};
[] ¬ SymTab.Store[fsTab, h.name, h];
IF downMsg # NIL THEN ErrorDownFS[h, downMsg];
};
DoGetFS:
PROC [r: Registration, fs:
ROPE, flavorSpecified:
BOOL, response: GetFSResponse] ~ {
h: FSHandle ¬ NIL;
downMsg: ROPE ¬ NIL;
NotifyDone:
ENTRY
PROC ~
--INLINE-- {
ENABLE UNWIND => NULL;
response.nRunning ¬ response.nRunning - 1;
IF (response.handle # NIL) OR (response.downMsg # NIL) THEN RETURN;
SELECT
TRUE
FROM
(h #
NIL)
OR (downMsg #
NIL) =>
-- found it -- {
response.handle ¬ h;
response.downMsg ¬ downMsg;
NOTIFY response.wakeup;
};
(response.nRunning = 0) =>
-- nobody will find it -- {
NOTIFY response.wakeup;
};
ENDCASE;
};
[h, downMsg] ¬ r.getHandle[fs, flavorSpecified
! Error -- can't happen--, ABORTED => CONTINUE];
NotifyDone[];
};