zOs/REXX.O08/DB2RCEST

/*---------------------REXX-------------------------------------------*/
/* DB2RCEST DB2 Recovey Estimator                                     */
/* Dises Programm gibt eine Schätzung, wie lange der Recovery eines   */
/* Pagesets etwa laufen wird.                                         */
/*                                                                    */
/* Für die folgenen Spaces sind die ermittelten Zeiten sicher falsch  */
/* (zu kurz):                                                         */
/*   DSNDB01.DBD01, DSNDB01.SPT01, DSNDB01.SCT02, DSNDB01.SYSLGRNX,   */
/*   DSNDB01.SYSUTILX, DSNDB06.SYSCOPY, DSNDB06.SYSGROUPS             */
/* Diese Spaces müssen alle Logs in ihrer ganzen Länge seit der       */
/* letzten Image Copy lesen.                                          */
/*                                                                    */
/* Input:  -Output aus dem DB2 REPORT Utility                         */
/*         -BSDS aller Group Members (StartRBA Activlog, highest      */
/*          written RBA)                                              */
/*                                                                    */
/* Output:  approximative Recoveryzeit                                */
/*                                                                    */
/* 04.08.2004 erstellt durch B.Dudle                                  */
/* 13.08.2004 BDU div. Anpassungen                                    */
/* 18.10.2005 BDU Anpassung an PT/A                                   */
/* 21.02.2006 BDU total überarbeitet                                  */
/*--------------------------------------------------------------------*/

/*--- initialisieren -------------------------------------------------*/

   numeric digits 15;
   z1=0;  z2=0;  z3=0;
   cc=0;
   out.="";  out.0=0;  o=0;
   group=left("",4);
   dat=translate(date('E'),".","/");
   dat=insert("20",dat,pos(".",dat,4));
   tim=time('N');

   rz=sysvar(sysnode);
   select;
      when (rz = 'RZ0');  then do;
         mount=150;                       /* tape mount: Sek.         */
         resto=2.00E+05;                  /* restore: Pages / 60 Sek. */
         logap=8.00E+08;                  /* logappl: Bytes / 60 Sek. */
      end;
      when (rz = 'RZ1');  then do;
         mount=150;                       /* tape mount: Sek.         */
         resto=2.00E+05;                  /* restore: Pages / 60 Sek. */
         logap=8.00E+08;                  /* logappl: Bytes / 60 Sek. */
      end;
      when (rz = 'RZ2');  then do;
         mount=90;                        /* tape mount: Sek.         */
         resto=2.00E+05;                  /* restore: Pages / 60 Sek. */
         logap=8.00E+08;                  /* logappl: Bytes / 60 Sek. */
      end;
      when (rz = 'RZ4');  then do;
         mount=90;                        /* tape mount: Sek.         */
         resto=2.00E+05;                  /* restore: Pages / 60 Sek. */
         logap=8.00E+08;                  /* logappl: Bytes / 60 Sek. */
      end;
      when (rz = 'RR2');  then do;
         rz='RZ2';                        /* change für PT/A          */
         mount=90;                        /* tape mount: Sek.         */
         resto=2.00E+05;                  /* restore: Pages / 60 Sek. */
         logap=8.00E+08;                  /* logappl: Bytes / 60 Sek. */
      end;
      when (rz = 'RR4');  then do;
         rz='RZ4';                        /* change für PT/A          */
         mount=90;                        /* tape mount: Sek.         */
         resto=2.00E+05;                  /* restore: Pages / 60 Sek. */
         logap=8.00E+08;                  /* logappl: Bytes / 60 Sek. */
      end;
      otherwise;  nop;
   end;

