Thursday, May 11, 2017

Rexx to Aggregate statistics by 1 hour, check and report bad counters - The must have for all sites

Update 18/01/2017 :  More field for Workfile BufferPool usage and alerts
Merge pass degraded ..., check Sequential Prefetch Quantity

Update 12/10/2017 :  Track Workfile usage and others enhancements
Counters are checked and reports are sent to a dataset (which is then sent to our DB2 team e-mail account). 


update : 11/5/2017

This Rexx allows to aggregate the detailed stats in value corresponding to 1 hour interval : this allows me to have a quick view / analysis , and it is enough light to be loaded to a DB2 database on Windows, SQLlite ...for a quick report (Note : after testing several free database on Windows, i am satisfied with DB2 because it allows a one click export to Excel from any SQL query )
I submit this Rexx daily on every Production LPAR and get the files sent to my PC where i load it to the DB2 table ...
I do this for the accounting and the statistics.





/*REXX*/
/****************************************************************/
/*   DB2 STATS AGGREGATED BY HOUR                               */
/****************************************************************/
numeric digits 15
arg OPT OPT2
if OPT = '' then lpar = MVSVAR(SYSNAME)
else   lpar = OPT
clnt=''
temX=0 /* just open new one time */
temR=0 /* Report in LOGW  */
Call SetSmfDs
hlq='SYSTMP.DBDC.DB2'
vsm='Y'    /*virtual storage monitoring Yes/No*/

/* Start processing unit for one SSID */

Start_Pgm:

nbGBP=0
nbBP=0
Hour='00'
Max_QISTW4K=0
Max_QISTW32K=0
bp0_vpsize=0
ifcid1_seen=0
Max_SUD2_gp=0
SumBP_SUD2=0
SumBP_SUD2_all=0
SUD2_BpInact=0
tsaylocal=0
ope =0
rupture=0
rec.0  =1
recw   =0
RFlush =0

/* init compteurs divers */
call init_var

/* START PROCESSING */
DO FOREVER
  /* read SMF record one by one   */
  "EXECIO 1 DISKR INP"
  IF RC > 0 THEN DO
            if rc =  2 then
             do
              SAY 'End of input SMF file rc=' RC
              rcalloc = rc
             end
             else do
              SAY 'Error while reading SMF file rc=' RC
              rcalloc = 8
             end
              leave
            END
  PARSE PULL INPUT_REC
  reci=reci+1
  OFFSET = 1
  /* Decode SMF header */
  CALL DSNDQWST
  /* process only smf100 */
  IF (SM100RTY = 100    ) THEN
  DO
    if ope = 0 then call CrOutput /* do the first time only */
    if  sm100ssi <> ssid then iterate
    /* record SMF records period   */
    if min_time > run_fmt_time then min_time=run_fmt_time
    if Max_time < run_fmt_time then Max_time=run_fmt_time
    if min_date > sm100dte     then min_date=sm100dte
    if Max_date < sm100dte     then Max_date=sm100dte

    /*sauvegarde offset_self car on le reutilise */
    offset_selfdef= offset
    /* on va sur le self def. section pour aller vers prod section*/
    offset = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset - 4 + 1
    /* traitement product section*/
    CALL DSNDQWHS
    offset=offset_selfdef
    /* ifcid 1 must start the stats group */
    if   ifcid =  1 then ifcid1_seen = 1
    else if   ifcid <> 1 & ifcid1_seen = 0 then
                               do
                                      iterate
                                      say 'bypass' ifcid
                               end
    recs=recs+1
    Select
         When ifcid     = 1  Then do
                                      CALL DSNDQWS0
                                      OFFSET = QWS00PSO - 4 + 1
                                  end
         When ifcid     = 2  Then do
                                      CALL DSNDQWS1
                                      OFFSET = QWS10PSO - 4 + 1
                                  end
         When ifcid     = 225 Then do
                                      CALL QW0225
                                      OFFSET = QWS10PSO - 4 + 1
                                  end
         Otherwise      do
                  /* add line here to avoid excessive displays */
                          if  ifcid = 202 then nop
                          else
                              if  ifcid = 230 then nop
                          else
                              say 'ifcid ' ifcid ' not processed'
                        end
    end   /* select */

    /*write report quand on a fait le tour des ifcids */
    if ifcid = 1 & recs > 1 then
       do
          call ifcid_diff
          /* on bypass le 1er record qui comprend les totaux*/
          if reco > 0 then Call write_report
          else reco = 1
       end
    else
    do
         if ifcid = 1 & recs = 1 then
         do
              Old_Mstrtcb =       Mstrtcb
              Old_MstrSrb =       MstrSrb
              Old_MstrpSRB=       MstrpSRB
              Old_MstrpSRB_Ziip = MstrpSRB_Ziip
              Old_dbm1Tcb =       dbm1Tcb
              Old_dbm1srb =       dbm1srb
              Old_dbm1pSRB=       dbm1pSRB
              Old_dbm1pSRB_Ziip = dbm1pSRB_Ziip
              Old_irlmTcb =       irlmTcb
              Old_irlmsrb =       irlmsrb
              Old_irlmpSRB=       irlmpSRB
              Old_irlmpSRB_Ziip = irlmpSRB_Ziip
              Old_distTcb =       distTcb
              Old_distsrb =       distsrb
              Old_distpSRB=       distpSRB
              Old_distpSRB_Ziip = distpSRB_Ziip
         end
    end
  END /*    IF SM100RTY = 100  */
END
/* flush pending report (only at eof ) */
RFlush=1
call write_summary
"EXECIO" queued() "DISKW OUFL ( FINIS"
rcwrite = rc
if rcwrite<> 0 then Do
   say "**********************************************"
   say "   Error writting OUFL file: " rcwrite
   say "   Abnormal end   "
   say "**********************************************"
   Exit 8
end
"EXECIO 0 DISKR INP (STEM INL. FINIS"
/* Free REPORTS dataset */
"FREE DD(OUFL)"

rec.1= " "
call LOGW
call DisplayPref
rec.1= " "
call LOGW
rec.1= "Input records =" reci
call LOGW
rec.1=  "Output records=" reco
call LOGW
rec.1= 'SMF period : ' min_date "/" Max_date min_time "/" Max_time
call LOGW

/*-------------------------------------------------*/
/* F20 End of program display counters and figures */
/*-------------------------------------------------*/
call DisplayVStor
if lpar = 'SUD2' then
         call SUD2_report_bp_usage
"EXECIO 0 DISKW OUFw (FINIS"
/* Free REPORTSW dataset */
"FREE DD(OUFW)"
if lpar = 'IPO4' then
   do
         /* process DSNI now */
         if ssid = 'DSNI' then /* avoid forever loop */
         do
              say 'End processing for IPO4'
         end
         else
         do
              ssid = 'DSNI'
              signal start_pgm
         end
   end

if lpar = 'SUD2' then
   do
         if ssid = 'DBAP' then
         do
              ssid = 'DB2A'
              signal start_pgm
         end
         if ssid = 'DB2A' then
         do
              ssid = 'DB2C'
              signal start_pgm
         end
         if ssid = 'DB2C' then
         do
              ssid = 'DB2D'
              signal start_pgm
         end
         if ssid = 'DB2D' then
         do
              ssid = 'DB2G'
              signal start_pgm
         end
         if ssid = 'DB2G' then
         do
              ssid = 'DB2I'
              signal start_pgm
         end
         if ssid = 'DB2I' then
         do
              ssid = 'DB2P'
              signal start_pgm
         end
         if ssid = 'DB2P' then
         do
              ssid = 'DB2R'
              signal start_pgm
         end
         if ssid = 'DB2R' then
         do
              ssid = 'DFEI'
              signal start_pgm
         end
         if ssid = 'DFEI' then
         do
              ssid = 'DFLI'
              signal start_pgm
         end
         if ssid = 'DFLI' then
         do
              ssid = 'DPEI'
              signal start_pgm
         end
         if ssid = 'DPEI' then
         do
              ssid = 'DPLI'
              signal start_pgm
         end
         if ssid = 'DPLI' then
         do
              ssid = 'DQE3'
              signal start_pgm
         end
         if ssid = 'DQE3' then
         do
              ssid = 'DRC2'
              signal start_pgm
         end
         if ssid = 'DRC2' then
         do
              say 'All DB2 of SUD2 processed - Ending'
         end
   end

if lpar = 'ZPR1' then
   do
         /* process DSNH now */
         if ssid = 'DB2E' then /* avoid forever loop */
         do
              ssid = 'DB2H'
              signal start_pgm
         end
         else
         do
              if ssid = 'DB2H' then
              do
                   ssid = 'DB2I'
                   signal start_pgm
              end
              else
              do
                   /* je suis la parce que ssid = 'DB2I'*/
                   say 'Tous les DB2 de ZPR1 sont traités'
              end
         end
   end
"FREE DD(INP)"
if lpar = 'SUD2' then
do
  "EXECIO 0 DISKW OUFs2 (FINIS"
  "FREE DD(OUFs2)"
end
EXIT rcalloc

/*---------------------------------------*/
/* End of program body- Routines section */
/*---------------------------------------*/

/* MAP SELF-DEFINING SECT IFCID 001 LG = 112 */
DSNDQWS0:
  /*  OFFSET TO THE PRODUCT SECTION */
  QWS00PSO = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 4
  QWS00PSL = C2D(SUBSTR(INPUT_REC,OFFSET,2))
  OFFSET = OFFSET + 2
  QWS00PSN = C2D(SUBSTR(INPUT_REC,OFFSET,2))
  OFFSET = OFFSET + 2
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQWSA CPU TIME */
  QWS00R1O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 4
  QWS00R1L =  C2D(SUBSTR(INPUT_REC,OFFSET,2))
  OFFSET = OFFSET + 2
  QWS00R1N =  C2D(SUBSTR(INPUT_REC,OFFSET,2))
  OFFSET = OFFSET + 2
  save_offset = offset
  /* controle de coherence */
  if  QWS00R1N  > 4 then
      do
           say 'QWS00R1N is not equal to 4, abnormal end ' QWS00R1N
           exit 8
      end
  /* Load offset to DSNDQWSA section - decode db2 stc cpu section */
  OFFSET= QWS00R1O - 4 + 1
  /* init DIST pas toujours pr§sent */
  DISTTcb      = 0
  DISTSrb      = 0
  DISTpSRB     = 0
  DISTpSRB_Ziip= 0
  i=0
  do until i= QWS00R1N
         i = i+ 1
         call DSNDQWSA
  end

  /*restore offset */
  offset = save_offset

  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQWSB STATS COUNTERS*/
  /*  INSTRUMENTATION STATISTICS DATA ABOUT OUTPUT DESTINATION */
  QWS00R2O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQWSC */
  /*  IFCIDS RECORDED TO STATISTICS */
  QWS00R3O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQ3ST */
  /*  Subsytem services fields */
  /*  SIGNON, IDEN, COMMITS, ABORTS ...*/
  QWS00R4O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  save_offset = offset
  offset = QWS00R4O - 4 + 1
  call DSNDQ3ST
  offset = save_offset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQ9ST */
  QWS00R5O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQWSD */
  /*  CHECKPOINT INFO, IFI COUNT    ...*/
  QWS00R6O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  save_offset = offset
  offset = QWS00R6O - 4 + 1
  call DSNDQWSD
  offset = save_offset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQVLS */
  /*  LATCH COUNTS                  ...*/
  QWS00R7O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQVAS */
  /*  ASMC STATS NBRE DE SUSPENSIONS ..*/
  QWS00R8O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQSST */
  /*  STORAGE MANAGER */
  QWS00R9O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  save_offset = offset
  offset = QWS00R9O - 4 + 1
  call DSNDQSST
  offset = save_offset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQLST */
  /*  DDF STATS BY LOCATION */
  QWS00RAO = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQJST */
  /*  LOG MANAGER           */
  QWS00RAO = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  save_offset = offset
  offset = QWS00RAO - 4 + 1
  call DSNDQJST
  offset = save_offset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQDST */
  /*  DBAT STATS            */
  QWS00RCO = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  save_offset = offset
  offset = QWS00RCO - 4 + 1
  call DSNDQDST
  offset = save_offset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQWOS */
  /*  ZOS STATS             */
  QWS00RCO = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /* LG = 112 = 14 SECTIONS * 8 */

  Return


