*DECK DB$TRJL 
USETEXT CDCSCTX 
USETEXT JLPCMTX 
  
      PROC DB$TRJL; 
      BEGIN 
 #
* *   DB$TRJL -- COPY TRF TO JOURNAL LOG FILE    PAGE 1 
* *   BOB MCALLESTER                             DATE  01/19/81 
* 
* DC  PURPOSE 
* 
*     COPY LOG RECORDS FROM THE TRANSACTION RECOVERY FILE TO THE
*     JOURNAL LOG FILE. 
* 
* DC  ENTRY CONDITIONS
* 
* D   PARAMETERS
* 
*     NONE
* 
* D   ASSUMPTIONS 
* 
*     SALX                   SCHEMA ACCESS LIST INDEX 
*     SAL                    SCHEMA ACCESS LIST 
*       SAARTPTR             ART POINTER
*       SATRFPTR             POINTER TO CURRENTLY USED TRF FET
* 
*     ART                    AUTO RECOVERY TABLE
*       ARFETPTR             POINTER TO TRF SEGMENT FET 
* 
*     TQT                    TASK QUEUE TABLE 
*       TQARTX               ART INDEX
* 
*     FET                    FILE ENVIRONMENT TABLE FOR THE TRF.
*       FIRST,IN,OUT,LIMIT,RR  POINTERS 
* 
* DC  EXIT CONDITIONS 
* 
*     LOG RECORDS HAVE BEEN COPIED FROM THE TRF TO THE JOURNAL LOG FILE.
* 
* DC  CALLING ROUTINES
* 
*     DB$CMT$                COMMIT SYMBIONT
* 
* DC  CALLED ROUTINES 
# 
      XREF FUNC CLOCK C(10); # OBTAIN THE CURRENT TIME FROM THE OS     #
      XREF FUNC DB$CBIN I;   # CONVERT DISPLAY TO BINARY               #
      XREF PROC DB$FLOP;     # FLOW POINT PROCESSOR                    #
      XREF PROC DB$IOER;     # I-O ERROR ON A LOG FILE                 #
      XREF PROC DB$JLCT;     # JOURNAL LOG FILE OUTPUT CONTROLLER      #
      XREF PROC DB$JLRS;     # RESERVE SPACE ON THE JOURNAL LOG FILE   #
      XREF PROC DB$MBA;      # ALLOCATE AN AUTOMATIC MEMORY BLOCK      #
      XREF PROC DB$MBF;      # FREE AN AUTOMATIC MEMORY BLOCK          #
      XREF PROC DB$PUNT;     # CDCS INTERNAL ERROR PROCESSOR           #
      XREF PROC DB$RDM;      # ISSUE A READ FUNCTION WITHOUT RECALL    #
      XREF PROC DB$SCHD;     # RETURN TEMPORARILY TO CDCS TASK SCHEDLR #
      XREF FUNC JDATE C(10); # OBTAIN THE CURRENT DATE FROM THE OS     #