/*--- Output aus Report Utility einlesen und in Tablellen speichern --*/

   address tso "execio * diskr REPORT (stem rpt. open finis";
   do r=1 to rpt.0;
      select;
         when (pos("DSNU050I",rpt.r) > 0); then do;  /* DSNUM request */
            p=pos("REPORT RECOVERY TABLESPACE",rpt.r)+26;
            do while (substr(rpt.r,p,1) = " "); p=p+1; end;
            p1=p;
            do while (substr(rpt.r,p1,1) <> " "); p1=p1+1; end;
            space=substr(rpt.r,p,p1-p);
            p=pos("DSNUM",rpt.r);  part=0;
            if (p > 0); then do;
               p=p+5;
               do while (substr(rpt.r,p,1) = " "); p=p+1; end;
               do while (substr(rpt.r,p,1) <> " ");
                  part=part*10+substr(rpt.r,p,1);  p=p+1;
               end;
            end;
            else nop;
         end;
         when ((pos("DSNU054I",rpt.r)>0) | (pos("DSNU007I",rpt.r)>0));
            then do;                                 /* TS not found  */
            o=o+1;  out.o=group right(dat tim,75);
            o=o+1;  out.o=left("",80,"-");
            o=o+1;  out.o=" ";  out.0=o;
            address tso "execio * diskw PRINT  (stem out. open";
            address tso "execio * diskw PRINT  (stem rpt. finis";
            cc=8;
            exit cc;
         end;
         when (pos("IC TYPE =",rpt.r) > 0); then do; /* image copies  */
            r1=r;  z1=z1+1;
            p=pos("IC TYPE =",rpt.r1);
            ictype.z1=substr(rpt.r1,p+11,1);
            if (ictype.z1 = "F" | ictype.z1 = "I"); then do;
               p=pos("DSNUM    =",rpt.r1);
               p=p+10;  dsnum.z1=0;
               do while (substr(rpt.r,p,1) = " "); p=p+1; end;
               do while (substr(rpt.r,p,1) <> ",");
                  dsnum.z1=dsnum.z1*10+substr(rpt.r,p,1);  p=p+1;
               end;
               if (dsnum.z1 = part | dsnum.z1 = 0); then do;
                  p=pos("START LRSN =",rpt.r1);
                  slrsn.z1=x2d(substr(rpt.r1,p+12,12));
                  r1=r1+1;
                  p=pos("IC BACK =",rpt.r1);
                  icback.z1=substr(rpt.r1,p+10,2);
                  p=pos("DEV TYPE  =",rpt.r1);
                  devtyp.z1=substr(rpt.r1,p+12,4);
                  r1=r1+2;
                  p=pos("COPYPAGESF =",rpt.r1);
                  copypage.z1=0;
                  copypage.z1=trunc(strip(substr(rpt.r1,p+13,14)));
                  r1=r1+2;
                  p=pos("DSNAME    =",rpt.r1);
                  group=strip(substr(rpt.r1,p+12,4)); /* group name   */
                  p=pos("MEMBER NAME =",rpt.r1);
                  memb=strip(substr(rpt.r1,p+14,4));  /* member name  */
               end;
               else do;
                  z1=z1-1;
               end;
            end;
            else do;
               z1=z1-1;
            end;
         end;
         when (pos("UCDATE    ",rpt.r) > 0); then do; /* log ranges   */
            r2=r+1;
            do while (substr(rpt.r2,24,12) <> " ");
               z2=z2+1;
               srba.z2=x2d(substr(rpt.r2,24,12),14);
               erba.z2=x2d(substr(rpt.r2,39,12),14);
               slrsns.z2=x2d(substr(rpt.r2,54,12),14);
               elrsns.z2=x2d(substr(rpt.r2,69,12),14);
               mbid.z2=x2d(substr(rpt.r2,99,4),4);
               if (srba.z2 = erba.z2); then do;       /* not a range  */
                  z2=z2-1;
               end;
               else nop;
               r2=r2+1;
            end;
         end;
         otherwise nop;
      end;
   end;
   slrsn.0=z1;  srba.0=z2;