QW0225:
numeric digits 15
       offset_save=offset /* sauvergarde offset debut data section*/
       /* offset= offset of self definition section*/
       /* offset= offset + 8 : bypass pointer to Product  Section*/
       /* offset_d = offset de la data section */
       offset=offset+4+2+2 /*pointer to data section 1*/
       /*take the contents pointed by the offset */
       offset_d= C2D(SUBSTR(INPUT_REC,OFFSET,4))

       /* -------------- */
       /* data section 1 */
       /* -------------- */
       /* Data section 1 = 2 parts, DBM1 and DIST */

       /* offset to dbm1 */
       offset_d=offset_d -4+1
       offset=offset+4

    /* say 'offs sect1'  offset_d */
       /* len of data section 1 : it will be repeated :*/
       /* One for DBM1 and one for DIST */
       len=      C2D(SUBSTR(INPUT_REC,OFFSET,2))
       offset=offset+2
       rep=      C2D(SUBSTR(INPUT_REC,OFFSET,2))
       offset=offset+2
    /* say 'len' len
       say 'rep' rep */

       /* offset to DIST */
       offset_d2=offset_d+len

    /* say 'offs sect2'  offset_d2 */

       QW0225AN =(SUBSTR(INPUT_REC,OFFSET_d,4))
       if  QW0225AN <> 'DBM1' then
       do
           say 'W0225 - Mapping error'
           exit 8
       end
    /***********************************/
    /* Processing DBM1 storage section */
    /***********************************/
       if  QW0225AN =  'DBM1' & vsm ='Y'  then
       do
           offset_d=offset_d+4
           /* extended region size */
           QW0225RG = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4+4+4
           QW0225EL = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           QW0225EH = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4 +4+4
           /* storage reserved fo must complete */
           /* before V10 depends on CTHREAD and MaxDBAT zparm*/
           QW0225CR = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           /* storage reserved for open/close datasets */
           /* depends on DSMax value */
           QW0225MV = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           QW0225SO = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           QW0225GS = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4+4
           QW0225VR = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           QW0225FX = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           QW0225GM = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4
           /* 31 bit storage available */
           QW0225AV = C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
           offset_d=offset_d+4+4+8+8+8+8
           QW0225RL_dbm1 = C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           /* 225RL = Real stor. frame used by the Address Space*/
           /*    this includes bufferpools storage qw0225bb */
           offset_d=offset_d+8
           QW0225AX_dbm1 = C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+8
           /* QW0225HVPagesInReal 64 bits private Real */
           QW0225HVPagesInReal =  C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+8
           /* QW0225HVAuxSlots    64 bits private Aux */
           QW0225HVAuxSlots =  C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+24
      /*   /* QW0225HWM           64 bits private Real*/
           QW0225HVGPagesInReal =  C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+8
           /* QW0225HWM           64 bits private Aux */
           QW0225HVGAuxSlots=  C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+8 */
           /* QW0225PagesInReal 64 bits private Real without BP */
           QW0225PriStg_Real=  C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+8
           /* QW0225PagesInAux  64 bits private Aux  without BP */
           QW0225PriStg_Aux=  C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
           offset_d=offset_d+8
           TotalRealUsedBP = QW0225HVPagesInReal - QW0225PriStg_Real
           TotalAuxUsedBP = QW0225HVAuxSlots    - QW0225PriStg_Aux
       end  /* if  QW0225AN =  'DBM1' & vsm = 'Y' then */

       /* rep = 2 : there is 2 parts , DBM1 and DDF */
       if rep = 2 then
       do
          /* partie DIST */
          QW0225AN =(SUBSTR(INPUT_REC,OFFSET_d2,4))
          if  QW0225AN <> 'DIST'  then
          do
              say 'W0225 - Mapping error DIST not found'
              say 'input_rec' input_rec
              say 'offset'   offset_d2
              exit 8
          end
          if  QW0225AN =  'DIST' & vsm='Y' then
          do
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4+4+4
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4 +4+4
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4+4
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4
              offset_d2=offset_d2+4+4+4+8+8+8+8
              QW0225RL_dist = C2D(SUBSTR(INPUT_REC,offset_d2,8))
              offset_d2=offset_d2+8
              QW0225AX_dist = C2D(SUBSTR(INPUT_REC,offset_d2,8))
          end  /* if  QW0225AN =  'DIST' & vsm = 'Y' then */
       end
       else /*if rep = 2 then*/
       do
              QW0225RL_dist = 0
              QW0225AX_dist = 0
       end

       /*pointer to data section 2*/

       offset_d= C2D(SUBSTR(INPUT_REC,OFFSET,4))
       offset_d=offset_d -4+1


       QW0225AT =C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
       offset_d=offset_d+4 /*pointer on data section 2*/
       QW0225DB =C2D(SUBSTR(INPUT_REC,OFFSET_d,4))

       if (QW0225AT + qw0225DB) < MinThdSee then
          do
              MinThdSee = QW0225AT + qw0225DB
              MinThdSeeTime= run_fmt_time
              MinThdSeeDate= sm100dte
          end
       if (QW0225AT + qw0225DB) > MaxThdSee then
          do
              MaxThdSee = QW0225AT + qw0225DB
              MaxThdSeeTime= run_fmt_time
              MaxThdSeeDate= sm100dte
          end
       /* say 'threads allied=' QW0225AT
          say 'threads dbat=' QW0225DB      */

       /*pointer to data section 3 : Shared and Common Storage */
       offset=offset+8 /* go to next pointer*/
       if vsm = 'Y' then
       do
          /* load address of section 3*/
          offset_d= C2D(SUBSTR(INPUT_REC,OFFSET,4))
          offset_d=offset_d -4+1

          offset_d=offset_d +136
          QW0225SHRINREAL  =C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
          offset_d=offset_d + 32
          QW0225ShrStg_Real=C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
          offset_d=offset_d + 8
          QW0225ShrStg_Aux =C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
          offset_d=offset_d + 8
          QW0225ShrStkStg_Real=C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
          offset_d=offset_d + 8
          QW0225ShrStkStg_Aux =C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
          offset_d=offset_d + 8
          QW0225ComStg_Real=C2D(SUBSTR(INPUT_REC,OFFSET_d,8))
          offset_d=offset_d + 8
          QW0225ComStg_Aux =C2D(SUBSTR(INPUT_REC,OFFSET_d,8))

         /* formula from    Redbook V11 Monitoring */
         /* table 13-1 13-2                        */
         /* Calculation to be updated when V11 + Log Mgr control */
         /* in Real, Log. write buffers  */
          TotalRealUsedByDB2 = qw0225rl_dbm1+ qw0225rl_dist +,
                 QW0225ShrStg_Real + QW0225ShrStkStg_Real +,
                 QW0225ComStg_Real

      /*  TotalRealUsedByLPAR meaning not clear - value does not  */
      /*     corresponds with others z/OS monitoring tool         */
      /*  TotalRealUsedByLPAR= qw0225rl_dbm1+ qw0225rl_dist +,    */
      /*       QW0225ComStg_Real + -- in redbook but no where else*/
      /*                           QW0225SHRINREAL                */
          /* QW0225ComStg_Real Real in use 64 bit shared */
          /* QW0225SHRINREAL   Real in use 64 bit common */

      /*  if MaxRealLPAR  <  TotalRealUsedByLPAR then */
      /*       do                                     */
      /*           MaxRealLPAR = TotalRealUsedByLPAR  */
      /*           time_MaxRealLPAR = run_fmt_time    */
      /*       end                                    */

          offset_d=offset_d + 32
      /*  QW0225_WARN      =C2D(SUBSTR(INPUT_REC,OFFSET_d,4)) */
          offset_d=offset_d + 8
          QW0225_REALAVAIL =C2D(SUBSTR(INPUT_REC,OFFSET_d,4))

          if MinQW0225_REALAVAIL > QW0225_REALAVAIL then
               do
                   MinQW0225_REALAVAIL = QW0225_REALAVAIL
                   time_MinQW0225_REALAVAIL = run_fmt_time
                   date_MinQW0225_REALAVAIL = sm100dte
               end
       end

       /*-------------------------*/
       /*pointer to data section 4*/
       /*-------------------------*/
       offset=offset+8

       /*-------------------------------------------------*/
       /*pointer to data section 5 : Pool storage details */
       /*-------------------------------------------------*/
       offset=offset+8
       if  vsm = 'Y' then
       do
         offset_d= C2D(SUBSTR(INPUT_REC,OFFSET,4))
         offset_d= offset_d+4
       /* QW0225AS Total system agent storage 31 bits*/
         QW0225AS =C2D(SUBSTR(INPUT_REC,OFFSET_d,4))
       /* QW0225BB Total buffer manager storage blocks */

       /*-------------------------------*/
       /* Calculate Max threads allowed */
       /*-------------------------------*/

         /*Ici on a eu tous les infos on peut donc calculer le */
         /* nombre de threads Max theoriques*/
         /* Source : IBM formula  */
         /* (Redbook V11 subsystem monitoring Chap. Virtual Stor*/
         /* Min and Max is used in a very defensive way */
         /* The excel proposed with MEMU deoesn't use min Max */
         /* I also caculate this value (thdcomp2) */

         /*    Thread footprint calculation : */

         /* Basic Storage Cushion */
         BC = QW0225CR + QW0225MV + QW0225SO
         /* Non DB2 storage, retains Max value for final calculation*/
         ND = QW0225EH-QW0225GM-QW0225GS-QW0225FX-QW0225VR
         if ND > MaxND then MaxND=ND
         /* Max Allowable storage */
         AS = QW0225RG-BC-MaxND
         AS2= QW0225RG-BC-ND
         if AS < MinAS then MinAS=AS
         /* Max Allowable storage for thread use*/
         TS = MinAS-(QW0225AS + QW0225FX + QW0225GM+ QW0225EL)
         TS2= AS2-(QW0225AS + QW0225FX + QW0225GM+ QW0225EL)
         if TS < MinTS then MinTS=TS
         /* Average thread footprint */
         if (QW0225AT + qdstcnat) = 0 then
            /* if threads in system = 0 then 1 */
            TF =  QW0225VR- QW0225AS + QW0225GS
         else
            TF = (QW0225VR-QW0225AS+QW0225GS)/(QW0225AT+qdstcnat)

         if TF > MaxTF then MaxTF=TF
         /* Max threads supported    */
         ThdComp=MinTS/MaxTF
         ThdComp2=TS2/TF
         StorBefContract=qw0225AV-(qw0225cr+qw0225SO+qw0225MV)
         /* Storage contraction ?*/
         if qw0225AV <  qw0225cr then
                do
                    say ' Storage critical condition',
                        '@ ' run_fmt_time
                end
         else do
              if qw0225AV <  (qw0225cr+ qw0225SO+qw0225MV) then
                do
                    say ' Full system contraction should happen',
                        '@ ' run_fmt_time
                end
         end /* else */

         if ThdComp < MinThdComp then do
                                     MinThdComp =ThdComp
                                     MinThdCompTime=run_fmt_time
                                     MinThdCompDate=sm100dte
                                   end
         if ThdComp2 < MinThdComp2 then do
                                     MinThdComp2 =ThdComp2
                                     MinThdComp2Time=run_fmt_time
                                     MinThdComp2Date=sm100dte
                                   end
         if ThdComp > MaxThdComp then do
                                     MaxThdComp =ThdComp
                                     MaxThdCompTime =run_fmt_time
                                     MaxThdCompDate =sm100dte
                                   end
         if ThdComp2 > MaxThdComp2 then do
                                     MaxThdComp2 =ThdComp2
                                     MaxThdComp2Time =run_fmt_time
                                     MaxThdComp2Date =sm100dte
                                   end

         Real4K_dbm1=(QW0225RL_dbm1 *4096)/ 1048576    /*1MB*/
         Real4K_dist=(QW0225RL_dist *4096)/ 1048576    /*1MB*/

         If MinReal4K_dbm1 > Real4K_dbm1 then
                          do
                             MinReal4K_dbm1=Real4K_dbm1
                             time_MinReal4K_dbm1=run_fmt_time
                             Date_MinReal4K_dbm1=sm100dte
                          end
         If MaxReal4K_dbm1 < Real4K_dbm1 then
                          do
                             MaxReal4K_dbm1=Real4K_dbm1
                             time_MaxReal4K_dbm1=run_fmt_time
                             Date_MaxReal4K_dbm1=sm100dte
                          end
         If MinReal4K_dist > Real4K_dist then
                          do
                             MinReal4K_dist=Real4K_dist
                             time_MinReal4K_dist=run_fmt_time
                             Date_MinReal4K_dist=sm100dte
                          end
         If MaxReal4K_dist < Real4K_dist then
                          do
                             MaxReal4K_dist=Real4K_dist
                             time_MaxReal4K_dist=run_fmt_time
                             Date_MaxReal4K_dist=sm100dte
                          end
         /* calculation to be updated when V11 + Log Mgr control */
         /* in aux - check IBM excel provided with memu */
         TotalAuxlUsedByDB2 = qw0225ax_dbm1+ qw0225ax_dist +,
               QW0225ComStg_Aux  + QW0225ShrStg_Aux  +  ,
                                   QW0225ShrStkStg_Aux
         If MaxDB2AuxUse < TotalAuxlUsedByDB2 then
                          do
                             MaxDB2AuxUse=TotalAuxlUsedByDB2
                             timeMaxDB2AuxUse=run_fmt_time
                             DateMaxDB2AuxUse=sm100dte
                          end
       end /* if vsm ... */