# 
* DC  NON-LOCAL VARIABLES MODIFIED
* 
*     P<ART>                 AUTO RECOVERY TABLE POINTER
*     P<JLREC>               JOURNAL LOG RECORD POINTER 
*     SATRFPTR               SAL POINTER TO CURRENT TRF FET 
*     JLHDDATE               DATE IN JOURNAL LOG RECORD HEADER
*     JLHDTIME               TIME IN JOURNAL LOG RECORD HEADER
* 
* DC  DESCRIPTION 
* 
* D   INITIALIZATION
* 
*     THE TOTAL WORD SIZE OF THE SET OF TRANSACTION LOG RECORDS IS
*     CALCULATED AND THE SPACE IS RESERVED ON THE JOURNAL LOG FILE. 
* 
*     IF THE COMPLETE SET IS STILL IN THE TRF SEGMENT I-O BUFFER, THEN
*     NO READ IS REQUIRED.  IF THE BUFFER HAS OVERFLOWED, THE FET 
*     POINTERS ARE RESET TO DEFINE AN EMPTY BUFFER AND AN INITIAL READ
*     OF THE TRF SEGMENT IS SIGNALLED.
* 
*     THE CURRENT TIME AND DATE ARE OBTAINED AND SAVED SO THAT EACH 
*     UPDATE LOG RECORD OF THE TRANSACTION WILL HAVE THE SAME TIME
*     AND DATE
* 
* D   LOG RECORD PROCESSING 
* 
*     JOURNAL LOG OUTPUT, TRANSACT FILE INPUT AND LOG RECORD PROCESSING 
*     TOGETHER CONSTITUTE A SINGLE CONTROL LOOP.
*     THE OUTPUT AND INPUT ARE CONTROLLED BY THE FLAGS, WRITEFLG AND
*     READFLG RESPECTIVELY. 
* 
*     INPUT RECORDS ARE DEBLOCKED IN THE I-O BUFFER ASSIGNED TO THE 
*     TRANSACTION SEGMENT.  THERE IS NO WORKING STORAGE AREA. 
*     EACH DEBLOCKED LOG RECORD IS EXAMINED.  IF IT IS A 'TRF ONLY' 
*     LOG RECORD (TYPE = DFJLRQTR) IT IS NOT PROCESSED. 
* 
*     THE DATE AND TIME ARE REPLACED IN EACH LOG RECORD.
* 
*     WHEN CONTIGUOUS LOG RECORDS ARE TO BE SENT TO THE JOURNAL LOG 
*     FILE, THEY ARE SENT WITH A SINGLE DB$JLCT CALL. 
*     LOG RECORDS ARE CONSIDERED CONTIGUOUS EVEN WHEN THEY WRAP AROUND
*     THE END OF THE BUFFER.
* 
*     THE DB$JLCT CALLS ARE GENERATED FOR THE FOLLOWING REASONS:  
* 
*     ..  WHEN THE NEXT RECORD IS A 'TRF ONLY' RECORD, THE PRECEDING
*     RECORDS ARE OUTPUT AND THE 'TRF ONLY' RECORD IS SKIPPED.
* 
*     ..  WHEN THE NEXT RECORD IS NOT ENTIRELY CONTAINED IN THE I-O 
*     BUFFER, THE PRECEDING RECORDS ARE OUTPUT AND MORE DATA IS READ
*     FROM THE TRF FOR DEBLOCKING.
* 
*     ..  WHEN ALL OF THE RECORDS HAVE BEEN DEBLOCKED, THEY ARE OUTPUT
*     AND DB$TRJL RETURNS TO THE CALLING PROCEDURE. 
 #
# 
*     LOCAL VARIABLES 
# 
      ITEM BASESA I;         # BASE SECTOR ADDRESS OF THE TRF SEGMENT  #
      ITEM P1     I;         # PARAMETER POINTER                       #
      ITEM RECLEN I;         # LENGTH OF THE LOG RECORD IN WORDS       #
      ITEM TEMP I;           # TEMPORARY STORAGE WORD                  #
      ITEM TEMPC C(10);      # TEMPORARY CHARACTER STORAGE             #
      ITEM WRITEFLG B;       # THE LOG RECORDS ARE TO BE OUTPUT        #
      ITEM WTR B;            # DB$JLCT PARAMETER - WRITE RECORD        #
      ITEM XX I;             # INDUCTION VARIABLE                      #
# 
*     THE FOLLOWING LOCAL VARIABLES MUST BE PRESERVED OVER THE
*     INTERRUPTIBLE PORTIONS OF THE PROGRAM.
*     THEY ARE ALLOCATED IN A MANAGED MEMORY BLOCK BASED ARRAY. 
*     DB$SCHD AUTOMATICALLY RESTORED THE BASED ARRAY POINTER. 
# 
      DEF DFRUISIZE #07#;    # SIZE OF THE RUN-UNIT ITEMS ARRAY        #
  
      BASED ARRAY RUITEMS;   # RUN-UNIT ITEMS                          #
        BEGIN 
        ITEM NEXTREC I(00,00,60);  # LOCATION OF THE FOLLOWING LOG REC #
        ITEM READFLG B(01,00,60);  # MORE DATA IS TO BE READ FROM TRF  #
        ITEM SAVEIN  I(02,00,60);  # SAVE THE FET IN POINTER VALUE     #
        ITEM SAVERR  I(03,00,60);  # SAVE THE FET RR FIELD             #
        ITEM TRANSWL I(04,00,60);  # TOTAL WORD LENGTH OF TRANS RECORDS#
        ITEM TRDATE  C(05,00,10);  # DATE ASSIGNED TO THE TRANSACTION  #
        ITEM TRTIME  C(06,00,10);  # TIME ASSIGNED TO THE TRANSACTION  #
        END 
  
*CALL ARTDCLS 
  
  
      BASED ARRAY FET;
*CALL FETDCLS 
  
  
# 
*     B E G I N   D B $ T R J L   E X E C U T A B L E   C O D E 
# 
  
                             # INITIALIZATION                          #
      CONTROL IFGR DFFLOP,0;
        DB$FLOP("TRJL");
      CONTROL ENDIF;
                             # DB$PUSH(DB$TRJL) IS NOT REQUIRED        #
                             # BECAUSE THERE IS ONLY ONE CALLER.       #
      P<ART> = SAARTPTR[SALX];
      P<FET> = ARFETPTR[TQARTX[0]]; 
      DB$MBA(DFRUISIZE,P<RUITEMS>); 
      BASESA = BSAFORMULA;
      TRANSWL[0] = FETCWA[0] - BASESA * 64;  # TOTAL TRANSACTION SIZE  #