/* say "---copy table";
   do z1=1 to slrsn.0;
     say right(d2x(slrsn.z1),12) devtyp.z1 copypage.z1;
   end;
   say "---syslgrnx table";
   do z2=1 to srba.0;
      say right(d2x(srba.z2),12),
          right(d2x(erba.z2),12),
          right(d2x(slrsns.z2),12),
          right(d2x(elrsns.z2),12),
          right(d2x(mbid.z2),12);
   end;
*/
/*--- Image Copies Set selektieren -----------------------------------*/

   do z1=1 to slrsn.0-1;                      /* sortieren            */
      do z11=z1+1 to slrsn.0;
         select;
         when (slrsn.z1 > slrsn.z11);  then do;
            sl=slrsn.z1;     slrsn.z1=slrsn.z11;        slrsn.z11=sl;
            it=ictype.z1;    ictype.z1=ictype.z11;      ictype.z11=it;
            ib=icback.z1;    icback.z1=icback.z11;      icback.z11=ib;
            dv=devtyp.z1;    devtyp.z1=devtyp.z11;      devtyp.z11=dv;
            ds=dsnum.z1;     dsnum.z1=devtyp.z11;       dsnum.z11=dv;
            cp=copypage.z1;  copypage.z1=copypage.z11;  copypage.z11=cp;
         end;
         when (slrsn.z1 = slrsn.z11);  then do;
            if (icback.z1 <> "  ");  then do;
               sl=slrsn.z1;   slrsn.z1=slrsn.z11;    slrsn.z11=sl;
               it=ictype.z1;  ictype.z1=ictype.z11;  ictype.z11=it;
               ib=icback.z1;  icback.z1=icback.z11;  icback.z11=ib;
               dv=devtyp.z1;  devtyp.z1=devtyp.z11;  devtyp.z11=dv;
               ds=dsnum.z1;   dsnum.z1=devtyp.z11;   dsnum.z11=dv;
               cp=copypage.z1;  copypage.z1=copypage.z11;
               copypage.z11=cp;
            end;
            else nop;
         end;
         otherwise nop;
         end;
      end;
   end;
   z1=1;                                      /* Duplikat eliminieren */
   do z11=z1+1 to slrsn.0;
      if (slrsn.z1 <> slrsn.z11); then do;
         z1=z1+1;
         slrsn.z1=slrsn.z11;
         ictype.z1=ictype.z11;
         icback.z1=icback.z11;
         devtyp.z1=devtyp.z11;
         dsnum.z1=devtyp.z11;
         copypage.z1=copypage.z11;
      end;
      else nop;
   end;
   slrsn.0=z1;