return
/* MAP SELF-DEFINING SECT IFCID 002 LG = 12X8 = 96 */
DSNDQWS1:
  /*  OFFSET TO THE PRODUCT SECTION */
  QWS10PSO = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQXST */
  /*  RDS stats block  */
  QWS10R1O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  if  QWS10R1O > 0 then
  do
    save_offset = offset
    offset = QWS10R1O - 4 + 1
    call DSNDQXST
    offset = save_offset
  end
  else
  do
    call DSNDQXST0
  end
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQTST */
  /*  nbre de bind, nbre de plan allocated succ ... */
  QWS10R2O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  save_offset = offset
  offset = QWS10R2O - 4 + 1
  call DSNDQTST
  offset = save_offset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQBST */
  /*  Buffer manager stats                          */
  QWS10R3O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 6
  QWS10r3N = C2D(SUBSTR(INPUT_REC,OFFSET,2))
  OFFSET = OFFSET + 2
  /* decode dsndqbst to have  buffer stats */
  Sum_QBSTGET = 0
  Sum_QBSTRIO = 0
  Sum_QBSTIMW = 0
  Sum_QBSTDSO = 0
  Sum_QBSTWIO = 0
  Sum_QBSTRPI = 0
  Sum_QBSTWPI = 0
  Sum_QBSTPIO = 0
  Sum_QBSTMAX = 0
  Sum_QBSTWFD = 0
  Sum_QBSTWFF = 0
  Sum_QBSTCIO = 0
  Sum_QBSTDIO = 0
  Sum_QBSTLIO = 0
  Sum_QBSTSIO = 0
  if  QWS10R3O > 0 then
  do
      saveoffset= offset
      offset=QWS10R3O - 4 + 1
      /*add code here if need figures by bufferpool ID */
      m=0
      do until m= QWS10r3N
         m = m+ 1
         call dsndqbst
         Sum_QBSTGET = Sum_QBSTGET + QBSTGET
         Sum_QBSTRIO = Sum_QBSTRIO + QBSTRIO
         Sum_QBSTIMW = Sum_QBSTIMW + QBSTIMW
         Sum_QBSTDSO = Sum_QBSTDSO + QBSTDSO
         Sum_QBSTWIO = Sum_QBSTWIO + QBSTWIO
         Sum_QBSTRPI = Sum_QBSTRPI + QBSTRPI
         Sum_QBSTWPI = Sum_QBSTWPI + QBSTWPI
         Sum_QBSTPIO = Sum_QBSTPIO + QBSTPIO
         Sum_QBSTMAX = Sum_QBSTMAX + QBSTMAX
         Sum_QBSTWFD = Sum_QBSTWFD + QBSTWFD
         Sum_QBSTWFF = Sum_QBSTWFF + QBSTWFF
         Sum_QBSTCIO = Sum_QBSTCIO + QBSTCIO
         Sum_QBSTDIO = Sum_QBSTDIO + QBSTDIO
         Sum_QBSTLIO = Sum_QBSTLIO + QBSTLIO
         Sum_QBSTSIO = Sum_QBSTSIO + QBSTSIO
      end
      offset=saveoffset
  end

  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQIST */
  /*  Data   manager stats                          */
  QWS10R4O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 8
  /* decode dsnDQIST to have to Data manager stats */
  saveoffset= offset
  offset=QWS10R4O - 4 + 1
  call dsndqist
  offset=saveoffset
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQTXA */
  /*  Lock   manager stats                          */
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQISE */
  OFFSET = OFFSET + 8
  /*  OFFSET TO THE DATA SECTION MAPPED BY DSNDQBGL */
  /*  GBP Stats                                     */
  QWS10R7O = C2D(SUBSTR(INPUT_REC,OFFSET,4))
  OFFSET = OFFSET + 6
  QWS10R7N = C2D(SUBSTR(INPUT_REC,OFFSET,2))
  OFFSET = OFFSET + 2
  if  QWS10R7O > 0 then
  do
       save_offset = offset
       offset = QWS10R7O - 4 + 1
       m=0
       do until m= QWS10r7N
           m = m+ 1
           call DSNDQBGL
       end /* do until */
       offset = save_offset
  end  /* QWS10R7O > 0  */
  /*  (...)                                         */
  /*  Others sections - Check Rex100                */
  return

dsndqist:
    numeric digits 15
    offset  =  offset +4
    /* Fields of these macro seems to be all cumulative */
    /* calculate difference between interval */
    /* check QIEYE */
      if  SUBSTR(INPUT_REC,OFFSET,4) <> 'QIST' then
        do
              say 'Mapping error QIST eye catcher not found'
              exit(8)
        end

    offset = offset + 4
    /* RID Term RDS Limit */
    QISTRLLM = C2D(SUBSTR(INPUT_REC,offset,4))
    offset = offset + 4
    /* RID Term DM  Limit */
    QISTRPDM = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 20
    /* not optimal column proc Invalid Sproc */
    QISTCOLS = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 40
    /* 32KB Wrkfile used instead of 4KB */
    QISTWFP1 = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* 4 KB Wrkfile used instead of 32 KB */
    QISTWFP2 = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 28
    /* hwm storage used by workfiles in KB */
    offset = offset + 8
    /* Current all workfile usage in KB : DGTT and Sort */
    offset = offset + 8
    /* Current 4K wrkfile storage usage in KB*/
    QISTW4K  = C2D(SUBSTR(INPUT_REC,OFFSET,8))
    if QISTW4K > Max_QISTW4K then
          Max_QISTW4K = QISTW4K
    offset = offset + 8
    /* Current 32K wrkfile storage usage in KB*/
    QISTW32K = C2D(SUBSTR(INPUT_REC,OFFSET,8))
    if QISTW32K > Max_QISTW32K then
          Max_QISTW32K = QISTW32K
    offset = offset + 8
    /* Nb DM in memory   wrkfiles active currently */
    offset = offset + 8
    /* Space DM in memory active currently in KB*/
    offset = offset + 24
    /* Nb SRT in memory   wrkfiles active currently */
    offset = offset + 8
    /* Space SRT in memory active currently in bytes */
    offset = offset + 32
    /* Current RID blocks overflowed (stored) in wrkfiles*/
    offset = offset + 8
    /* Current NON Sort related workfiles active */
    offset = offset + 16
    /* Physical  workfiles created */
    offset = offset + 24
    /* HWM wkfile storage used by an agent */
    QISTAMXU =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    /* Current storage configured for wkfiles*/
    offset = offset + 8
    /* Current DGTT  configured for wkfile KB*/
    offset = offset + 8
    /* Current DGTT  used  KB*/
    offset = offset + 8
    /* HWM     DGTT  used  KB*/
    QISTDGTTMXU = C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    /* Current others  configured for wkfile KB*/
    offset = offset + 8
    /* Current others used  KB*/
    offset = offset + 8
    /* HWM    others used KB*/
    QISTWFMXU = C2D(SUBSTR(INPUT_REC,OFFSET,8))
    return
/* MAP STANDARD HEADER PRODUCT SECTION */
DSNDQWHS:
  OFFSET = OFFSET + 2
  QWHSTYP = C2D(SUBSTR(INPUT_REC,OFFSET,1))
  OFFSET = OFFSET + 2
  /* QWHSIID DS XL2 IFCID */
  QWHSIID = C2D(SUBSTR(INPUT_REC,OFFSET,2))
  IFCID=QWHSIID
  OFFSET = OFFSET + 2
  QWHSNSDA =C2D(SUBSTR(INPUT_REC,OFFSET,1))
  OFFSET = OFFSET + 6
  /* QWHSSSID DS CL4 SUBSYSTEM NAME */
  QWHSSSID = SUBSTR(INPUT_REC,OFFSET,4)
  OFFSET = OFFSET + 64
  /* TOTAL LENGTH = 76 */
  RETURN

/* STATISTICS CPU TIME MAPPING MACRO LG = 52*4*/
DSNDQWSA:
    numeric digits 15
    QWSAPROC =(SUBSTR(INPUT_REC,OFFSET,4))
    OFFSET = OFFSET + 4
    /*CONVERT INTO HEX VALUE*/
    QWSAEJST = C2X(SUBSTR(INPUT_REC,OFFSET,8))
    /*ELIMINATE 1.5 BYTES */
    QWSAEJST = X2D(SUBSTR(QWSAEJST,1,13))
    QWSAEJST = QWSAEJST/1000000
    OFFSET = OFFSET + 8

    QWSASRBT = C2X(SUBSTR(INPUT_REC,OFFSET,8))
    QWSASRBT = X2D(SUBSTR(QWSASRBT,1,13))
    QWSASRBT = QWSASRBT/1000000
    OFFSET = OFFSET + 16

    QWSAPSRB = C2X(SUBSTR(INPUT_REC,OFFSET,8))
    QWSAPSRB = X2D(SUBSTR(QWSAPSRB,1,13))
    QWSAPSRB = QWSAPSRB/1000000
    OFFSET = OFFSET + 8

    QWSAPSRB_Ziip = C2X(SUBSTR(INPUT_REC,OFFSET,8))
    QWSAPSRB_Ziip = X2D(SUBSTR(QWSAPSRB_Ziip,1,13))
    QWSAPSRB_Ziip = QWSAPSRB_Ziip/1000000
    OFFSET = OFFSET + 16

    Select
         When qwsaproc  = 'MSTR' Then do
                    MstrTcb      =QWSAEJST
                    MstrSrb      =QWSAsrbt
                    MstrpSRB     =QWSApsrb
                    MstrpSRB_Ziip=QWSApsrb_Ziip
                 end
         When qwsaproc  = 'DBM1' Then do
                    DBM1Tcb      =QWSAEJST
                    DBM1Srb      =QWSAsrbt
                    DBM1pSRB     =QWSApsrb
                    DBM1pSRB_Ziip=QWSApsrb_Ziip
                 end
         When qwsaproc  = 'DIST' Then do
                    DISTTcb      =QWSAEJST
                    DISTSrb      =QWSAsrbt
                    DISTpSRB     =QWSApsrb
                    DISTpSRB_Ziip=QWSApsrb_Ziip
                 end
         When qwsaproc  = 'IRLM' Then do
                    IRLMTcb      =QWSAEJST
                    IRLMSrb      =QWSAsrbt
                    IRLMpSRB     =QWSApsrb
                    IRLMpSRB_Ziip=QWSApsrb_Ziip
                 end
         Otherwise      do
                          say 'qwsaproc NOT correct' qwsaproc
                          exit 8
                        end
    end   /* select */
RETURN

DSNDQISE:
    /* EDMPOOL STATS */
    numeric digits 15
    /* Fields from IFCID002  : all cumulative */
    /* calculate difference between interval */

    /*# OF REQ FOR CT SECTIONS*/
    offset = offset + 8
    QISECTG = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF LOAD CT SECT FROM DASD*/
    offset = offset + 4
    QISECTL = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF REQUESTS FOR DBD*/
    offset = offset + 20
    QISEDBDG = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF LOAD DBD FROM DASD*/
    offset = offset + 4
    QISEDBDL = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF REQ FOR PT SECTIONS*/
    offset = offset + 4
    QISEKTG  = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF LOAD PT SECT FROM DASD*/
    offset = offset + 4
    QISEKTL = C2D(SUBSTR(INPUT_REC,offset,4))
    offset = offset + 12
    /*# OF Inserts  FOR DYN CACHE*/
    QISEDSI  = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF REQUESTS FOR DYN CACHE*/
    offset = offset +  4
    QISEDSG  = C2D(SUBSTR(INPUT_REC,offset,4))
    /*NUMBER OF PAGES IN DBD POOL*/
    offset = offset + 12
    QISEDPGE = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF FREE PG IN DBD FREE CHAIN*/
    offset = offset + 4
    QISEDFRE = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF FAIL DUE TO DBD POOL FULL*/
    offset = offset - 8
    QISEDFAL = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF PGS IN STMT POOL*/
    offset = offset + 20
    QISECPGE = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF FREE PG IN STMT FREE CHAIN*/
    offset = offset + 4
    QISECFRE = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF FAIL DUE TO STMT POOL FULL*/
    offset = offset - 8
    QISECFAL = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF PAGES IN SKEL EDM POOL*/
    offset = offset + 24
    QISEKPGE = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF FREE PG IN SKEL EDM POOL FREE CHAIN */
    offset = offset + 4
    QISEKFRE = C2D(SUBSTR(INPUT_REC,offset,4))
    /*# OF FAIL DUE TO STMT SKEL POOL FULL*/
    offset = offset - 8
    QISEKFAL = C2D(SUBSTR(INPUT_REC,offset,4))

return
DSNDQSST:
    offset= offset+4
    /* eye catcher */
    eyec     = SUBSTR(INPUT_REC,OFFSET,4)
    if ( eyec     <> 'QSST' ) then
                  do
                      say 'DSNDQSST eye catcher not met, error'
                      exit(8)
                  end
    offset= offset+4*14
    /* full storage contraction*/
    QSSTCONT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    QSSTCRIT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    QSSTABND = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
 return

