YggdrasilInitImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bob Hagmann July 6, 1989 9:46:01 am PDT
Initialize Yggdrasil.
DIRECTORY
Camelot,
CamelotRecoverable,
IO USING [int, PutFR],
Mach,
Process USING [Detach, MsecToTicks, Pause],
Rope,
YggBuffMan,
YggDIDMap,
YggdrasilInit,
YggEnvironment;
YggdrasilInitImpl: CEDAR PROGRAM
IMPORTS Camelot, CamelotRecoverable, Mach, IO, Process, YggBuffMan, YggDIDMap, YggdrasilInit
EXPORTS YggdrasilInit, YggEnvironment
~ BEGIN
Exported global variables
dsPort: PUBLIC Mach.portT;
serverID: PUBLIC Camelot.serverIdT;
tsPort: PUBLIC Mach.portT;
mPort: PUBLIC Mach.portT;
sPort: PUBLIC Mach.portT;
dsqSharedMemAddr: PUBLIC Mach.vmAddressT;
tPort: PUBLIC Mach.portT;
aPort: PUBLIC Mach.portT;
atPort: PUBLIC Mach.portT;
taPort: PUBLIC Mach.portT;
applicationID: PUBLIC Camelot.applicationIdT;
Global variables
camlibServerPort: Mach.portT;
CamelotRecoveryComplete: BOOLFALSE;
ReadyForRecovery: PUBLIC BOOLFALSE;
Exported procedures
InitSeqDescList: Camelot.ListOfSegmentDesc;
InitSeqPortList: Mach.ListOfPorts;
InitializePart1: PUBLIC PROC [] ~ {
Initialize the data server to the transaction manager. Part 1 gets the segments known so that logging and recovery can run (under SunOS). Part 2 does the rest.
Perform the initializaion like CamLib that corresponds to the INITIALIZE←SERVER macro and START←SERVER procedure (procedures CamlibInitServerInternal and START←SERVER in src/lib/camlib/server←struct.c).
Then do a TA�pplication (code from src/lib/camlib/appl←struct.c and procedure INITIALIZE𡤊PPLICATION).
fullSeqDescList: Camelot.ListOfSegmentDesc;
fullSeqPortList: Mach.ListOfPorts;
firstTime: BOOL ← FALSE;
kernCode: Mach.kernReturnT;
{ -- InitializeGlobalData calling to ServerInit
dsPort ← GetTheDSPort[];
[serverID: serverID, tsPort: tsPort, mPort: mPort, sPort: sPort, sharedMemAddr: dsqSharedMemAddr, seqDescList: InitSeqDescList, seqPortList: InitSeqPortList, kernCode: kernCode] ← Camelot.DSInitialize[dsPort: dsPort, raiseSignal: TRUE];
Camelot.DSQInit[dsqSharedMemAddr];
};
TRUSTED {Process.Detach[FORK NotifyHandlerProcess[]];}; -- CamlibInitServerInternal
[fullSeqDescList, fullSeqPortList] ← CamelotRecoverable.CamelotRecoverableInit[];
IF fullSeqDescList = NIL THEN fullSeqDescList ← InitSeqDescList
ELSE {
FOR fsdl: Camelot.ListOfSegmentDesc ← fullSeqDescList, fsdl.rest UNTIL fsdl = NIL DO
IF fsdl.rest = NIL THEN {fsdl.rest ← InitSeqDescList; EXIT};
ENDLOOP;
};
IF fullSeqPortList = NIL THEN fullSeqPortList ← InitSeqPortList
ELSE {
FOR lop: Mach.ListOfPorts ← fullSeqPortList, lop.rest UNTIL lop = NIL DO
IF lop.rest = NIL THEN {lop.rest ← InitSeqPortList; EXIT};
ENDLOOP;
};
firstTime ← RecoverSegments[fullSeqDescList, fullSeqPortList, TRUE]; -- CamlibInitServerInternal
};
InitializePart2: PUBLIC PROC [serverName: Rope.ROPE, applName: Rope.ROPE] RETURNS [firstTime: BOOLFALSE] ~ {
firstTime ← RecoverSegments[InitSeqDescList, InitSeqPortList, FALSE]; -- CamlibInitServerInternal
[] ← Mach.portRestrict[Mach.taskSelf[], sPort, TRUE]; -- CamlibInitServerInternal
TRUSTED {Process.Detach[FORK SystemMessageHandler[]];}; -- CamlibInitServerInternal
{ -- PublicizeService
[newPort: camlibServerPort] ← Mach.portAllocate[Mach.taskSelf[], TRUE];
[] ← Mach.netnameCheckIn[Mach.nameServerPort[], serverName, Mach.taskSelf[], camlibServerPort, TRUE];
};
[] ← Mach.portUnrestrict[Mach.taskSelf[], camlibServerPort, TRUE];
TRUSTED {Process.Detach[FORK RequestHandler[]];};
Wait for recovery to complete (maybe lots of SR messages)
ReadyForRecovery ← TRUE;
WHILE ~CamelotRecoveryComplete DO Process.Pause[Process.MsecToTicks[50]] ENDLOOP;
{ -- TA�pplication setup
tPortList: Mach.ListOfPorts;
[portList: tPortList] ← Camelot.CALookup[Mach.nameServerPort[], "TranPort", "", 1, 1, TRUE];
IF tPortList = NIL THEN ERROR;
IF tPortList.rest # NIL THEN ERROR;
tPort ← tPortList.first;
[newPort: atPort] ← Mach.portAllocate[Mach.taskSelf[], TRUE];
[] ← Mach.portRestrict[Mach.taskSelf[], atPort, TRUE];
[applicationID: applicationID, taPort: taPort] ← Camelot.TAAddApplication[tPort: tPort, atPort: atPort, authName: applName, raiseSignal: TRUE];
TRUSTED {Process.Detach[FORK ApplSysMsgHandler[]];};
};
YggDIDMap.InitDIDMap[firstTime]; -- call after recovery completes and TAAddApplication
};
RecoveryComplete: PUBLIC PROC [] ~ {
CamelotRecoveryComplete ← TRUE;
};
Recovery
RecoverSegments: PROC [seqDescList: Camelot.ListOfSegmentDesc, seqPortList: Mach.ListOfPorts, firstPass: BOOL] RETURNS [firstTime : BOOL ] ~ {
Map "recoverable segments into memory and perform all necessary recovery on segments".
We process the segment list, perform all necessary recovery on segments, and tell the buff man about it.
Messages show up to tell us how to recover (to SystemMessageHandler -> srServer->YggSRProcsImpl-> ??). Finally, a SR←RecoveryComplete message causes RecoveryComplete to be called.
firstTime ← YggBuffMan.InitializeFilePageMgr[seqDescList: seqDescList, seqPortList: seqPortList, firstPass: firstPass];
};
Processes
NotifyHandlerProcess: PROC [] ~ {
Look for port death messages
taskNotifyPort: Mach.portT;
inMsg: REF Camelot.camlibSysReqMsgT;
np: REF Mach.notificationT;
taskNotifyPort ← Mach.taskNotify[];
inMsg ← NEW[Camelot.camlibSysReqMsgT];
DO
inMsg.head.msgSize ← BYTES[Camelot.camlibMsgT];
inMsg.head.msgLocalPort ← taskNotifyPort;
TRUSTED {
recCode: Mach.msgReturnT ← -1;
recCode ← Mach.msgReceive[header: LOOPHOLE[inMsg], option: Mach.MsgOptionNone, timeout: 0, raiseSignal: TRUE];
IF recCode = Mach.RcvTimedOut THEN EXIT;
np ← LOOPHOLE[inMsg];
};
IF np.notifyHeader.msgId # Mach.NotifyPortDeleted THEN SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on the notify port that was not NOTIFY←PORT�LETED; msg←id is %g",IO.int[np.notifyHeader.msgId]]]
ELSE {
SELECT np.notifyPort FROM
Mach.nameServerPort[] => SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on the notify port that the name server connection failed!"]];
dsPort => SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on the notify port that the DiskMan (DS) connection failed!"]];
ENDCASE => SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on the notify port that some random connection failed! (port # %g)", IO.int[np.notifyPort]]];
};
ENDLOOP;
};
SystemMessageHandler: PROC [] ~ {
inMsg: REF Camelot.camlibSysReqMsgT;
outMsg: REF Camelot.camlibSysRepMsgT;
inMsg ← NEW[Camelot.camlibSysReqMsgT];
outMsg ← NEW[Camelot.camlibSysRepMsgT];
DO
recCode: Mach.msgReturnT ← -1;
sendCode: Mach.msgReturnT ← -1;
inMsg.head.msgSize ← BYTES[Camelot.camlibMsgT];
inMsg.head.msgLocalPort ← sPort;
outMsg.retcode ← Mach.MigNoReply;
TRUSTED {recCode ← Mach.msgReceive[header: LOOPHOLE[inMsg], option: Mach.MsgOptionNone, timeout: 0, raiseSignal: TRUE];};
IF recCode = Mach.RcvTimedOut THEN EXIT;
IF ~YggdrasilInit.STServer[inMsg, outMsg] THEN {
IF ~YggdrasilInit.SRServer[inMsg, outMsg] THEN SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on the sPort port that is unrecognized; message ID is %g!", IO.int[inMsg.head.msgId]]];
};
IF outMsg.retcode # Mach.MigNoReply THEN TRUSTED {
sendCode ← Mach.msgSend[LOOPHOLE[outMsg], Mach.MsgOptionNone, 0, TRUE];
};
ENDLOOP;
};
stServer: PROC [inMsg: REF Camelot.camlibSysReqMsgT, outMsg: REF Camelot.camlibSysRepMsgT] RETURNS [messageUnderstood: BOOLFALSE] ~ {
Call the st←server code in src/lib/camlib/sys/stServer.c (MIG generated)
innerSTServert: PROC [InHeadP: POINTER TO Camelot.camlibSysReqMsgT, OutHeadP: POINTER TO Camelot.camlibSysReqMsgT] RETURNS [ok: BOOL] ~ TRUSTED MACHINE CODE {
"<st.h>.st←server"
};
messageUnderstood ← innerSTServert[LOOPHOLE[inMsg], LOOPHOLE[outMsg]];
};
srServer: PROC [inMsg: REF Camelot.camlibSysReqMsgT, outMsg: REF Camelot.camlibSysRepMsgT] RETURNS [messageUnderstood: BOOL ← FALSE]~ {
Call the sr←server code in src/lib/camlib/sys/stServer.c (MIG generated)
innerSRServert: PROC [InHeadP: POINTER TO Camelot.camlibSysReqMsgT, OutHeadP: POINTER TO Camelot.camlibSysReqMsgT] RETURNS [ok: BOOL]~ TRUSTED MACHINE CODE {
"<sr.h>.sr←server"
};
messageUnderstood ← innerSRServert[LOOPHOLE[inMsg], LOOPHOLE[outMsg]];
};
RequestHandler: PROC [] ~ {
inMsg: REF Camelot.camlibSysReqMsgT;
inMsg ← NEW[Camelot.camlibSysReqMsgT];
DO
recCode: Mach.msgReturnT ← -1;
inMsg.head.msgSize ← BYTES[Camelot.camlibMsgT];
inMsg.head.msgLocalPort ← Mach.PortEnabled;
TRUSTED {recCode ← Mach.msgReceive[header: LOOPHOLE[inMsg], option: Mach.MsgOptionNone, timeout: 0, raiseSignal: TRUE];};
IF recCode = Mach.RcvTimedOut THEN EXIT;
SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on some random port that is unrecognized; port number %gmessage ID is %g!", IO.int[inMsg.head.msgId], IO.int[inMsg.head.msgLocalPort]]];
ENDLOOP;
};
ApplSysMsgHandler: PROC [] ~ {
AT←TransactionHasDied messages will show up here (on the atPort)
inMsg: REF Camelot.camlibSysReqMsgT;
outMsg: REF Camelot.camlibSysRepMsgT;
inMsg ← NEW[Camelot.camlibSysReqMsgT];
outMsg ← NEW[Camelot.camlibSysRepMsgT];
DO
recCode: Mach.msgReturnT ← -1;
sendCode: Mach.msgReturnT ← -1;
inMsg.head.msgSize ← BYTES[Camelot.camlibMsgT];
inMsg.head.msgLocalPort ← atPort;
outMsg.retcode ← Mach.MigNoReply;
TRUSTED {recCode ← Mach.msgReceive[header: LOOPHOLE[inMsg], option: Mach.MsgOptionNone, timeout: 0, raiseSignal: TRUE];};
IF recCode = Mach.RcvTimedOut THEN EXIT;
IF YggdrasilInit.ATServer[inMsg, outMsg] THEN {
IF outMsg.retcode # Mach.MigNoReply THEN TRUSTED {
sendCode ← Mach.msgSend[LOOPHOLE[outMsg], Mach.MsgOptionNone, 0, TRUE];
};
}
ELSE SIGNAL Mach.MachAnomaly[IO.PutFR["Got a message on the atPort port that is unrecognized; message ID is %g!", IO.int[inMsg.head.msgId]]];
ENDLOOP;
};
atServer: PROC [inMsg: REF Camelot.camlibSysReqMsgT, outMsg: REF Camelot.camlibSysRepMsgT] RETURNS [messageUnderstood: BOOLFALSE] ~ {
Call the st←server code in src/lib/camlib/sys/atServer.c (MIG generated)
innerSTServert: PROC [InHeadP: POINTER TO Camelot.camlibSysReqMsgT, OutHeadP: POINTER TO Camelot.camlibSysReqMsgT] RETURNS [ok: BOOL] ~ TRUSTED MACHINE CODE {
"<at.h>.at←server"
};
messageUnderstood ← innerSTServert[LOOPHOLE[inMsg], LOOPHOLE[outMsg]];
};
Utilities
GetTheDSPort: PROC RETURNS[dsPort: Mach.portT] ~ {
Get the ds port. Copied from CamLib/server←struct.c
intPortSet: Mach.portArrayT;
intPortArrayCount: INT;
kernCode: Mach.kernReturnT;
TRUSTED {
[intPortSet: intPortSet, intPortArrayCount: intPortArrayCount, kernCode: kernCode] ← Mach.MachPortsLookup[targetTask: Mach.taskSelf[], raiseSignal: TRUE];
IF intPortArrayCount < Mach.MachPortsSlotsUsed THEN ERROR;
dsPort ← (intPortSet+ UNITS[Mach.portArrayT] *Mach.MachPortsSlotsUsed)^;
};
[] ← Mach.vmDeallocate[Mach.taskSelf[], LOOPHOLE[intPortSet], BYTES[Mach.portArrayT]*intPortArrayCount, TRUE];
};
GetTheDSPort: PROC RETURNS[dsPort: Mach.portT] ~ {
Get the ds port. Calls into CamLib/server←struct.c
innerGetTheDSPort: PROC RETURNS [idsPort: Mach.portT] ~ TRUSTED MACHINE CODE {
"+extern port←t GetDSPort();.$GetDSPort"
};
dsPort ← innerGetTheDSPort[];
};
Initialization
END.