/* say "---copy table sortiert";
   do z1=1 to slrsn.0;
     say right(d2x(slrsn.z1),12),
         devtyp.z1,
         copypage.z1;
   end;
*/
/*--- highest written RBAs, oldest RBAs Active Log ermitteln ---------*/

   loadlib="DB2@."rz".P0.DSNLOAD";
   callmod="call '"loadlib"(DSNJU004)'";  upper callmod;
   cntl.1="MEMBER *";  cntl.0=1;  upper cntl.1;
   bsds="'"group"."memb".BSDS01'";  upper bsds;

   address tso "alloc  dd(SYSIN)  new space(1,1) tracks
     unit(VIO) dsorg(PS) blksize(800) lrecl(80) recfm(F B) reuse";
   address tso "execio * diskw SYSIN (stem cntl. open finis";

   address tso "alloc  dd(SYSPRINT)  new space(15,15) tracks
     unit(VIO) dsorg(PS) blksize(27875) lrecl(125) recfm(F B A) reuse";

   allcbsds="alloc f(GROUP) da("bsds") shr";
   address tso allcbsds;
   address tso callmod;
   address tso "free  f(GROUP)";
   address tso "free  f(SYSIN)";
   address tso "execio * diskr SYSPRINT (stem bsdslst. open finis";
   address tso "free  f(SYSPRINT)";
   h2=0;  z3=0;  z1=slrsn.0;  highlrsn=0;
   do h1=1 to bsdslst.0;
      select;
      when (pos("HIGHEST RBA WRITTEN",bsdslst.h1) > 0); then do;
         p=pos("HIGHEST RBA WRITTEN",bsdslst.h1);
         h2=h2+1;  highrba.h2=x2d(substr(bsdslst.h1,p+26,12),14);
      end;
      when (pos("HOST MEMBER NAME:",bsdslst.h1) > 0); then do;
         h3=h1+1;  p=pos("MEMBER ID:",bsdslst.h3);
         do h4=p+10 to 133 while (substr(bsdslst.h3,h4,1) = " ");
         end;
         himemb.h2=0;
         do while (substr(bsdslst.h3,h4,1) <> " ");
            himemb.h2=himemb.h2*10+substr(bsdslst.h3,h4,1);
            h4=h4+1;
         end;
      end;
      when (pos("ACTIVE LOG COPY 1",bsdslst.h1) > 0); then do;
         p=pos("ACTIVE LOG COPY 1",bsdslst.h1);  h3=h1+3;
         do while (pos("EMPTY DATA SET",bsdslst.h3) > 0);
            h3=h3+3;
         end;
         h4=h3+1;  z1=slrsn.0;
         activrba.h2=x2d(substr(bsdslst.h3,p+3,12),14);
         activlrsn.h2=x2d(substr(bsdslst.h4,p+5,12),14);
         do while(substr(bsdslst.h4,p+28,12) <> "............");
            elrsn=x2d(substr(bsdslst.h4,p+28,12),14);
            if (elrsn >= slrsn.z1);
            then do;
               z3=z3+1;
               srbalog.z3=x2d(substr(bsdslst.h3,p+3,12),14);
               erbalog.z3=x2d(substr(bsdslst.h3,p+26,12),14);
               slrsnlog.z3=x2d(substr(bsdslst.h4,p+5,12),14);
               elrsnlog.z3=elrsn;
               unitlog.z3="DISK";
               memblog.z3=himemb.h2;
               logtyp.z3="ACTIV";
            end;
            h3=h3+3;  h4=h3+1;
         end;
         z3=z3+1;
         srbalog.z3=x2d(substr(bsdslst.h3,p+3,12),14);
         erbalog.z3=x2d(substr(bsdslst.h3,p+26,12),14);
         slrsnlog.z3=x2d(substr(bsdslst.h4,p+5,12),14);
         elrsnlog.z3=max(slrsnlog.z3+1,slrsn.z1);
         unitlog.z3="DISK";
         memblog.z3=himemb.h2;
         logtyp.z3="ACTIV";
         highlrsn=max(highlrsn,elrsnlog.z3);
         h3=h3+3;  h4=h3+1;
      end;
      when (pos("ARCHIVE LOG COPY 1",bsdslst.h1) > 0); then do;
         h0=h1+1;  z1=slrsn.0;
         if (pos("NO ARCHIVE DATA SETS",bsdslst.h0) = 0); then do;
            p=pos("ARCHIVE LOG COPY 1",bsdslst.h1);  h3=h1+3;
            do while(pos("ACTIVE LOG COPY",bsdslst.h3) = 0);
               h4=h3+1;
               elrsn=x2d(substr(bsdslst.h4,p+28,12),14);
               if (elrsn >= slrsn.z1 & elrsn <= activlrsn.h2);
               then do;
                  z3=z3+1;
                  srbalog.z3=x2d(substr(bsdslst.h3,p+3,12),14);
                  erbalog.z3=x2d(substr(bsdslst.h3,p+26,12),14);
                  slrsnlog.z3=x2d(substr(bsdslst.h4,p+5,12),14);
                  elrsnlog.z3=x2d(substr(bsdslst.h4,p+28,12),14);
                  u=pos("UNIT=",bsdslst.h4);
                  unitlog.z3=strip(substr(bsdslst.h4,u+5,6));
                  memblog.z3=himemb.h2;
                  logtyp.z3="ARCHIV";
               end;
               h3=h3+4;
            end;
         end;
         else nop;
      end;
      otherwise nop;
      end;
   end;
   highrba.0=h2;  srbalog.0=z3;
/* say "---Logs";
   do z3=1 to srbalog.0
      say right(d2x(srbalog.z3),12)  right(d2x(erbalog.z3),12),
          right(d2x(slrsnlog.z3),12) right(d2x(elrsnlog.z3),12),
          unitlog.z3 right(memblog.z3,2) logtyp.z3;
   end;

   say "---highest LRSN:" d2x(highlrsn,12);
   say "---highest written RBA";
   do h2=1 to highrba.0;
      say "highest:" right(d2x(highrba.h2,12),12) right(himemb.h2,2);
   end;
*/
/*--- highest written RBAs nachführen in Logapply Ranges -------------*/

   z1=slrsn.0;
   do z2=1 to srba.0;
      if (erba.z2 = 0); then do;               /* SYSLGRNX open ?     */
         do h2=1 to highrba.0;
            if (mbid.z2 = himemb.h2); then do;
               erba.z2=highrba.h2;
               elrsns.z2=max(slrsns.z2+1,highlrsn,slrsn.z1);
            end;
            else nop;
         end;
      end;
      else nop;
   end;