DSNDQTST:
    /* Service Controler Stats */
    offset= offset+4
    /* eye catcher */
    eyec     = SUBSTR(INPUT_REC,OFFSET,4)
    if ( eyec     <> 'QTST' ) then
                  do
                      say 'DSNDQTST eye catcher not met, error'
                      exit(8)
                  end
    offset= offset+4*18
    /* Datasets opened */
    QTDSOPN  =  C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4*12
    /* DS closed by drain DSMax reached */
    QTDSDRN  =  C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* RWRO Convert */
    QTPCCT   =  C2D(SUBSTR(INPUT_REC,OFFSET,4))

 return
DSNDQ3ST:
    /* DB2 Subsystem services fields */
    offset= offset+4
    /* Signon, meaningful only with CICS or IMS */
    /* Nbr of signon for new user of an EXISTING thread*/
    /* If Signon > CrtThread then there is Thread reuse */
    Q3STSIGN = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Create thread (does not include DBAT) */
    Q3STCTHD = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Terminate     */
    Q3STTERM = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 8
    /* Commit1 */
    Q3STPREP = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Commit2 */
    Q3STCOMM = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Aborts */
    Q3STABRT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4*9
    /* HWM   IDBACK*/
    Q3STHWIB = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* HWM   IDFORE*/
    Q3STHWIF = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* HWM   CTHREAD*/
    Q3STHWCT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
 return

DSNDQJST:
    offset=offset+4
    /* eye catcher */
    eyec     = SUBSTR(INPUT_REC,OFFSET,4)
    if ( eyec     <> 'QJST' ) then
                  do
                      say 'DSNDQJST eye catcher not met, error'
                      exit(8)
                  end
    offset=offset+40
    /* active log output CI created */
    QJSTBFFL = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    return
DSNDQDST:
    if QWS00RCO = 0 then
    /* No DDF information */
      do
          say 'There is no DDF information in this trace'
          say ' '
          QDSTQDBT =0
          QDSTQCRT =0
          QDSTQCIT =0
          QDSTQMIT =0
          QDSTCNAT =0
          QDSTHWAT =0
          QDSTHWDT =0
          QDSTCIN2 =0
          QDSTMIN2 =0
          return
      end
    /* dbat queued */
    QDSTQDBT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 20 /* 4x 5 */
    /* dbat rejected condbat reached */
    QDSTQCRT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* current inact 1 */
    QDSTQCIT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Max     inact 1 */
    QDSTQMIT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* curr pooled dbat : active and disconnect */
    QDSTCNAT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Max  pooled dbat : active and disconnect */
    QDSTHWAT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Max  dbat        : Max active + inact    */
    QDSTHWDT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 8
    /* cur inact 2        */
    QDSTCIN2 = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4
    /* Max inact 2        */
    QDSTMIN2 = C2D(SUBSTR(INPUT_REC,OFFSET,4))
    return


GET_FMT_TIME:
  Old_Hour = Hour
  RUN_HH = SM100TME % 360000
  RUN_HH = RIGHT(RUN_HH,2,'0')
  RUN_MIN = SM100TME % 6000 - RUN_HH*60
  RUN_MIN = RIGHT(RUN_MIN,2,'0')
  RUN_SEC = SM100TME % 100 - RUN_HH *3600 - RUN_MIN*60
  RUN_SEC = RIGHT(RUN_SEC,2,'0')
  RUN_FMT_TIME = RUN_HH!!':'!!RUN_MIN!!':'!!RUN_SEC
  Hour = left(run_fmt_time,2)
  /* Detect if we change hour */
  if Old_Hour <> Hour then Change_Hour=1
                      else Change_Hour=0
  RETURN


write_header:
  say 'CSV file ' oufl     ' will be produced'
  queue "Lpar,ssid,date,dow,Hour,MstrTCB,MstrSRB,MstrPSRB,"!!,
         "MstrPSRB_Ziip,Dbm1TCB,DBm1SRB,DBm1PSRB,Dbm1PSRB_Ziip,"!!,
                       "IrlmTCB,IrlmSRB,IrlmPSRB,IrlmPSRB_Ziip,"!!,
                       "DistTCB,DistSRB,DistPSRB,DistPSRB_Ziip,"!!,
         "CrtThd,Sign,Term,Comm1,Comm2,Abort,MaxIDBACK,"!!,
         "MaxIDFOR,CThread,"!!,
         "Chkpt,"!!,
         "MaxDSCur,DSClose,DSOpen,"!!,
         "ROSwitch,"!!,
                       "Getpage,Syncio,SyncWr,AsyncWr,"!!,
                       "PageInR,PageInW,"!!,
                       "SPrefIO,CastIO,DynPrfIO,LstPrfIO,BpSio,"!!,
         "MaxInac1,MaxActDbat,MaxAllDbat,"!!,
         "MaxDbat,"!!,
         "MaxAldThds,ThdMaxComp,ThdMaxComp2,"!!,
         "MaxRealUsedDB2,MaxAuxUsedDB2,MinRealAvail,"!!,
         "MaxExtRegion,Min31Avail,"!!,
         "NotOptColProc,32KbUsed4Prf,4KbUsed32Prf,"!!,
    ,/* Logging */
         "ActLogCI," !!,
    ,/* Workfile usage  */
         "Max4KwfMB,Max32KWfMB,MaxWfUseThdMB," !!,
         "MaxDGTTMB,MaxOthMB"
     /*  Zones below correspond to the ibm provided excel columns */
     /*  "Z,BE,CV,CX,CZ,CU,CW,CY,CQ,Y,BD"  */

  "EXECIO" queued() "DISKW OUFL"
  return


write_report:
    /* summarize or Max min to report only by hour */
   /* pas de rupture pour le 1er record lu */
   if rupture = 0
   then do
       rupture=1
       call init_summary
   end
   /* We change hour, start write */

   if   Change_Hour
   then do
       call write_summary
       call init_summary
   end
   else do
   /* if same hour, continue the sum */
       sum_MstrTcb      = sum_MstrTcb + dif_MstrTcb
       sum_MstrSrb      = sum_MstrSrb + dif_MstrSrb
       sum_MstrpSRB     = sum_MstrpSRB + dif_MstrpSRB
       sum_MstrpSRB_Ziip = sum_MstrpSRB_Ziip + dif_MstrpSRB_Ziip
       sum_dbm1Tcb      = sum_dbm1Tcb + dif_dbm1Tcb
       sum_dbm1Srb      = sum_dbm1Srb + dif_dbm1Srb
       sum_dbm1pSRB     = sum_dbm1pSRB + dif_dbm1pSRB
       sum_dbm1pSRB_Ziip = sum_dbm1pSRB_Ziip + dif_dbm1pSRB_Ziip
       sum_IrlmTcb      = sum_IrlmTcb + dif_IrlmTcb
       sum_IrlmSrb      = sum_IrlmSrb + dif_IrlmSrb
       sum_IrlmpSRB     = sum_IrlmpSRB + dif_IrlmpSRB
       sum_IrlmpSRB_Ziip = sum_IrlmpSRB_Ziip + dif_IrlmpSRB_Ziip
       sum_DistTcb   = sum_DistTcb + dif_DistTcb
       sum_DistSrb   = sum_DistSrb + dif_DistSrb
       sum_DistpSRB  = sum_DistpSRB+ dif_DistpSRB
       sum_DistpSRB_Ziip = sum_DistpSRB_Ziip+ dif_DistpSRB_Ziip
       sum_Q3STCTHD  = sum_Q3STCTHD + dif_Q3STCTHD /* cr threads*/
       sum_Q3STSIGN  = sum_Q3STSIGN + dif_Q3STSIGN /* Signon  */
       sum_Q3STTERM  = sum_Q3STTERM + dif_Q3STTERM /* Terminate*/
       sum_Q3STPREP  = sum_Q3STPREP + dif_Q3STPREP /* commit ph1*/
       sum_Q3STCOMM  = sum_Q3STCOMM + dif_Q3STCOMM /* Commit Ph 2*/
       sum_Q3STABRT  = sum_Q3STABRT + dif_Q3STABRT /* Aborts */
       if  Q3STHWIB > Max_Q3STHWIB  then     /* Max IDBACK */
           Max_Q3STHWIB = Q3STHWIB
       if  Q3STHWIF > Max_Q3STHWIF  then     /* Max IDFORE */
           Max_Q3STHWIF = Q3STHWIF
       if  Q3STHWCT > Max_Q3STHWCT  then     /* Max IDFORE */
           Max_Q3STHWCT = Q3STHWCT
       if  QTDSOPN  > Max_QTDSOPN   then     /* Max DS Opened*/
           Max_QTDSOPN  = QTDSOPN
       Sum_QXSTFND = Sum_QXSTFND + dif_QXSTFND   /* Full prepare*/
       Sum_QXSTNFND= Sum_QXSTNFND+ dif_QXSTNFND
       Sum_QXSTIPRP= Sum_QXSTIPRP+ dif_QXSTIPRP
       Sum_QXSTNPRP= Sum_QXSTNPRP+ dif_QXSTNPRP
       Sum_QWSDCKPT= Sum_QWSDCKPT+ dif_QWSDCKPT  /* Checkpoints */
       Sum_QTDSDRN = Sum_QTDSDRN + dif_QTDSDRN   /* Drain Close */
       Sum_QTPCCT  = Sum_QTPCCT  + dif_QTPCCT    /* RWRO Switch */
       Sum2_QBSTDSO = Sum2_QBSTDSO + dif_QBSTDSO   /* Open DS*/
       sum2_QBSTGET = sum2_QBSTGET + dif_QBSTGET /* gp */
       sum2_QBSTRIO = sum2_QBSTRIO + dif_QBSTRIO /* sync read */
       sum2_QBSTIMW = sum2_QBSTIMW + dif_QBSTIMW /* Immed. write */
       sum2_QBSTWIO = sum2_QBSTWIO + dif_QBSTWIO /* Async Write */
       sum2_QBSTRPI = sum2_QBSTRPI + dif_QBSTRPI /* Page IN Read*/
       sum2_QBSTWPI = sum2_QBSTWPI + dif_QBSTWPI /* Page In Writ*/
       sum2_QBSTPIO = sum2_QBSTPIO + dif_QBSTPIO /* Seq Pref. IO */
       sum2_QBSTMAX = sum2_QBSTMAX + dif_QBSTMAX /* Wrkfil no created*/
       sum2_QBSTWFD = sum2_QBSTWFD + dif_QBSTWFD /* Wrkfil rejected*/
       sum2_QBSTWFF = sum2_QBSTWFF + dif_QBSTWFF /* merge pass degrad*/
       sum2_QBSTCIO = sum2_QBSTCIO + dif_QBSTCIO /* Castout IO */
       sum2_QBSTDIO = sum2_QBSTDIO + dif_QBSTDIO /* Dyn Pr IO */
       sum2_QBSTLIO = sum2_QBSTLIO + dif_QBSTLIO /* Lst Pr IO */
       sum2_QBSTSIO = sum2_QBSTSIO + dif_QBSTSIO /* SIO */
       if  QDSTQMIT > Max_QDSTQMIT  then     /* Max inact type1*/
           Max_QDSTQMIT = QDSTQMIT
       if  QDSTHWAT > Max_QDSTHWAT  then     /* Max act dbat */
           Max_QDSTHWAT = QDSTHWAT
       if  QDSTHWDT > Max_QDSTHWDT  then     /* Max act&inact dbat*/
           Max_QDSTHWDT = QDSTHWDT
       if  QDSTMIN2 > Max_QDSTMIN2  then     /* Max  dbat*/
           Max_QDSTMIN2 = QDSTMIN2
       if  QW0225AT > Max_QW0225AT  then     /* Max allied threads*/
           Max_QW0225AT = QW0225AT
       if  ThdComp  < min_ThdComp   then     /* Max thread computed*/
           min_Thdcomp  = Thdcomp
       if  ThdComp2 < min_ThdComp2  then  /* Max thread computed*/
           min_Thdcomp2 = Thdcomp2
       if  TotalRealUsedByDB2 > Max_TotalRealUsedByDB2 then
           Max_TotalRealUsedByDB2 = TotalRealUsedByDB2
       if  TotalAuxlUsedByDB2 > Max_TotalAuxlUsedByDB2 then
           Max_TotalAuxlUsedByDB2 = TotalAuxlUsedByDB2
       if  QW0225_REALAVAIL   < min_QW0225_REALAVAIL then
           min_QW0225_REALAVAIL = QW0225_REALAVAIL
       if  QW0225RG    > Max_QW0225RG then
           Max_QW0225RG         = QW0225RG /* Region Size extended */
       if  QW0225AV    < Min_QW0225AV then /* 31 bits available */
          Min_QW0225AV         = QW0225AV
       sum_QISTCOLS= Sum_QISTCOLS+ dif_QISTCOLS /* Cols not optimized*/
       sum_QISTWFP1= Sum_QISTWFP1+ dif_QISTWFP1 /* 32KbUsed4Pref.*/
       sum_QISTWFP2= Sum_QISTWFP2+ dif_QISTWFP2 /* 4KbUsed32Prf*/
       sum_QJSTBFFL= Sum_QJSTBFFL+ dif_QJSTBFFL /* Log created*/
   end
   return