# 
*     THE FOLLOWING STATEMENT IS REQUIRED ONLY WHEN TRANSWL IS
*     EXACTLY EQUAL TO THE BUFFER SIZE. 
*     IN THAT CASE IT SETS FETIN EQUAL TO FETLIMIT INSTEAD OF FETFIRST. 
# 
      FETIN[0] = FETFIRST[0] + TRANSWL[0];
      IF TRANSWL[0] EQ 0
      THEN
        BEGIN 
        DB$MBF(P<RUITEMS>); 
        P<ART> = DFNPTR;
        P<FET> = DFNPTR;
        RETURN;              # IF NO UPDATES WERE LOGGED               #
  
        END 
# 
*     IF THE TOTAL TRANSACTION SIZE IS LARGER THAN THE I-O BUFFER,
*     THE BUFFER OVERFLOWED DURING THE BEGIN/COMMIT SEQUENCE. 
*     IN THAT CASE READFLG IS SET TRUE TO SIGNAL THAT AN INITIAL
*     READ IS REQUIRED. 
# 
      READFLG[0] = (FETLIMIT[0] - FETFIRST[0]) LS TRANSWL[0]; 
      IF READFLG[0] 
      THEN
        BEGIN 
        FETIN[0] = FETFIRST[0];  # INDICATE AN EMPTY BUFFER            #
        FETRR[0] = BASESA;   # SET RANDOM ADDRESS TO BEGINNING OF SEG  #
        END 
  
      DB$JLRS(TRANSWL[0]);   # RESERVE SPACE ON THE JOURNAL LOG FILE   #
# 
*     DB$JLRS IS INTERRUPTIBLE.  RESTORE BASED ARRAY POINTERS.
# 
      P<ART> = SAARTPTR[SALX];
      P<FET> = ARFETPTR[TQARTX[0]]; 
# 
*     OBTAIN CURRENT TIME AND DATE FROM THE OPERATING SYSTEM. 
*     USE IT AS THE UNIFORM TRANSACTION TIME. 
# 
      TRDATE[0] = JDATE(TEMPC); 
      TRTIME[0] = CLOCK(TEMPC); 
  
      WRITEFLG = FALSE;      # NOTHING TO OUTPUT ON FIRST LOOP         #
      FETOUT[0]  = FETFIRST[0];  # INITIAL RECORD POSITIONS            #
      P<JLREC>   = FETFIRST[0]; 
      NEXTREC[0] = FETFIRST[0]; 
  
# 
*         F O R   X X   =   X X 
* 
*     THIS "FOR LOOP" INCLUDES THE REMAINDER OF THE PROCEDURE.
# 
  
      FOR XX = XX 
      DO
        BEGIN 
  
  
# 
*         J O U R N A L   L O G   O U T P U T . 
# 
  
        IF WRITEFLG 
          OR TRANSWL[0] EQ 0
        THEN                 # WRITE OUTPUT TO THE JOURNAL LOG FILE    #
          BEGIN 
# 
*         WTR IS SET TRUE FOR THE TRANSMITTAL OF THE FINAL RECORDS TO 
*         THE JOURNAL LOG FILE. 
*         WHEN WTR IS TRUE, ALL REMAINING RESERVATIONS ARE RELEASED 
*         AND THE JOURNAL LOG RECORDS ARE FORCED ONTO THE DISK. 
# 
          WTR = TRANSWL[0] EQ 0;
# 
*         IF THE GROUP OF LOG RECORDS DOES NOT WRAP AROUND THE END
*         OF THE BUFFER, THEY ARE SENT AS A SINGLE TRANSFER.
*         IF THEY DO WRAP AROUND, THEY ARE SENT AS TWO TRANSFERS
*         WITHIN A SINGLE DB$JLCT CALL. 
# 
          IF P<JLREC> GQ FETOUT[0]
          THEN
            BEGIN 
            DB$JLCT(FETOUT[0], P<JLREC> - FETOUT[0], 0,0,WTR);
            END 
          ELSE
            BEGIN 
            DB$JLCT(FETOUT[0], FETLIMIT[0] - FETOUT[0], 
                    FETFIRST[0], P<JLREC> - FETFIRST[0], WTR);
            END 
