!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.*** MODULE MCSONC(RESERVE(#11, #12, #13, #14), SREG = #17, FREG = #16, DREGS = 4, VREG = #15, MLIST, TIMER = EXTERNAL(SIX12), FSAVE ) = BEGIN REQUIRE DATA.BLI; ! EVERYONE NEEDS THIS EXTERNAL LEAFDSKTAB,TRMDSKTAB,DELDSKGH,DELGH,DGPURGE,GPURGE,BUILD,MOVE,LINK,CHKRUN; FORWARD FIXLEAVES, FIXTERMINALS, FIXGROUP; BIND DEFERRED = TRUE; STRUCTURE HALFFORMAT[ I ] = IF .I THEN ( .HALFFORMAT + .I / 2 ) ELSE ( .HALFFORMAT + .I / 2 ); STRUCTURE SIMPLEFORMAT[WD,I,J] = (.SIMPLEFORMAT + .WD)<.I,.J>; GLOBAL ROUTINE MCSONCE = BEGIN FIXLEAVES(); FIXTERMINALS() END; COMMENT; ! ROUTINE FIXLEAVES ! ======= ========= ! THIS ROUTINE READS THE FAILSOFT FILE AND FIXES THE IN-CORE DATABASE ROUTINE FIXLEAVES = BEGIN REGISTER NEXT, DSKGHTABPTR; LOCAL PTL, DSKGHADDR, LEAFPTR, GHPTR, DSKMHPTR; LOCAL EMPTYFLAG; LOCAL PTAB[ PTLSIZE ], ! THIS IS USED TO STORE THE LEAF DSKGH TABLE DSKGHTAB[ PTLSIZE ], ! THIS IS USED TO STORE A DSKGH LPTPTL; ! NEXT LEAF DSKGHPTR PLT TO USE MAP SIMPLEFORMAT DSKGHTAB; MAP FORMAT GHPTR; MAP FORMAT LEAFPTR; MAP HALFFORMAT PTAB; LPTPTL _ .IBASE; ! START WITH THE FIRST PARTICLE ! OF THE LEAF GROUP POINTER TABLE NEXT _ LEAFPERPTL; ! FORCE A READ THE FIRST TIME THRU THE LOOP INCR LEAFNO FROM 0 TO .N0LFNO DO ! FOR ALL LEAVES DO BEGIN IF .NEXT GEQ LEAFPERPTL THEN ! DO WE NEED TO READ BEGIN MOVE( DREAD( .LPTPTL ), PTAB, PTLSIZE ); ! YES THEN DO SO AND STORE IN PTAB NEXT _ 0; ! RESET OUR INDEX INTO PTAB LPTPTL _ .LPTPTL + 1 ! SET NEXT PTL TO READ END ELSE NEXT _ .NEXT + 1; ! NO READ THEN INC THE INDEX DSKGHTABPTR _ .PTAB[ .NEXT ]; ! GET A DSK GH TABLE POINTER LEAFPTR _ .LFPTRTAB[ .LEAFNO ]; ! GET THE LEAF'S ADDRESS BASE UPON IT'S NUMBER WHILE .DSKGHTABPTR NEQ 0 DO ! WHILE THERE ARE DSKGH'S BEGIN MOVE( DREAD( PTL _ .DSKGHTABPTR ), DSKGHTAB, PTLSIZE ); ! READ A GROUP EMPTYFLAG _ TRUE; !ASSUME EMPTY IF .DSKGHTAB[DG0NEXT] EQL 0 THEN LEAFDSKTAB[.LEAFNO] _ .PTL; DSKGHTABPTR _ .DSKGHTAB[ DG0NEXT ]; ! NEXT GROUP TO READ INCR I FROM 1 TO DG0MAX DO ! AND PROCESS THE GROUP IF ( DSKMHPTR _ .DSKGHTAB[ DG0MH( .I ) ] ) NEQ 0 THEN ! IF NON-ZERO BEGIN EMPTYFLAG _ FALSE; !NOT EMPTY DSKGHADDR _ .I; DSKGHADDR _ .PTL; IF ( GHPTR _ FIXGROUP( .DSKGHTAB[ DG0TSN( .I ) ], .DSKGHTAB[ DG0SENDER( .I ) ], .DSKMHPTR, .DSKGHADDR, NOT DEFERRED ) ) NEQ 0 THEN ! RECONSTITUTE THE GROUP BEGIN LINK( LEAFPTR[N0GHS], .GHPTR ); ! ATTACH IT TO THE TREE GHPTR[ G0LFPTR ] _ .LEAFPTR; ! STORE POINTER TO OWNER CHKRUN( .LEAFPTR, 1, .GHPTR ); ! AND SEE IF ANYONE TO START LEAFPTR[N0TSCORE] _ 0 !NO TRANSACTIONS IN CORE ON RESTART END END; IF .EMPTYFLAG THEN DELDSKGH( 1^18 + .PTL, LEAFTYPE) END END END; COMMENT; ! ROUTINE FIXTERMINALS ! ======= ============ ! THIS ROUTINE FIXES THE IN-CORE DATABASE FOR THE TERMINALS ROUTINE FIXTERMINALS = BEGIN REGISTER NEXT, DSKGHTABPTR; LOCAL PTL, DSKGHADDR, GHPTR, DEST, DSKMHPTR; LOCAL EMPTYFLAG; LOCAL PTAB[ PTLSIZE ], ! THIS IS USED TO STORE THE LEAF DSKGH TABLE DSKGHTAB[ PTLSIZE ], ! THIS IS USED TO STORE A DSKGH LPTPTL; ! NEXT LEAF DSKGHPTR PLT TO USE MAP SIMPLEFORMAT DSKGHTAB; MAP FORMAT DEST; MAP HALFFORMAT PTAB; LPTPTL _ .OBASE; ! START WITH THE FIRST PARTICLE ! OF THE DESTINATION GROUP POINTER TABLE NEXT _ LEAFPERPTL; ! FORCE A READ THE FIRST TIME THRU THE LOOP DEST _ .SRCTAB + 1; ! FIRST DESTINATION INCR DESTNO FROM 0 TO .S0CNT DO ! FOR ALL DESTINATIONS DO BEGIN IF .NEXT GEQ LEAFPERPTL THEN ! DO WE NEED TO READ BEGIN MOVE( DREAD( .LPTPTL ), PTAB, PTLSIZE ); ! YES THEN DO SO AND STORE IN PTAB NEXT _ 0; ! RESET OUR INDEX INTO PTAB LPTPTL _ .LPTPTL + 1 ! SET NEXT PTL TO READ END ELSE NEXT _ .NEXT + 1; ! NO READ THEN INC THE INDEX DSKGHTABPTR _ .PTAB[ .NEXT ]; ! GET A DSK GH TABLE POINTER WHILE .DSKGHTABPTR NEQ 0 DO ! WHILE THERE ARE DSKGH'S BEGIN MOVE( DREAD( PTL _ .DSKGHTABPTR ), DSKGHTAB, PTLSIZE ); ! READ A GROUP EMPTYFLAG _ TRUE; !ASSUME EMPTY IF .DSKGHTAB[DG0NEXT] EQL 0 THEN TRMDSKTAB[.DESTNO] _ .PTL; DSKGHTABPTR _ .DSKGHTAB[ DG0NEXT ]; ! NEXT GROUP TO READ INCR I FROM 1 TO DG0MAX DO ! AND PROCESS THE GROUP IF ( DSKMHPTR _ .DSKGHTAB[ DG0MH( .I ) ] ) NEQ 0 THEN ! IF NON-ZERO BEGIN EMPTYFLAG _ FALSE; !NOT EMPTY DSKGHADDR _ .I; DSKGHADDR _ .PTL; IF ( GHPTR _ FIXGROUP( .DSKGHTAB[ DG0TSN( .I ) ], .DSKGHTAB[ DG0SENDER( .I ) ], .DSKMHPTR, .DSKGHADDR, DEFERRED ) ) NEQ 0 THEN ! RECONSTITUTE THE GROUP BEGIN LINK( DEST[S0DGHS], .GHPTR ); ! ATTACH IT TO THE DEST DEST[ S0DFGCNT ] _ .DEST[ S0DFGCNT ] + 1 END END; IF .EMPTYFLAG THEN DELDSKGH( 1^18 + .PTL, TERMINAL) END; DEST _ .DEST + .S0SIZE END END; COMMENT; ! ROUTINE FIXGROUP ! ======= ======== ! THIS ROUTINE CREATES GROUPS AND MESSAGES FROM THE DISK IMMAGE ROUTINE FIXGROUP( TSN, SENDERID, DSKMH, DSKGH, TYPEDEFERRED ) = BEGIN REGISTER GHPTR, MHPTR, DSKMHPTR; LOCAL M, LASTENDI, N, X, Y; LABEL LOOP; MAP FORMAT GHPTR; MAP FORMAT MHPTR; MAP FORMAT DSKMHPTR; MAP FORMAT N; MAP FORMAT X; MAP FORMAT Y; DSKMHPTR _ .DSKMH; ! PICK UP THE DSK MESSAGE HEADER PTL NUMBER GHPTR _ CREATEGH(0); ! MAKE A GROUP HEADER GHPTR[ G0TSN ] _ .TSN; ! AND FILL IT WITH GOODIES GHPTR[ G0SENDER ] _ .SENDERID; ! ... GHPTR[G0ONDSK ] _ TRUE; ! ... GHPTR[G0DSKGHADDR ] _ .DSKGH; ! STORE DSK GROUP ADDRESS IN THE GH WHILE .DSKMHPTR NEQ 0 DO ! FOR ALL MESSAGES OF THE GROUP BEGIN LOOP: IF .TYPEDEFERRED THEN BEGIN X _ .SRCTAB + 1; INCR M FROM 0 TO .S0CNT DO BEGIN IF ( N _ .X[S0FDGHPTR] ) NEQ 0 THEN DO IF ( Y _ .N[G0FMHPTR] ) NEQ 0 THEN DO IF .DSKMHPTR EQL .Y[M0DSKADDR] THEN BEGIN Y[M0DSCNT] _ .Y[M0DSCNT] + 1; GHPTR[G0MHS] _ .N[G0MHS]; LEAVE LOOP END WHILE ( Y _ .Y[M0FORE] ) NEQ 0 WHILE ( N _ .N[G0FORE] ) NEQ 0; X _ .X + .S0SIZE END; MHPTR _ CREATEMH( GHPTR[G0MHS] ); MHPTR[M0DSCNT] _ 1; MHPTR[M0DSKADDR] _ .DSKMHPTR END ELSE BEGIN MHPTR _ CREATEMH( GHPTR[ G0MHS ] ); ! AMKE A MESSAGE HEADER MHPTR[ M0DSKADDR ] _ .DSKMHPTR ! SAVE THE DSK PTL NUMBER IN THE MH END; DSKMHPTR _ DREAD( .DSKMHPTR ); ! READ THE DISK MESSAGE HEADER IF NOT .TYPEDEFERRED THEN BEGIN IF(MHPTR[M0DATE]_.DSKMHPTR[DM0DATE]) EQL 0 THEN DSKMHPTR[DM0ENDI]_0; MHPTR[M0TIME]_.DSKMHPTR[DM0TIME]; MHPTR[M0SOT]_.DSKMHPTR[DM0SOT] ! MOVE INTERESTING NUMBERS END; LASTENDI _ .DSKMHPTR[ DM0ENDI ]; ! SAVE THE LAST END INDICATOR DSKMHPTR _ .DSKMHPTR[ DM0NEXTMH ]; ! GET THE NEXT DISK MESSAGE HEADER END; ! NOT MORE MESSAGES IN THE GROUP IF NOT .TYPEDEFERRED AND .LASTENDI LSS EGI THEN ! INPUT PARTIALLY ENTERED BEGIN ! YES... TOO BAD ZAP IT GPURGE( .GHPTR[ G0DSKGHADDR ] ); ! CLEAN UP THE DISK DELGH( .GHPTR ); ! AND DELETE WHAT'S IN CORE RETURN 0 ! RETURN NO GH END; ! GOT A GOOD GROUP GHPTR[ G0ENDI ] _ TRUE; ! MARK THE GROUP COMPLETE GHPTR[ G0OUTMH ] _ .GHPTR[ G0FMHPTR ]; GHPTR[ G0CHKPNT ] _ TRUE; .GHPTR ! ABND RETURN A POINTER TO THE GROUP HEADER END; ! END OF MCSONC.BLI