write_summary:
    /* write only if some records have been read between writes*/
    if RFlush= 0 ! ( RFlush=1 & recw<reci)  then nop
                      else return
    /* output counter */
    reco= reco+ 1
    recw= reci  /* we save when we write */
    /* Display some warnings */
    Call Check_counters
    /*rows in excel format */
    queue sm100sid !! ',' !! sm100ssi !! ','  ,
    !! '"' !! sm100dte !! '"' !! ','   ,
    !! dayoweek     !! ','   ,
    !! Old_Hour     !! ','   ,
    !! sum_MstrTcb      !! ','   ,
    !! sum_MstrSrb      !! ','   ,
    !! sum_MstrpSRB     !! ','   ,
    !! sum_MstrpSRB_Ziip !! ','   ,
    !! sum_dbm1Tcb      !! ','   ,
    !! sum_dbm1Srb      !! ','   ,
    !! sum_dbm1pSRB     !! ','   ,
    !! sum_dbm1pSRB_Ziip !! ','   ,
    !! sum_IrlmTcb      !! ','   ,
    !! sum_IrlmSrb      !! ','   ,
    !! sum_IrlmpSRB     !! ','   ,
    !! sum_IrlmpSRB_Ziip !! ','  ,
    !! sum_DistTcb      !! ','   ,
    !! sum_DistSrb      !! ','   ,
    !! sum_DistpSRB     !! ','     ,
    !! sum_DistpSRB_Ziip !! ','    ,
    !! sum_Q3STCTHD  !! ','        ,     /* Create Thd */
    !! sum_Q3STSIGN  !! ','        ,     /* Signon  */
    !! sum_Q3STTERM  !! ','        ,     /* Terminate*/
    !! sum_Q3STPREP  !! ','        ,     /* Commit phase 1 */
    !! sum_Q3STCOMM  !! ','        ,     /* Commit Ph 2*/
    !! sum_Q3STABRT  !! ','        ,     /* Aborts */
    !! Max_Q3STHWIB  !! ','        ,     /* Max IDBACK */
    !! Max_Q3STHWIF  !! ','        ,     /* Max IDFORE */
    !! Max_Q3STHWCT  !! ','        ,     /* Max CTHREAD */
    !! sum_QWSDCKPT  !! ','        ,     /* Checkpoints */
    !! Max_QTDSOPN   !! ','        ,     /* DS Opened   */
    !! sum_QTDSDRN   !! ','        ,     /* Drain Close */
    !! sum2_QBSTDSO  !! ','        ,     /* OPEN DS     */
    !! sum_QTPCCT    !! ','        ,     /* RWRO switch */
    !! sum2_QBSTGET   !! ','        ,
    !! sum2_QBSTRIO   !! ','        ,
    !! sum2_QBSTIMW   !! ','        ,
    !! sum2_QBSTWIO   !! ','        ,
    !! sum2_QBSTRPI   !! ','        , /*page in read */
    !! sum2_QBSTWPI   !! ','        ,
    !! sum2_QBSTPIO   !! ','        ,
    !! sum2_QBSTCIO   !! ','        ,
    !! sum2_QBSTDIO   !! ','        ,
    !! sum2_QBSTLIO   !! ','        ,
    !! sum2_QBSTSIO   !! ','        ,
    !! Max_QDSTQMIT      !! ','        ,     /* Max . inact type 1*/
    !! Max_QDSTHWAT      !! ','        ,     /* Max active dbat*/
    !! Max_QDSTHWDT      !! ','        ,     /* Max act & inact dbat */
    !! Max_QDSTMIN2      !! ','        ,     /* act dbat */
    !! Max_QW0225AT      !! ','        ,     /*  allied threads*/
    !! format(min_ThdComp ,4,0)   !! ',' ,
    !! format(min_ThdComp2,4,0)   !! ',' ,
    !! f2mb(Max_TotalRealUsedByDB2)     !! ',' ,
    !! f2mb(Max_TotalAuxlUsedByDB2)     !! ',' ,
    !! f2mb(min_QW0225_REALAVAIL)       !! ',' ,
    !! b2mb(Max_QW0225RG)               !! ',' ,
    !! b2mb(min_QW0225AV)               !! ',' , /* 31 bits avail*/
    !!         sum_QISTCOLS         !! ',' ,
    !!         sum_QISTWFP1         !! ',' ,
    !!         sum_QISTWFP2         !! ',' ,
    !!     sum_QJSTBFFL             !! ',' ,  /*Log created*/
    !!  trunc(Max_QISTW4K/1024)  !! ',' , /* Max MB 4K */
    !!  trunc(Max_QISTW32K/1024) !! ',' ,
    !!  trunc(QISTAMXU/1024)     !! ',' , /*Max MB wk used thread*/
    !!  trunc(QISTDGTTMXU/1024)  !! ',' , /* Max MB DGTT */
    !!  trunc(QISTWFMXU/1024)    !! ','   /* Max MB Other*/
   "EXECIO" queued() "DISKW OUFL"
return


/* SMF HEADER */
DSNDQWST:
   OFFSET = OFFSET + 1
   /* SM100RTY DS XL1 RECORD TYPE X'64' OR 100 */
   SM100RTY = C2D(SUBSTR(INPUT_REC,OFFSET,1))
   /* stop processing if not 100 */
   if sm100rty <> 100 then return
   OFFSET = OFFSET + 1
   /* SM100TME DS XL4 TIME SMF MOVED RECORD */
   SM100TME = C2D(SUBSTR(INPUT_REC,OFFSET,4))
   CALL GET_FMT_TIME
   OFFSET = OFFSET + 4
   field    = C2X(SUBSTR(INPUT_REC,OFFSET,4))
     parse value field with 1 . 2 c 3 yy 5 ddd 8 .
     if (c = 0) then
       yyyy = '19'!!yy
     else
       yyyy = '20'!!yy
   sm100dte    = yyyy!!'.'!!ddd
   /* get day of week : easier to select days */
   test_date = yyyy ddd
   sm100dte=DAT_MVS2SD(test_date)
   dayoweek = DAT_S2DOW(sm100dte)
   /* save date of smf records processed */
   if reco = 0 then save_date=sm100dte
   else do
     if save_date <> sm100dte & displ = 0 then do
        displ=1
        say 'There is 2 different dates in this SMF extract'
        say '             '  save_date sm100dte
        say ' '
     end
   end
   OFFSET = OFFSET + 4
   sm100sid = SUBSTR(INPUT_REC,OFFSET,4)
   OFFSET = OFFSET + 4
   /* SM100SSI DS CL4 SUBSYSTEM ID */
   sm100ssi = SUBSTR(INPUT_REC,OFFSET,4)
   OFFSET = OFFSET + 10
   /* TOTAL LENGTH = 28 */
RETURN


dsndqbst:
    numeric digits 15
    QBSTPID =  C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 8
    QBSTGET =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    QBSTRIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    offset = offset + 8*5
    QBSTWIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 16
    QBSTRPI =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    QBSTWPI =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    /* Open Dataset */
    QBSTDSO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    QBSTIMW =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 16
    /* Pages read seq Prefetch */
    QBSTSPP =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 56
    /* OF SEQ PREFETCH (ASYNCHRONOUS) READ*/
    QBSTPIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 16
    /* nb wkfile not created due to buffers resource */
    QBSTMAX =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 48
    /* nb of workfiles denied during sort/merge */
    QBSTWFD =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    /* nb of time sort not optimized due to BP shortage*/
    QBSTWFF =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 40
    /* nb of cast out IO */
    QBSTCIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    QBSTVPL =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 24
    /* save BP0 size - after 17:00 because i had time to modify */
    if lpar = 'SUD2' & Old_Hour > '17' then
    do
         if bp0_vpsize  = 0 then
         do
             if QBSTPID = 0 then do
                                 bp0_vpsize = QBSTVPL
                                 say  ssid 'BP0VPSIZE=' bp0_vpsize
                            end
         end
    end
    QBSTDIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8
    QBSTLIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 16
    QBSTSIO =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    /*    say 'Buffid =' QBSTPID,     */
    /*        'QBSTGET=' QBSTGET,     */
    /*        'QBSTRIO=' QBSTRIO,     */
    /*        'QBSTWIO=' QBSTWIO,     */
    /*        'QBSTIMW=' QBSTIMW,     */
    /*    say 'QBSTPIO=' QBSTPIO,     */
    /*        'QBSTCIO=' QBSTCIO,     */
    /*        'QBSTDIO=' QBSTDIO,     */
    /*        'QBSTLIO=' QBSTLIO,     */
    /*        'QBSTSIO=' QBSTSIO      */
    offset = offset + 144 /* 8*18 */

    /*****************************/
    /* Processing the data read  */
    /*****************************/

    /* test if BufferID QBSTPIDis already recorded */
    i=1
    do while i <= nbBP
       if QBSTPID = BPList.i then leave
       i=i+1
    end
    if i >  nbBP then /* this BP is not recorded yet */
    do
        nbBP=nbBP+1
        BPList.nbBP=QBSTPID
        ListPrefLow.QBSTPID = 0
        /* First entry is  created with read value because */
        /* records are cumulative (from yesterday value for example*/
        Old_QBSTSPP.QBSTPID=QBSTSPP
        Old_QBSTPIO.QBSTPID=QBSTPIO
    end

    /* Processing counters to report */
    Dif_QBSTSPP.QBSTPID = QBSTSPP  - Old_QBSTSPP.QBSTPID
    Dif_QBSTPIO.QBSTPID = QBSTPIO  - Old_QBSTPIO.QBSTPID
    Old_QBSTSPP.QBSTPID=QBSTSPP
    Old_QBSTPIO.QBSTPID=QBSTPIO
    /*******************************/
    /* Calculate prefetch quantity */
    /*******************************/
    /*say  Dif_QBSTSPP.QBSTPID  Dif_QBSTPIO.QBSTPID*/
    if  Dif_QBSTSPP.QBSTPID > 0 & Dif_QBSTPIO.QBSTPID > 0 then
    do
      PrefQty = trunc(Dif_QBSTSPP.QBSTPID/Dif_QBSTPIO.QBSTPID)
      if PrefQty <= 4 then do
         /*  temR=1
             rec.1= 'Prefetch Qty too low for BP ' QBSTPID,
                    sm100sid'/'sm100ssi '@'RUN_FMT_TIME PrefQty
                  call logW */
             ListPrefLow.QBSTPID = ListPrefLow.QBSTPID+1
        end
    end

    return
dsndqbgl:
    numeric digits 15
    /* Group BPID */
    QBGLGN  =  C2D(SUBSTR(INPUT_REC,OFFSET,4))
    offset = offset + 4+1+3
    offset = offset + 8*17
    /* Write requests failed no storage */
    QBGLWF  =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    offset = offset + 8*13
    /* Write requests failed no storage secondary GBP */
    QBGL2F  =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    /* Write Around */
    offset = offset + 8*17
    QBGLWA  =  C2D(SUBSTR(INPUT_REC,OFFSET,8))
    /* go to end of macro QBGL */
    offset = offset + 8 + 24

    /*****************************/
    /* Processing the data read  */
    /*****************************/

    /* test if BufferID QBGLGN is already recorded */
    i=1
    do while i <= nbGBP
       if QBGLGN = GBPList.i then leave
       i=i+1
    end
    if i >  nbGBP then /* this GBP is not recorded yet */
    do
        nbGBP=nbGBP+1
        GBPList.nbGBP=QBGLGN
        /* First entry is  created with read value because */
        /* records are cumulative (from yesterday value for example*/
        Old_QBGL2F.QBGLGN =QBGL2F
        Old_QBGLWF.QBGLGN =QBGLWF
        Old_QBGLWA.QBGLGN =QBGLWA
        SumHr_QBGLWF.QBGLGN = 0
        SumHr_QBGL2F.QBGLGN = 0
        SumHr_QBGLWA.QBGLGN = 0
    end

    /* Processing counters to report */
    Dif_QBGLWF.QBGLGN = QBGLWF - Old_QBGLWF.QBGLGN
    Dif_QBGL2F.QBGLGN = QBGL2F - Old_QBGL2F.QBGLGN
    Dif_QBGLWA.QBGLGN = QBGLWA - Old_QBGLWA.QBGLGN
    Old_QBGLWF.QBGLGN = QBGLWF
    Old_QBGL2F.QBGLGN = QBGL2F
    Old_QBGLWA.QBGLGN = QBGLWA
    if Dif_QBGLWA.QBGLGN > 0  then
      SumHr_QBGLWA.QBGLGN=SumHr_QBGLWA.QBGLGN+Dif_QBGLWA.QBGLGN
    if Dif_QBGL2F.QBGLGN > 0  then
      SumHr_QBGL2F.QBGLGN=SumHr_QBGL2F.QBGLGN+Dif_QBGL2F.QBGLGN
    if Dif_QBGLWF.QBGLGN > 0  then
      SumHr_QBGLWF.QBGLGN=SumHr_QBGLWF.QBGLGN+Dif_QBGLWF.QBGLGN

    return