# 
*         DB$JLCT IS INTERRUPTIBLE, RESTORE BASED ARRAY POINTERS. 
# 
          P<ART> = SAARTPTR[SALX];
          P<FET> = ARFETPTR[TQARTX[0]]; 
          P<JLREC> = NEXTREC[0];
          FETOUT[0] = NEXTREC[0]; 
  
          IF TRANSWL[0] EQ 0
          THEN               # THE TRANSACTION COPY IS COMPLETED       #
            BEGIN 
            DB$MBF(P<RUITEMS>);  # RELEASE LOCAL ITEM FROM MANAGED MEM #
            P<ART> = DFNPTR;
            P<FET> = DFNPTR;
            RETURN; 
  
            END 
          END 
  
  
# 
*         T R A N S A C T I O N   F I L E   I N P U T . 
# 
  
  
        IF READFLG[0] 
        THEN                 # READ MORE DATA FROM THE TRF             #
          BEGIN 
# 
*         THERE IS ONE FET FOR EACH SEGMENT OF THE TRF. 
*         ONLY ONE AT A TIME CAN BE USED FOR CIO CALLS. 
*         CHECK IF THE LAST ONE THAT WAS USED IS COMPLETE.
# 
          P<FET> = SATRFPTR[SALX];  # LAST TRF FET USED FOR A CIO CALL #
          IF NOT FETCOMP[0] 
          THEN               # WAIT FOR A CHANCE TO ISSUE THE I-O      #
            BEGIN 
            P<ART> = DFNPTR;
            P<FET> = DFNPTR;
                             # A NEGATIVE LOCATION IS AN INDIRECT      #
                             # CONSTRAINING ADDRESS.                   #
            DB$SCHD(-LOC(SATRFPTR[SALX]), DFWAITLOG); 
  
            CONTROL IFGR DFFLOP,0;
              DB$FLOP("TRJL-S1"); 
            CONTROL ENDIF;
  
            P<ART> = SAARTPTR[SALX];
            P<FET> = SATRFPTR[SALX];
            END 
          IF FETNOSAT[0] NQ 0 
          THEN               # I-O ERROR FROM A PRIOR FILE ACCESS      #
            BEGIN 
            DB$IOER(P<FET>);
            END 
# 
*         SET THE FET POINTER BACK TO THE FET FOR THE CURRENT SEGMENT 
*         AND RECORD IT AS THE FET CURRENTLY IN USE.
# 
          P<FET> = ARFETPTR[TQARTX[0]]; 
          SATRFPTR[SALX] = P<FET>;
  
          SAVEIN[0] = FETIN[0]; 
          SAVERR[0] = FETRR[0]; 
          DB$RDM(P<FET>);    # ISSUE A READ FUNCTION WITHOUT RECALL    #
          P1 = LOC(FET);
          P<ART> = DFNPTR;
          P<FET> = DFNPTR;
          DB$SCHD(P1,DFWAITIO);  # WAIT FOR THE I-O TO COMPLETE    #
  
          CONTROL IFGR DFFLOP,0;
            DB$FLOP("TRJL-S2"); 
          CONTROL ENDIF;
  
          P<ART> = SAARTPTR[SALX];
          P<FET> = ARFETPTR[TQARTX[0]]; 
# 
*         COMPUTE THE RANDOM REQUEST ADDRESS FOR THE NEXT READ
# 
          TEMP = FETIN[0] - SAVEIN[0];  # SIZE OF THE READ IF NO WRAP  #
          IF TEMP LS 0
          THEN               # THE READ WRAPPED AROUND THE END         #
            BEGIN 
            TEMP = TEMP + FETLIMIT[0] - FETFIRST[0];
            END 
          FETRR[0] = SAVERR[0] + (TEMP+63)/64;
  
          P<JLREC> = NEXTREC[0];
          READFLG[0] = FALSE; 
          IF FETNOSAT[0] NQ 0 
          THEN               # I-O ERROR OCCURRED ON THE READ          #
            BEGIN 
            DB$IOER(P<FET>);
            END 
          END 
  
  
# 
*         L O G   R E C O R D   P R O C E S S I N G . 
# 
  
  
        WRITEFLG = FALSE; 
  
        IF P<JLREC> EQ FETLIMIT[0]
        THEN                 # THE NEXT RECORD IS AT FIRST BUFFER WORD #
          BEGIN 
          P<JLREC> = FETFIRST[0]; 
          NEXTREC[0] = FETFIRST[0]; 
          END 
  