/* say "---syslgrnx table ergänzt";
   do z2=1 to srba.0;
     say right(d2x(srba.z2),12),
         right(d2x(erba.z2),12),
         right(d2x(slrsns.z2),12),
         right(d2x(elrsns.z2),12),
         right(d2x(mbid.z2),12);
   end;
*/
/*--- Logapply Ranges ermitteln --------------------------------------*/

   do z3=1 to srbalog.0;                  /* archlog ranges berechnen */
      range.z3=0;
      do z2=1 to srba.0;
         if (mbid.z2 = memblog.z3);  then do;
            select;
               when (elrsnlog.z3 < slrsns.z2);
                  then nop;
               when (slrsnlog.z3 < slrsns.z2 & ,
                     elrsnlog.z3 <= elrsns.z2);
                  then do;
                     if (unitlog.z3 = "DISK"); then do;
                        range.z3=range.z3 + erbalog.z3 - srba.z2;
                     end;
                     else do;
                        range.z3=range.z3 + erbalog.z3 - srbalog.z3;
                     end;
               end;
               when (slrsnlog.z3 < slrsns.z2 & ,
                     elrsnlog.z3 > elrsns.z2);
                  then do;
                     if (unitlog.z3 = "DISK"); then do;
                        range.z3=range.z3 + erba.z2 - srba.z2;
                     end;
                     else do;
                        range.z3=range.z3 + erba.z2 - srbalog.z3;
                     end;
               end;
               when (slrsnlog.z3 >= slrsns.z2 & ,
                     elrsnlog.z3 <= elrsns.z2);
                  then do;
                     range.z3=range.z3 + erbalog.z3 - srbalog.z3;
               end;
               when (slrsnlog.z3 >= slrsns.z2 & ,
                     slrsnlog.z3 <= elrsns.z2 & ,
                     elrsnlog.z3 >  elrsns.z2);
                  then do;
                     range.z3=range.z3 + erba.z2 - srbalog.z3;
               end;
               otherwise;  nop;
            end;
         end;
      end;
   end;
/* say "---LOGS mit Ranges";
   do z4=1 to srbalog.0;
      say "srbalog:" d2x(srbalog.z4,12) ,
          "erbalog:" d2x(erbalog.z4,12) ,
          memblog.z4 unitlog.z4 logtyp.z4 range.z4;
   end;
*/
   z4=0;                                   /* Reduktion no ranges     */
   do z3=1 to srbalog.0;
      if (range.z3 > 0);  then do;
         z4=z4+1;
         srbalog.z4=srbalog.z3;    erbalog.z4=erbalog.z3;
         slrsnlog.z4=slrsnlog.z3;  elrsnlog.z4=elrsnlog.z3;
         memblog.z4=memblog.z3;    unitlog.z4=unitlog.z3;
         logtyp.z4=logtyp.z3;      range.z4=range.z3;
      end;
      else nop;
   end;
   srbalog.0=z4;
/* say "---benötigte Logs";
   do z3=1 to srbalog.0
      say right(d2x(srbalog.z3),12)  right(d2x(erbalog.z3),12),
          right(d2x(slrsnlog.z3),12) right(d2x(elrsnlog.z3),12),
          unitlog.z3 right(memblog.z3,2) logtyp.z3 range.z3;
   end;
*/
/*--- Bestimmen erforderliche Anzahl Cart Units ----------------------*/

   icunit=0;  lgunit=0;
   do z1=1 to slrsn.0;
      if (devtyp.z1 <> 3390);  then do;
         icunit=icunit+1;
      end;
   end;
   do z3=1 to srbalog.0;
      if (unitlog.z3 <> "DISK");  then do;
         lgunit=lgunit+1;
      end;
   end;
   lgvts=lgunit;
   lgunit=min(2,lgunit);
   cartunit=max(icunit,lgunit);