ifcid_diff:
       /* Cumulative values, report only the difference */
       /* When diff is negative, this means that the value have been*/
       /* reset (Seen at DB2 restart , but probably also if they    */
       /* reach their Max)                                          */
              Dif_MstrTcb =       MstrTcb       - Old_MstrTcb
              Dif_MstrSrb =       MstrSrb       - Old_MstrSrb
              Dif_MstrpSRB=       MstrpSRB      - Old_MstrpSRB
              Dif_MstrpSRB_Ziip = MstrpSRB_Ziip - Old_MstrpSRB_Ziip
              Dif_dbm1Tcb =       dbm1Tcb       - Old_dbm1Tcb
              Dif_dbm1srb =       dbm1srb       - Old_dbm1srb
              Dif_dbm1pSRB=       dbm1pSRB      - Old_dbm1pSRB
              Dif_dbm1pSRB_Ziip = dbm1pSRB_Ziip - Old_dbm1pSRB_Ziip
              Dif_irlmTcb =       irlmTcb       - Old_irlmTcb
              Dif_irlmsrb =       irlmsrb       - Old_irlmsrb
              Dif_irlmpSRB=       irlmpSRB      - Old_irlmpSRB
              Dif_irlmpSRB_Ziip = irlmpSRB_Ziip - Old_irlmpSRB_Ziip
              Dif_distTcb =       distTcb       - Old_distTcb
              Dif_distsrb =       distsrb       - Old_distsrb
              Dif_distpSRB=       distpSRB      - Old_distpSRB
              Dif_distpSRB_Ziip = distpSRB_Ziip - Old_distpSRB_Ziip

        if    Dif_MstrTcb < 0 then
        do
              say '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
              say 'Cumulative fields reset, possible DB2 RECYCLE'
              say '      at' sm100dte run_fmt_time
              say '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
              say ''

              Dif_MstrTcb =       MstrTcb
              Dif_MstrSrb =       MstrSrb
              Dif_MstrpSRB=       MstrpSRB
              Dif_MstrpSRB_Ziip = MstrpSRB_Ziip
              Dif_dbm1Tcb =       dbm1Tcb
              Dif_dbm1srb =       dbm1srb
              Dif_dbm1pSRB=       dbm1pSRB
              Dif_dbm1pSRB_Ziip = dbm1pSRB_Ziip
              Dif_irlmTcb =       irlmTcb
              Dif_irlmsrb =       irlmsrb
              Dif_irlmpSRB=       irlmpSRB
              Dif_irlmpSRB_Ziip = irlmpSRB_Ziip
              Dif_distTcb =       distTcb
              Dif_distsrb =       distsrb
              Dif_distpSRB=       distpSRB
              Dif_distpSRB_Ziip = distpSRB_Ziip
        end
              Old_Mstrtcb =       Mstrtcb
              Old_MstrSrb =       MstrSrb
              Old_MstrpSRB=       MstrpSRB
              Old_MstrpSRB_Ziip = MstrpSRB_Ziip
              Old_dbm1Tcb =       dbm1Tcb
              Old_dbm1srb =       dbm1srb
              Old_dbm1pSRB=       dbm1pSRB
              Old_dbm1pSRB_Ziip = dbm1pSRB_Ziip
              Old_irlmTcb =       irlmTcb
              Old_irlmsrb =       irlmsrb
              Old_irlmpSRB=       irlmpSRB
              Old_irlmpSRB_Ziip = irlmpSRB_Ziip
              Old_distTcb =       distTcb
              Old_distsrb =       distsrb
              Old_distpSRB=       distpSRB
              Old_distpSRB_Ziip = distpSRB_Ziip

       /*********************************/
       /* Subsystem services stats Q3ST */
       /*********************************/
              Dif_Q3STSIGN =     Q3STSIGN-Old_Q3STSIGN
              Dif_Q3STTERM =     Q3STTERM-Old_Q3STTERM
              Dif_Q3STCTHD =     Q3STCTHD-Old_Q3STCTHD
              Dif_Q3STPREP =     Q3STPREP-Old_Q3STPREP
              Dif_Q3STCOMM =     Q3STCOMM-Old_Q3STCOMM
              Dif_Q3STABRT =     Q3STABRT-Old_Q3STABRT

          if  Dif_Q3STSIGN < 0 then
          do
              Dif_Q3STSIGN = Q3STSIGN
              Dif_Q3STTERM = Q3STTERM
              Dif_Q3STCTHD = Q3STCTHD
              Dif_Q3STPREP = Q3STPREP
              Dif_Q3STCOMM = Q3STCOMM
              Dif_Q3STABRT = Q3STABRT
          end

          Old_Q3STSIGN = Q3STSIGN
          Old_Q3STTERM = Q3STTERM
          Old_Q3STCTHD = Q3STCTHD
          Old_Q3STPREP = Q3STPREP
          Old_Q3STCOMM = Q3STCOMM
          Old_Q3STABRT = Q3STABRT

       /***************************/
       /* buffer pool stats       */
       /***************************/

              Dif_QBSTGET = Sum_QBSTGET-Old_QBSTGET
              Dif_QBSTRIO = Sum_QBSTRIO-Old_QBSTRIO
              Dif_QBSTDSO = Sum_QBSTDSO-Old_QBSTDSO
              Dif_QBSTIMW = Sum_QBSTIMW-Old_QBSTIMW
              Dif_QBSTWIO = Sum_QBSTWIO-Old_QBSTWIO
              Dif_QBSTRPI = Sum_QBSTRPI-Old_QBSTRPI
              Dif_QBSTWPI = Sum_QBSTWPI-Old_QBSTWPI
              Dif_QBSTPIO = Sum_QBSTPIO-Old_QBSTPIO
              Dif_QBSTMAX = Sum_QBSTMAX-Old_QBSTMAX
              Dif_QBSTWFD = Sum_QBSTWFD-Old_QBSTWFD
              Dif_QBSTWFF = Sum_QBSTWFF-Old_QBSTWFF
              Dif_QBSTCIO = Sum_QBSTCIO-Old_QBSTCIO
              Dif_QBSTDIO = Sum_QBSTDIO-Old_QBSTDIO
              Dif_QBSTlIO = Sum_QBSTlIO-Old_QBSTlIO
              Dif_QBSTsIO = Sum_QBSTsIO-Old_QBSTsIO

          if  Dif_QBSTGET < 0 then
          do
              Dif_QBSTGET = Sum_QBSTGET
              Dif_QBSTRIO = Sum_QBSTRIO
              Dif_QBSTDSO = Sum_QBSTDSO
              Dif_QBSTIMW = Sum_QBSTIMW
              Dif_QBSTWIO = Sum_QBSTWIO
              Dif_QBSTRPI = Sum_QBSTRPI
              Dif_QBSTWPI = Sum_QBSTWPI
              Dif_QBSTPIO = Sum_QBSTPIO
              Dif_QBSTMAX = Sum_QBSTMAX
              Dif_QBSTWFD = Sum_QBSTWFD
              Dif_QBSTWFF = Sum_QBSTWFF
              Dif_QBSTCIO = Sum_QBSTCIO
              Dif_QBSTDIO = Sum_QBSTDIO
              Dif_QBSTlIO = Sum_QBSTlIO
              Dif_QBSTsIO = Sum_QBSTsIO
          end
              Old_QBSTGET = Sum_QBSTGET
              Old_QBSTRIO = Sum_QBSTRIO
              Old_QBSTIMW = Sum_QBSTIMW
              Old_QBSTDSO = Sum_QBSTDSO
              Old_QBSTWIO = Sum_QBSTWIO
              Old_QBSTRPI = Sum_QBSTRPI
              Old_QBSTWPI = Sum_QBSTWPI
              Old_QBSTPIO = Sum_QBSTPIO
              Old_QBSTMAX = Sum_QBSTMAX
              Old_QBSTWFD = Sum_QBSTWFD
              Old_QBSTWFF = Sum_QBSTWFF
              Old_QBSTCIO = Sum_QBSTCIO
              Old_QBSTDIO = Sum_QBSTDIO
              Old_QBSTlIO = Sum_QBSTlIO
              Old_QBSTsIO = Sum_QBSTsIO

      /****************************************/
      /* dsndqjst Log  Manager stats IFCID 001*/
      /****************************************/
      Dif_QJSTBFFL = QJSTBFFL - Old_QJSTBFFL
      if  Dif_QJSTBFFL < 0 then
              Dif_QJSTBFFL = QJSTBFFL
      Old_QJSTBFFL = QJSTBFFL

      /****************************************/
      /* dsndqist Data Manager stats IFCID 002 */
      /****************************************/
              Dif_QTDSDRN  = QTDSDRN  - Old_QTDSDRN
              Dif_QTPCCT   = QTPCCT   - Old_QTPCCT
              Dif_QWSDCKPT = QWSDCKPT - Old_QWSDCKPT
              Dif_QXSTFND  = QXSTFND  - Old_QXSTFND
              Dif_QXSTNFND = QXSTNFND - Old_QXSTNFND
              Dif_QXSTIPRP = QXSTIPRP - Old_QXSTIPRP
              Dif_QXSTNPRP = QXSTNPRP - Old_QXSTNPRP

              Dif_QISTRPDM = QISTRPDM - Old_QISTRPDM
              Dif_QISTCOLS = QISTCOLS - Old_QISTCOLS
              Dif_QISTWFP1 = QISTWFP1 - Old_QISTWFP1
              Dif_QISTWFP2 = QISTWFP2 - Old_QISTWFP2

      if  Dif_QISTRLLM < 0 then
      do
              Dif_QTDSDRN  = QTDSDRN
              Dif_QTPCCT   = QTPCCT
              Dif_QWSDCKPT = QWSDCKPT
              Dif_QXSTFND  = QXSTFND
              Dif_QXSTNFND = QXSTNFND
              Dif_QXSTIPRP = QXSTIPRP
              Dif_QXSTNPRP = QXSTNPRP
              Dif_QISTRLLM = QISTRLLM
              Dif_QISTRPDM = QISTRPDM
              Dif_QISTCOLS = QISTCOLS
              Dif_QISTWFP1 = QISTWFP1
              Dif_QISTWFP2 = QISTWFP2
      end

              Old_QTDSDRN  = QTDSDRN
              Old_QTPCCT   = QTPCCT
              Old_QWSDCKPT = QWSDCKPT
              Old_QXSTFND  = QXSTFND
              Old_QXSTNFND = QXSTNFND
              Old_QXSTIPRP = QXSTIPRP
              Old_QXSTNPRP = QXSTNPRP
              Old_QISTRLLM = QISTRLLM
              Old_QISTRPDM = QISTRPDM
              Old_QISTCOLS = QISTCOLS
              Old_QISTWFP1 = QISTWFP1
              Old_QISTWFP2 = QISTWFP2

      return
DisplayVStor:
  if vsm='Y' & reco > 0 & lpar <> 'SUD2' then
  do
    rec.1= ' '; call LOGW ; rec.1= ' ' ; call LOGW
    rec.1= 'Threads observed Max : ' MaxThdSee 'at' MaxThdSeeDate,
                                                 MaxThdSeeTime
    call LOGW
    rec.1= '                 Min : ' MinThdSee 'at' MinThdSeeDate,
                                                 MinThdSeeTime
    call LOGW
    rec.1= ' '; call LOGW ; rec.1= ' ' ; call LOGW
    rec.1= 'Max Threads allowed projected with this period is : '
    call LOGW
    rec.1= '    ' floor(MinThdComp) 'at' MinThdCompDate MinThdCompTime,
        '/' floor(MaxThdComp) 'at' MaxThdCompDate MaxThdCompTime
    call LOGW
    rec.1= '    Formula without Min/Max applied : '
    call LOGW
    rec.1= '    ' floor(MinThdComp2) 'at' MinThdComp2Date MinThdComp2Time,
        '/' floor(MaxThdComp2) 'at' MaxThdComp2Date MaxThdComp2Time
    call LOGW
    rec.1= ' '
    call LOGW
    rec.1= 'DBM1, Max Real Storage is : ' format(MaxReal4K_dbm1,5,2),
        'MB at ' Date_MaxReal4K_dbm1 time_MaxReal4K_dbm1
    call LOGW
    rec.1= '                   Min is : ' ,
                             format(MinReal4K_dbm1,5,2) 'MB at ',
           Date_MinReal4K_dbm1 time_MinReal4K_dbm1
    call LOGW
    rec.1= 'DIST, Max Real Storage is : ' format(MaxReal4K_dist,5,2),
        'MB at ' Date_MaxReal4K_dist time_MaxReal4K_dist
    rec.1= '                   Min is : ' ,
                          format(MinReal4K_dist,5,2) 'MB at ',
         Date_MinReal4K_dist time_MinReal4K_dist
    call LOGW
    rec.1= ' '
    call LOGW
 /* rec.1= 'Max Real Storage used by LPAR :' MaxRealLPAR ' Frames --', */
 /*            f2mb(MaxRealLPAR)  ' in MB'                          */
 /* rec.1= '       at ' time_MaxRealLPAR                            */
    temp=MinQW0225_REALAVAIL*4096 / 1048576      /* in MB*/
    rec.1= 'Min Real Storage available for LPAR : ' MinQW0225_REALAVAIL,
                'Frames --' f2mb(MinQW0225_REALAVAIL) ' MB'
    call LOGW
    rec.1= '       at ' Date_MinQW0225_REALAVAIL time_MinQW0225_REALAVAIL
    call LOGW
    rec.1= ' '
    call LOGW
    rec.1= 'Max Aux Storage used by DB2  :' MaxDB2AuxUse ' Frames --',
           f2mb(MaxDB2AuxUse)        ' MB'
    call LOGW
    rec.1= '       at ' DateMaxDB2AuxUse timeMaxDB2AuxUse
    call LOGW
  end