# 
*     IF THE TRANSACTION RECORDS ARE THE EXACT SIZE OF THE BUFFER 
*     FETIN HAS BEEN SET TO FETLIMIT TO AVOID A READ HERE.
# 
        IF P<JLREC> EQ FETIN[0] 
        THEN                 # THE NEXT RECORD IS NOT IN THE BUFFER    #
          BEGIN 
          WRITEFLG = TRUE;
          READFLG[0] = TRUE;
          TEST XX;
          END 
# 
*       COMPUTE THE LENGTH OF THE NEW RECORD
# 
        TEMP = DB$CBIN(JLHDTRLS[0],6,10); 
  
        IF JLHDFILA[0] NQ "*" 
          OR JLHDFILAA[0] NQ "*"
          OR TEMP LS 0
        THEN                 # IT IS NOT A LOG RECORD HEADER FIRST WORD#
          BEGIN 
          DB$PUNT("DB$TRJL 1"); 
          END 
  
        RECLEN = (TEMP + DFHDRSZ +9) /10; 
  
        NEXTREC[0] = P<JLREC> + RECLEN; 
        TRANSWL[0] = TRANSWL[0] - RECLEN; 
        IF TRANSWL[0] LS 0
        THEN
          BEGIN 
          DB$PUNT("DB$TRJL"); 
          END 
# 
*       IF THE RECORD IMAGE IS ENTIRELY IN THE BUFFER 
*       WITHOUT BEING WRAPPED AROUND THE END, PROCESS IT. 
# 
        IF NEXTREC[0] LQ FETIN[0] 
          OR (FETIN [0] LS P<JLREC> 
          AND NEXTREC[0] LQ FETLIMIT[0])
        THEN
          BEGIN 
          IF JLHDTYPE[0] EQ DFJLRQTR
          THEN               # IT IS A 'TRF ONLY' RECORD               #
            BEGIN 
            WRITEFLG = TRUE;  # WRITE THE PRECEDING RECORDS            #
            TEST XX;         # SKIP THE 'TRF ONLY' RECORD              #
  
            END 
          JLHDDATE[0] = C<5,5>TRDATE[0];
          JLHDTIME[0] = TRTIME[0];
# 
*         INCLUDE THE RECORD IN THE GROUP TO BE OUTPUT ON THE 
*         NEXT DB$JLCT CALL.
# 
          P<JLREC> = NEXTREC[0];
          TEST XX;
          END 
# 
*       IF THE RECORD IMAGE IS ENTIRELY IN THE BUFFER 
*       BUT WRAPS AROUND THE END OF THE BUFFER, 
*       SOME SPECIAL PROCESSING IS REQUIRED.
# 
        IF NEXTREC[0] GR FETLIMIT 
        THEN                 # IT WRAPS AROUND                         #
          BEGIN 
          NEXTREC[0] = NEXTREC[0] + FETFIRST[0] - FETLIMIT[0];
  
          IF NEXTREC[0] LQ FETIN[0] 
            AND P<JLREC> GR FETIN[0]
            AND FETIN[0] LS FETOUT[0] 
          THEN               # IT IS IN THE BUFFER                     #
            BEGIN 
            IF JLHDTYPE[0] EQ DFJLRQTR
            THEN             # IT IS A 'TRF ONLY' RECORD               #
              BEGIN 
              WRITEFLG = TRUE;  # WRITE THE PRECEDING RECORDS          #
              TEST XX;       # SKIP THIS ONE                           #
  
              END 
            IF LOC(JLHDDATE[0]) GQ FETLIMIT[0]
            THEN             # THE DATE IS IN THE LOWER BUFFER PORTION #
              BEGIN 
              P<JLREC> = NEXTREC - RECLEN;
              END 
            JLHDDATE[0] = C<5,5>TRDATE[0];
            IF LOC(JLHDTIME[0]) GQ FETLIMIT[0]
            THEN             # THE TIME IS IN THE LOWER BUFFER PORTION #
              BEGIN 
              P<JLREC> = NEXTREC - RECLEN;
              END 
            JLHDTIME[0] = TRTIME[0];
  
            P<JLREC> = NEXTREC[0];
            TEST XX;
  
            END 
          END 
# 
*       THE RECORD IMAGE IS NOT ENTIRELY IN THE BUFFER. 
*       WRITE THE RECORDS THAT HAVE BEEN PROCESSED AND
*       THEN READ MORE DATA INTO THE BUFFER.
# 
        TRANSWL[0] = TRANSWL[0] + RECLEN;  # RESTORE RECORD LENGTH     #
        NEXTREC[0] = P<JLREC>;
  
        WRITEFLG = TRUE;
        READFLG[0] = TRUE;
        END  # XX # 
      P<ART> = DFNPTR;
      P<FET> = DFNPTR;
      END    # PROC # 
  
      TERM
