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[];
};