return
init_var:
  if vsm='Y' then
      do
           MaxND=0
           MinAS=999999999999999
           MinTS=999999999999999
           MaxTF=0
           MaxThdSee =0
           MaxThdComp=0
           MaxThdComp2=0
           MinThdSee =999999999999999
           MinThdComp=999999999999999
           MinThdComp2=999999999999999
           MaxReal4K_dbm1=0
           MinReal4K_dbm1=999999999999999
           MaxReal4K_dist=0
           MinReal4K_dist=999999999999999
           MinQW0225_REALAVAIL=999999999999999
        /* MaxRealLPAR = 0 */
           MaxDB2AuxUse = -1
      end
  /* init counters */
  Old_QBSTGET = 0
  Old_QBSTRIO = 0
  Old_QTDSDRN = 0
  Old_QTPCCT  = 0
  Old_QWSDCKPT= 0
  Old_QXSTFND = 0
  Old_QXSTNFND= 0
  Old_QXSTIPRP= 0
  Old_QXSTNPRP= 0
  Old_QBSTDSO = 0
  Old_QBSTIMW = 0
  Old_QBSTWIO = 0
  Old_QBSTRPI = 0
  Old_QBSTWPI = 0
  Old_QBSTPIO = 0
  Old_QBSTMAX = 0
  Old_QBSTWFD = 0
  Old_QBSTWFF = 0
  Old_QBSTCIO = 0
  Old_QBSTDIO = 0
  Old_QBSTLIO = 0
  Old_QBSTSIO = 0

  Old_QJSTBFFL  = 0

  Old_QISTRLLM  = 0
  Old_QISTRPDM  = 0
  Old_QISTCOLS  = 0
  Old_QISTWFP1  = 0
  Old_QISTWFP2  = 0

  Old_Q3STSIGN = 0
  Old_Q3STTERM = 0
  Old_Q3STCTHD = 0
  Old_Q3STPREP = 0
  Old_Q3STCOMM = 0
  Old_Q3STABRT = 0


  Old_MstrTcb =       0
  Old_MstrSrb =       0
  Old_MstrpSRB=       0
  Old_MstrpSRB_Ziip = 0
  Old_dbm1Tcb =       0
  Old_dbm1srb =       0
  Old_dbm1pSRB=       0
  Old_dbm1pSRB_Ziip = 0
  Old_irlmTcb =       0
  Old_irlmsrb =       0
  Old_irlmpSRB=       0
  Old_irlmpSRB_Ziip = 0
  Old_distTcb =       0
  Old_distsrb =       0
  Old_distpSRB=       0
  Old_distpSRB_Ziip = 0


  /* compteurs input/output */
  reco= 0
  reci= 0
  recs= 0

  min_time ='26:00:00'
  Max_time ='ZZ:00:00'
  min_date ='20990101'
  Max_date ='19700101'
  return

FLOOR: procedure
parse arg F
return TRUNC(F) - (F < 0) * (F <> TRUNC(F))

CEIL: procedure
parse arg C
return TRUNC(C) + (C > 0) * (C <> TRUNC(C))
/* convert 4K frames to MB */
f2mb:
 arg num
 num = format(num*4/1024,,2)
 return num
/* convert bytes to MB */
b2mb:
 arg num
 num = format(num/1048576,,0)
 return num
/*========================================== */
/* Set SMF data set name , depending on lpar */
/*========================================== */
SetSmfDs:
  oufl = 'systmp.wsyngud.smfexta'
  Select
       When lpar  = 'SUD2' then
            do
                ssid='DBAP'
            end
       When lpar  = 'XX10' then
            do
                ssid='DB2B'
            end
       When lpar  = 'LIM'   then
            do
                ssid='DBP1'
            end
       When lpar  = 'CTR'   then
            do
                ssid='DB2I'
            end
       When lpar  = 'LIM2' then
            do
                ssid='DBP2'
            end /* end Lpar XX10 Sofinco */
       When lpar  = 'LIM3' then
            do
                ssid='DBP3'
            end /* end Lpar XX10 Sofinco */
       When lpar  = 'LIM4' then
            do
                ssid='DBP8'
            end /* end Lpar XX10 Sofinco */
       When lpar  = 'MVSA' then
            do
                ssid='DB2P'
            end /* end Lpar CRPP  */
       When lpar  = 'IPO4' then
            do
                ssid='DSN2'
            end /* end Lpar  Prod CACIB */
       When lpar  = 'ZPR1' then
            do
                ssid='DB2E'
            end /* end Lpar  Prod CASA  */
       When lpar  = 'PROD' then
            do
                clnt='CAAGIS'
            end /* end Lpar  Prod CAAG  */
       Otherwise
            do
               say 'Lpar not processed - End of program'
               exit(0)
            end
  end   /* End select */
  return
init_summary:
       sum_MstrTcb      = dif_MstrTcb
       sum_MstrSrb      = dif_MstrSrb
       sum_MstrpSRB     = dif_MstrpSRB
       sum_MstrpSRB_Ziip =  dif_MstrpSRB_Ziip
       sum_dbm1Tcb      = dif_dbm1Tcb
       sum_dbm1Srb      =  dif_dbm1Srb
       sum_dbm1pSRB     =  dif_dbm1pSRB
       sum_dbm1pSRB_Ziip = dif_dbm1pSRB_Ziip
       sum_IrlmTcb      =  dif_IrlmTcb
       sum_IrlmSrb      =  dif_IrlmSrb
       sum_IrlmpSRB     =  dif_IrlmpSRB
       sum_IrlmpSRB_Ziip =  dif_IrlmpSRB_Ziip
       sum_DistTcb   =  dif_DistTcb
       sum_DistSrb   =  dif_DistSrb
       sum_DistpSRB  =  dif_DistpSRB
       sum_DistpSRB_Ziip =  dif_DistpSRB_Ziip
       sum_Q3STCTHD  =  dif_Q3STCTHD /* cr threads*/
       sum_Q3STSIGN  =  dif_Q3STSIGN /* Signon  */
       sum_Q3STTERM  =  dif_Q3STTERM /* Terminate*/
       sum_Q3STPREP  =  dif_Q3STPREP /* commit ph1*/
       sum_Q3STCOMM  =  dif_Q3STCOMM /* Commit Ph 2*/
       sum_Q3STABRT  =  dif_Q3STABRT /* Aborts */
       Max_Q3STHWIB = Q3STHWIB
       Max_Q3STHWIF = Q3STHWIF
       Max_Q3STHWCT = Q3STHWCT
       Max_QTDSOPN  = QTDSOPN
       SUm_QWSDCKPT=  dif_QWSDCKPT  /* Checkpoints */
       SUm_QXSTFND =  dif_QXSTFND   /* Prepare     */
       SUm_QXSTNFND=  dif_QXSTNFND
       SUm_QXSTIPRP=  dif_QXSTIPRP
       SUm_QXSTNPRP=  dif_QXSTNPRP
       Sum_QTDSDRN =  dif_QTDSDRN   /* Drain Close */
       Sum_QTPCCT  =  dif_QTPCCT    /* RWRO switch */
       SUm2_QBSTDSO =  dif_QBSTDSO   /* Open DS*/
       sum2_QBSTGET = dif_QBSTGET /* gp */
       sum2_QBSTRIO = dif_QBSTRIO /* sync read */
       sum2_QBSTIMW = dif_QBSTIMW /* Immed. write */
       sum2_QBSTWIO = dif_QBSTWIO /* Async Write */
       sum2_QBSTRPI = dif_QBSTRPI /* Async Write */
       sum2_QBSTWPI = dif_QBSTWPI /* Async Write */
       sum2_QBSTPIO = dif_QBSTPIO /* Seq Pref. IO */
       sum2_QBSTMAX = dif_QBSTMAX
       sum2_QBSTWFD = dif_QBSTWFD
       sum2_QBSTWFF = dif_QBSTWFF
       sum2_QBSTCIO = dif_QBSTCIO /* Castout IO */
       sum2_QBSTDIO = dif_QBSTDIO /* Dyn Pr IO */
       sum2_QBSTLIO = dif_QBSTLIO /* Lst Pr IO */
       sum2_QBSTSIO = dif_QBSTSIO /* SIO */
       Max_QDSTQMIT = QDSTQMIT
       Max_QDSTHWAT = QDSTHWAT
       Max_QDSTHWDT = QDSTHWDT
       Max_QDSTMIN2 = QDSTMIN2
       Max_QW0225AT = QW0225AT
       min_Thdcomp  = Thdcomp
       min_Thdcomp2 = Thdcomp2
       Max_TotalRealUsedByDB2 = TotalRealUsedByDB2
       Max_TotalAuxlUsedByDB2 = TotalAuxlUsedByDB2
       min_QW0225_REALAVAIL = QW0225_REALAVAIL
       Max_QW0225RG         = QW0225RG /* Region Size extended */
       Min_QW0225AV         = QW0225AV
       sum_QISTCOLS=  dif_QISTCOLS /* Cols not optimized*/
       sum_QISTWFP1=  dif_QISTWFP1 /* 32KbUsed4Pref.*/
       sum_QISTWFP2=  dif_QISTWFP2 /* 4KbUsed32Prf*/
       sum_QJSTBFFL=  dif_QJSTBFFL /* Log created*/
  return
DSNDQWSD:
    /* Nbr of checkpoints cumulative value */
    QWSDCKPT = C2D(SUBSTR(INPUT_REC,OFFSET,4))
 return

