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 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; camlibServerPort: Mach.portT; CamelotRecoveryComplete: BOOL _ FALSE; ReadyForRecovery: PUBLIC BOOL _ FALSE; InitSeqDescList: Camelot.ListOfSegmentDesc; InitSeqPortList: Mach.ListOfPorts; InitializePart1: PUBLIC PROC [] ~ { 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: BOOL _ FALSE] ~ { 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[]];}; ReadyForRecovery _ TRUE; WHILE ~CamelotRecoveryComplete DO Process.Pause[Process.MsecToTicks[50]] ENDLOOP; { -- TA_AddApplication 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; }; RecoverSegments: PROC [seqDescList: Camelot.ListOfSegmentDesc, seqPortList: Mach.ListOfPorts, firstPass: BOOL] RETURNS [firstTime : BOOL ] ~ { firstTime _ YggBuffMan.InitializeFilePageMgr[seqDescList: seqDescList, seqPortList: seqPortList, firstPass: firstPass]; }; NotifyHandlerProcess: PROC [] ~ { 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_DELETED; 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; }; 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 [] ~ { 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; }; GetTheDSPort: PROC RETURNS[dsPort: Mach.portT] ~ { 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]; }; END. €YggdrasilInitImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Bob Hagmann July 6, 1989 9:46:01 am PDT Initialize Yggdrasil. Exported global variables Global variables Exported procedures 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_AddApplication (code from src/lib/camlib/appl_struct.c and procedure INITIALIZE_APPLICATION). Wait for recovery to complete (maybe lots of SR messages) Recovery 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. Processes Look for port death messages stServer: PROC [inMsg: REF Camelot.camlibSysReqMsgT, outMsg: REF Camelot.camlibSysRepMsgT] RETURNS [messageUnderstood: BOOL _ FALSE] ~ { 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_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_server" }; messageUnderstood _ innerSRServert[LOOPHOLE[inMsg], LOOPHOLE[outMsg]]; }; AT_TransactionHasDied messages will show up here (on the atPort) atServer: PROC [inMsg: REF Camelot.camlibSysReqMsgT, outMsg: REF Camelot.camlibSysRepMsgT] RETURNS [messageUnderstood: BOOL _ FALSE] ~ { 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_server" }; messageUnderstood _ innerSTServert[LOOPHOLE[inMsg], LOOPHOLE[outMsg]]; }; Utilities Get the ds port. Copied from CamLib/server_struct.c 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 Κ Τ˜code•Mark outsideHeaderšœ™Kšœ<™œΟc˜bKšœ/œ ˜RKšœœ ˜Tšœ ˜KšœAœ˜GKšœ_œ˜eK˜—K˜Kšœ<œ˜Bšœœ˜1Kšœ-œ ™9—Kšœœ˜Kšœœ(œ˜Qšœ ˜Kšœ˜KšœVœ˜\Kšœ œœœ˜Kšœœœœ˜#Kšœ˜Kšœ7œ˜=Kšœ0œ˜6Kšœ‰œ˜Kšœœ˜4K˜—Kšœ! 5˜VK˜K™—šŸœœœ˜$Kšœœ˜K˜K™——™K™š ŸœœTœœœ˜ŽKšœV™VKšœh™hKšœsœ?™΄Kšœw˜wK˜——™ K™šŸœœ˜!Kšœ™Kšœ˜Kšœœ˜$Kšœœ˜Kšœ#˜#Kšœœ˜&š˜Kšœœ˜/Kšœ)˜)šœ˜ Kšœ˜Kšœ"œ>œ˜nKšœœœ˜(Kšœœ˜K˜—Kš œ0œœœYœ˜Ιšœœ˜šœ˜KšœœœT˜‡Kšœ œœU˜yKšœœœ[œ˜˜—Kšœ˜—Kšœ˜—K˜K˜—šŸœœ˜!Kšœœ˜$Kšœœ˜%Kšœœ˜&Kšœ œ˜'š˜Kšœ˜Kšœ˜Kšœœ˜/Kšœ ˜ Kšœ!˜!Kšœ$œ>œ˜yKšœœœ˜(šœ(œ˜0Kš œ(œœœRœ˜ΆK˜—šœ"œœ˜2Kšœœ!œ˜GK˜—Kšœ˜—K˜K˜—šΟbœœ œ#œœœœ™ˆK™Hšœœ œœ%œœœœœœœ™žKšœ™K™—Kšœ#œ œ ™FK™K™—š‘œœ œ#œG™‡K™Hšœœ œœ%œœœœœœœ™Kšœ™K™—Kšœ#œ œ ™FK™K˜—šŸœœ˜Kšœœ˜$Kšœœ˜&š˜Kšœ˜Kšœœ˜/Kšœ+˜+Kšœ$œ>œ˜yKšœœœ˜(Kšœœbœœ ˜ΈKšœ˜—K˜K˜—šŸœœ˜Kšœ>™@Kšœœ˜$Kšœœ˜%Kšœœ˜&Kšœ œ˜'š˜Kšœ˜Kšœ˜Kšœœ˜/Kšœ!˜!Kšœ!˜!Kšœ$œ>œ˜yKšœœœ˜(šœ'œ˜/šœ"œœ˜2Kšœœ!œ˜GK˜—K˜K˜—Kš œœœœSœ˜ŽKšœ˜—K˜K˜—š‘œœ œ#œœœœ™ˆK™Hšœœ œœ%œœœœœœœ™žKšœ™K™—Kšœ#œ œ ™FK™K™K™——™ šŸ œœœ˜2Kšœ5™5Kšœ˜Kšœœ˜Kšœ˜šœ˜ Kšœ”œ˜šKšœ:˜:KšœH˜HK˜—Kšœn˜nK˜K™K™—šŸ œœœ™2Kšœ4™4š œœœœœœ™NJšœ(™(K™—Kšœ™K™K™K™——™K˜—K˜Kšœ˜—…—04¨