/*--- Berechnung der Recoverytime ------------------------------------*/

   icmount=icunit*mount;
   pages=0;
   do z1=1 to slrsn.0;
      pages=pages+copypage.z1;
   end;
   tmresto=icmount+trunc(pages*60/resto,0);

   apply=0;
   lgmount=min(1,lgunit)*mount;
   do z3=1 to srbalog.0;
      if (unitlog.z3 = "DISK"); then do;
         apply=apply+range.z3*60/logap;
      end;
      else do;
         apply=apply+max(mount,range.z3*60/logap);
      end;
   end;
   tmlgapp=trunc(apply,0);
   tmtot=tmresto+tmlgapp;
   tmtotmm=trunc(tmtot/60,0);
   tmtotss=tmtot-tmtotmm*60;

/*--- Print Resultate ------------------------------------------------*/

   z1=slrsn.0;
   o=o+1;  out.o=group right(dat tim,75);
   o=o+1;  out.o=left("",80,"-");
   o=o+1;  out.o=" ";
   o=o+1;  out.o="Annahmen:";
   o=o+1;  out.o=left("  mounts:",20) mount "Sek. / mount";
   o=o+1;  out.o=left("  restore:",20) format(resto,,,,2) ,
                 "Pages / Min.";
   o=o+1;  out.o=left("  logapply:",20) format(logap,,,,2) ,
                 "Bytes / Min.";
   o=o+1;  out.o=" ";
   o=o+1;  out.o="Pageset:            " space", PART/DSNUM:" part;
   o=o+1;  out.o="benötige Card Units:" format(cartunit,12,0);
   o=o+1;  out.o="Imagecopies:        " format(slrsn.0,12,0);
   o=o+1;  out.o="  Pages:            " format(pages,12,0);
   o=o+1;  out.o="  LRSN:             " right(d2x(slrsn.z1,12),12);
   o=o+1;  out.o="SYSLGRNX:           " format(srba.0,12,0);
   o=o+1;  out.o="Arch- und Activlogs:" format(srbalog.0,12,0);
   o=o+1;  out.o="Archlogs auf VTS:   " format(lgvts,12,0);
   o=o+1;  out.o="Recovery:";
   o=o+1;  out.o="  Restore:     " format(tmresto,17) "Sek.";
   o=o+1;  out.o="  Logapply:    " format(tmlgapp,17) "Sek.";
   o=o+1;  out.o=left("  ",36,"-");
   o=o+1;  out.o="  total:     " ,
                 right(tmtotmm,16)":"right(tmtotss,2,"0") "Min.";
   o=o+1;  out.o=copies("-",80);
   o=o+1;  out.o=" ";
   o=o+1;  out.o="SYSLGRNX Tabelle";
   o=o+1;  out.o="MEMBER" left("STARTRBA",12)  left("ENDRBA",12) ,
                          left("STARTLRSN",12) left("ENDLRSN",12);
   do z2=1 to srba.0;
      o=o+1;  out.o=right(mbid.z2,6) ,
                    d2x(srba.z2,12)    d2x(erba.z2,12) ,
                    d2x(slrsns.z2,12)  d2x(elrsns.z2,12);,
   end;
   o=o+1;  out.o=" ";
   o=o+1;  out.o="Log Tabelle";
   o=o+1;  out.o="MEMBER" left("STARTRBA",12)  left("ENDRBA",12) ,
                          left("STARTLRSN",12) left("ENDLRSN",12) ,
                          left("UNIT",4)       left("LOGTYP",6);
   do z3=1 to srbalog.0;
      o=o+1;  out.o=right(memblog.z3,6) ,
                    d2x(srbalog.z3,12)   d2x(erbalog.z3,12) ,
                    d2x(slrsnlog.z3,12)  d2x(elrsnlog.z3,12) ,
                    unitlog.z3  logtyp.z3;
   end;
   o=o+1;  out.o=left("",80,"=");
   out.0=o;
   address tso "execio * diskw PRINT (stem out.       open";
/* address tso "execio * diskw PRINT (stem rpt.";
   address tso "execio * diskw PRINT (stem bsdslst.";
*/ address tso "execio * diskw PRINT (                finis";
   exit cc;