Check_counters:
    /* Workfiles */
    if sum2_QBSTMAX > 0 then do
           temR=1
           rec.1= 'Workfile Not Created NoBuf QBSTMAX',
             sm100sid'/'sm100ssi '@'Old_Hour Sum2_QBSTMAX
           call logW
    end
    if sum2_QBSTWFD > 0 then do
           temR=1
           rec.1= 'Workfile Rejected NoBuf QBSTWFD',
             sm100sid'/'sm100ssi '@'Old_Hour Sum2_QBSTWFD
           call logW
    end
    if sum2_QBSTWFF > 0 then do
           temR=1
           rec.1= 'Merge Pass degraded Low Buf QBSTWFF',
             sm100sid'/'sm100ssi '@'Old_Hour Sum2_QBSTWFF
           call logW
    end
    /* Only for SUD2 */
    if lpar = 'SUD2'   then
    do
        SumBP_SUD2_all = sum2_QBSTGET + SumBP_SUD2_all
        /* record Max getpage */
        if  sum2_QBSTGET > Max_SUD2_gp then do
                Max_SUD2_gp = sum2_QBSTGET
                Max_SUD2_gp_hour = Old_Hour
            end
        /* record activity between 9-18 */
        if (Old_Hour > '08' & Old_Hour < '19') then
             do
               SumBP_SUD2 = sum2_QBSTGET + SumBP_SUD2
               if sum2_QBSTGET < 1000000 then,
                      SUD2_BpInact = SUD2_BpInact + 1
             end
        return
    end
    /* Global Dynamic Stmt cache hit ratio > 90% */
 /* Hit = Sum_QXSTFND / (Sum_QXSTFND+Sum_QXSTNFND + 0.01)
    if Hit < 0.90 then
             do
               rec.1= 'Warning : Global Dyn. Cache Hit < 90%',
                  format(Hit,3,2) ' @' run_fmt_time
               call logw
               retcode=4
             end
    /* Local  Dynamic Stmt cache hit ratio > 70% */
    /* Source Optimizing DB2 System Performance using db2 statistics*/
    Hit = Sum_QXSTNPRP/ (Sum_QXSTNPRP + Sum_QXSTIPRP + 0.01)
    if Hit = 0   then do
           if tsaylocal=0 then do
             rec.1= 'Warning : Local Dyn. Cache probably not used'
             call LOgw
             tsayLocal = 1
           end
    end
    else if Hit < 0.70 then
             do
               rec.1= 'Warning : Local Dyn. Cache Hit < 70%',
                  format(Hit,3,2) ' @' run_fmt_time
               call logw
               retcode=4
             end
    */
    if (sum_dbm1Tcb*3) > sum_dbm1Srb & sum_dbm1Tcb > 100 then do
     rec.1= 'DBM1 TCB time too high vs DBM1 SRB ',
            'Hour/DBM1TCB/DBM1SRB ' Old_Hour sum_dbm1TCB sum_dbm1SRB
     call LOGW
    end

    if sum_QWSDCKPT > 13             then  do
     rec.1= 'Checkpoint frequency too high, Max should be 1/ 5mn',
            'Hour/Checkpoints '     Old_Hour sum_QWSDCKPT
     call LOGW
    end

    if sum_QTDSDRN  > 1 & sum_dbm1Tcb > 100 then do
     rec.1= 'DSMax reached ',
            'Hour/DrainClose '     Old_Hour sum_QTDSDRN
     call LOGW
    end

    if sum_QTPCCT   > 900 sum_dbm1Tcb > 100 then do
     rec.1= 'RWRO Switch too high (15/mn is ok)',
            'Hour/ROSwitch   '     Old_Hour sum_QTPCCT
     call LOGW
    end

    if (sum2_QBSTRPI + sum2_QBSTWPI) >  100 then do
     rec.1=   'Page In for RW observed ',
        'Hour/PageIn R/PageInWrite' Old_Hour sum2_QBSTRPI sum2_QBSTWPI
     call LOGW
    end

    /* Bypassed columns - Invalid Select Procedure */
    if (sum_QISTCOLS )               >  500 then do
     temR=1
     rec.1= 'Not optimized SProc observed',
        'Hour/Number              '  Old_Hour sum_QISTCOLS
     call LOGW
    end

    if (Max_QDSTMIN2+Max_QW0225AT)   >  min_ThdComp ! ,
       (Max_QDSTMIN2+Max_QW0225AT)   >  min_ThdComp2  then do
     rec.1= 'DBAT + AlliedThreads > Theoric Minimum Thread Number',
        'Hour/DBAT/Allied/min_ThdComp/min_ThdComp2 '
     call LOGW
     rec.1= Old_Hour Max_QDSTMIN2 Max_QW0225AT min_ThdComp min_ThdComp2
     call LOGW
    end
    /* GBP counters */
      h=1
      do while h <= nbGBP
         i = GBPList.h
         h=h+1
         if SumHr_QBGLWA.i> 0    then
             do
                temR=1
                rec.1= 'GBP' i 'Write Around happened',
                  sm100sid'/'sm100ssi '@'Old_Hour SumHr_QBGLWA.i
                call logW
             end
         if SumHr_QBGL2F.i> 0    then
             do
                temR=1
                rec.1= 'GBP' i 'Write SecGBP NoStorage',
                  sm100sid'/'sm100ssi '@'Old_Hour SumHr_QBGL2F.i
                call logW
             end
         if SumHr_QBGLWF.i > 0    then
             do
                temR=1
                rec.1= 'GBP' i 'Write GBP NoStorage',
                  sm100sid'/'sm100ssi '@'Old_Hour SumHr_QBGLWF.i
                call logW
             end

          SumHr_QBGLWF.i=0
          SumHr_QBGL2F.i=0
          SumHr_QBGLWA.i=0
      end  /* End do */

    return
LOGW:
     say rec.1
     if temR=0 then return /* No file report if not set */
     "EXECIO 1 DISKW OUFw  (STEM rec. "
     temR=0 /* No file report is the default */
     return
/* for SUD2 */
LOGW2:
     say rec.1
     "EXECIO 1 DISKW OUFs2 (STEM rec. "
    return
/* Report dataset on output */
CrOutput:
    ope = 1
    /* caagis ssid forced to some value */
    if clnt = 'CAAGIS' then
    do
          if sm100ssi = 'DBPR' ! sm100ssi = 'DBAP'  then
          do
              lpar='SUDM'
              ssid='DBPR'
          end
          if sm100ssi = 'DB2I' ! sm100ssi = 'DB2V'  then
          do
              lpar='SUDB'
              ssid='DB2I'
          end
    end
    oufL = "'" !! hlq !! '.reportS.' !! lpar !! '.' !! ssid !! "'"
      X=outtrap(tmp.)
      "DELETE" oufL "PURGE"
      X=outtrap(off)
    say 'Allocate' oufL
    /* if with header */
       OPT2 = 'H'
    if OPT2 = 'H' then
      "ALLOC FI(OUFL) DA("oufL") NEW CATALOG REUSE" ,
      "LRECL(900) RECFM(V B) TRACKS SPACE(15,15)"
    else
      "ALLOC FI(OUFL) DA("oufL") NEW CATALOG REUSE" ,
      "LRECL(500) RECFM(V B) TRACKS SPACE(15,15)"
    rcalloc = rc
    if rcalloc <> 0 then Do
         say "**********************************************"
         say "   Error allocating report file" rcalloc
         say "   Abnormal end  "
         say "**********************************************"
         Exit 8
    end
/* WRITE report header */
      OPT2 = 'H'
   if OPT2 = 'H' then
    CALL write_header
/* Report warning messages  */
oufw = "'" !! hlq !! '.reportsw.' !! lpar !!'.' !! ssid !! "'"
X=OUTTRAP(TMP.)
"DELETE" oufw "PURGE"
X=OUTTRAP(OFF)
"ALLOC FI(OUFw) DA("oufw") NEW CATALOG REUSE" ,
"LRECL(80) RECFM(F B) TRACKS SPACE(5,5) RELEASE"
rcalloc = rc
if rcalloc <> 0 then Do
     say "**********************************************"
     say "   Error allocating report warnings file" rcalloc
     say "   Abnormal end  "
     say "**********************************************"
     Exit 8
end

/* Only SUD2 report BP usage Generate ALTER BP command */
if lpar = 'SUD2' & temX=0 then
do
  temX=1
  oufs2= "'" !! hlq !! '.reportsw.alrt2' !! "'"
  say 'Output to' oufs2
  X=OUTTRAP(TMP.)
  "DELETE" oufs2 "PURGE"
  x=OUTTRAP(OFF)
  "ALLOC FI(OUFs2) DA("oufs2") NEW CATALOG REUSE" ,
  "LRECL(80) RECFM(F B) TRACKS SPACE(2,2) RELEASE"
  rcalloc = rc
  if rcalloc <> 0 then Do
    say "**********************************************"
    say "   Error allocating report warnings bp file" rcalloc
    say "   Abnormal end  "
    say "**********************************************"
    Exit 8
  end
end /* SUD2*/
rec.1= ' '
call logw
rec.1= '*** Processing for Subsys ***' ssid lpar
call logw
return
DSNDQXST:
    /*************************************************/
    /*  RDS STATISTICS BLOCK  DSNDQXST               */
    /*************************************************/
    /* Fields from IFCID002 : cumulative */
    /* calculate difference between interval */
    offset=offset+4
    /* eye catcher */
    eyec     = SUBSTR(INPUT_REC,OFFSET,4)
    if ( eyec     <> 'QXST' ) then
                  do
                      say 'offset=' offset
                      eyec = SUBSTR(INPUT_REC,1,100)
                      say 'eyec' eyec
                      say 'DSNDQXST eye catcher not met, error'
                      exit(8)
                  end
    offset  =  offset + 4
    /* Selects     */
    QXSELECT = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /* Inserts     */
    QXINSRT  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /* Update      */
    QXUPDTE  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /* Delete      */
    QXDELET  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8 * 20
    /* Fetch       */
    QXFETCH  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8 * 14
    /*---*/
    /*#RID List failed No storage */
    QXNSMIAP = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# Failed Limit exceeded */
    QXMRMIAP = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8*31
    /*# Short Prepare */
    QXSTFND  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# Full  Prepare */
    QXSTNFND  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# Implicit Prepare = FULL prepare */
    QXSTIPRP  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# Avoided  Prepare */
    QXSTNPRP  = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# Stmt discarded - MaxKEEPD */
    QXSTDEXP  = C2D(SUBSTR(INPUT_REC,offset,8))
    /* (...) */
    offset  =  offset + 8*61
    /*# RID list Overflowed to Workfile No Storage */
    QXWFRIDS = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# RID list overflowed to wKk Limit Exceeded   */
    QXWFRIDT = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# RID list append for a hybrid join was interrupt No Storage*/
    QXHJINCS = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
    /*# RID list append for a hybrid join Limit exceeded*/
    QXHJINCT = C2D(SUBSTR(INPUT_REC,offset,8))
    offset  =  offset + 8
return
DSNDQXST0:
 /* say '!!! Record' reci 'no DSNDQXST data' */
    QXSELECT = 0
    QXINSRT  = 0
    QXUPDTE  = 0
    QXDELET  = 0
    QXFETCH  = 0
    QXNSMIAP = 0
    QXSTFND  = 0
    QXSTNFND = 0
    QXSTIPRP = 0
    QXSTNPRP = 0
    QXSTDEXP = 0
    QXWFRIDS = 0
    QXWFRIDT = 0
    QXHJINCS = 0
    QXHJINCT = 0
    QXMRMIAP = 0
return
/*-----------------------------------------*/
/* Specific for lpar SUD2 : Check BP usage */
/*-----------------------------------------*/
SUD2_report_bp_usage:
  /* report usage activity */
  rec.1= ' '
  call LOGW
  rec.1 = 'BP Usage report :'
  call LOGW
  /* compute average usage */
  SUD2avg_bp_all  = SumBP_SUD2 % 24
  rec.1 = ,
         'SUD2: ' ssid 'has BP inact - avg gp/h :' SUD2avg_bp_all
  call LOGW
  rec.1 = ,
         '              Max gp/h observed :' Max_SUD2_gp ' at ',
                                             Max_SUD2_gp_hour
  call LOGW
  rec.1 = ,
         '              avg gp/h office hours:' SUD2avg_bp
  call LOGW
  rec.1='  SUD2 avg getpage for 00:00-2359   :' SUD2avg_bp_all
  call logW
  SUD2avg_bp = SumBP_SUD2 % 10
  rec.1='  SUD2_BpInact hours from 9:00-18:00:' SUD2_BpInact
  call logW
  rec.1='  SUD2avg getpage during 9:00-18:00 :' SUD2avg_bp
  call logW
  /********************/
  /*  SET VPSIZE PART */
  /********************/

  /* important activity observed all day */
  if su2avg_bp_all > 2000000 &  bp0_vpsize < 55000 then
  do
        rec.1 ='BP probably small vs. observed activity, recommend :'
        call LOGW2
        rec.1 ='DSN SYSTEM('ssid')'
        call LOGW2
        rec.1 ='-ALTER BPOOL(BP0) VPSIZE(300000)'
        call LOGW2
        rec.1 ='-ALTER BPOOL(BP1) VPSIZE(100000)'
        call LOGW2
        return
  end

  /* Max gp/hour high at somes time => higher a little */
  if Max_SUD2_gp > 5000000 & bp0_vpsize < 55000 then
     do
        rec.1 ='DSN SYSTEM('ssid')'
        call LOGW2
        rec.1 ='-ALTER BPOOL(BP0) VPSIZE(100000)'
        call LOGW2
        return
     end
  /* Not enough activity */
  if Max_SUD2_gp < 5000000 & bp0_vpsize > 55000 then
     do
          rec.1 ='DSN SYSTEM('ssid')'
          call LOGW2
          rec.1 ='-ALTER BPOOL(BP0) VPSIZE(50000)'
          call LOGW2
          return
     end
return
/*---------------------------------------*/
/* Date functions from Chuck Meyer paper */
/*---------------------------------------*/
/* yyyymmdd => weekday */
DAT_S2DOW: Procedure
Parse Arg 1 yyyy +4 mm +2 dd +2 .
f = yyyy + (mm-14)%12
w = ((13*(mm+10-(mm+10)%13*12)-1)%5+dd+77 ,
+ 5 * (f - f%100*100)%4 + f%400 - f%100*2) //7
Return WORD('Sun Mon Tue Wed Thur Fri Sat',w+1)
/*---------------------*/
/* Is this leap year ? */
/*---------------------*/
LY?: Procedure
Parse Arg 1 y +4
Return ((y//4)=0)
/*---------------------*/
/* yyyyddd => yyyymmdd */
/*---------------------*/
DAT_MVS2SD: Procedure
Parse Value REVERSE(arg(1)) With 1 j +3 y
Parse Value REVERSE(j y) With y j
If LENGTH(y) = 2 Then y = YY2YYYY(y)
months = '31' (28 + LY?(y)) ,
'31 30 31 30 31 31 30 31 30 31'
Do m = 1 To 12 While j > WORD(months,m)
j = j - WORD(months,m)
End
Return RIGHT(y,4,0) !! RIGHT(m,2,0) !! RIGHT(j,2,0)
/********************************************/
/* Display list of BP with low Prefetch Qty */
/********************************************/
DisplayPref:
    temR=1
    rec.1= 'Lpar:' sm100sid  'SSID:' sm100ssi
    call logW
    temR=1
    rec.1= 'List of Bufferpols with a low Prefetch Quantity'
    call logW
    i=1
    do while i <= nbBP
       temR=1
       j=BPList.i
       rec.1= j ListPrefLow.j
       if  ListPrefLow.j > 0 then
                        call logW
       i=i+1
    end

No comments:

Post a Comment