zOs/REXX/VSAMCHK

$#@
$*(  vsamChk
         compare RTS with the VSAMs of a DB2 System
         report orphaned dataseets
             and differences between vsam huRba and RTS space
  25.11.14 Walter: partitionNr >= 1000, aber Instanz nur 1
$*)
$=wRBA = 1   $** with haRBA and huRRA, 0 = without (faster)
$=dbSys = DP4G
say timing() 'start vsamCheck' $dbSys f('%t E')
call sqlConnect $dbSys
numeric digits(20)
$<>
$<=[
with s as
(
  select s.dbName db , s.name sp, r.partition pa, s.name ts
      , s.partitions parts, s.pgSize pgSz, iPrefix, r.nActive act
    from sysibm.sysTableSpace s join sysibm.sysTableSpaceStats r
      on s.dbName = r.dbName and s.name = r.name
      join sysibm.sysTablePart p
          on s.dbName = p.dbName and s.name = p.tsname
              and r.partition = p.partition
         and s.dbId = r.dbId and s.psId = r.psid
 $**  where s.dbName = $"'$MAREC'"
  union all select i.dbName db , i.indexSpace sp, r.partition pa
      , s.name ts
      , s.partitions parts , i.pgSize pgSz, iPrefix, r.nActive act
    from sysibm.sysIndexes    i
      join sysibm.sysIndexSpaceStats r
        on i.creator = r.creator and i.name = r.name
           and i.dbId = r.dbId and i.isoBid = r.isoBid
      join sysibm.systables t
        on i.tbCreator = t.creator and i.tbName = t.name
      join sysibm.systableSpace s
        on t.dbName = s.dbName and t.tsName = s.name
      join sysibm.sysIndexPart p
        on i.creator = p.ixcreator and i.name = p.ixname
              and r.partition = p.partition
 $**  where i.dbName = $"'$MAREC'"
)
select strip(db) db, strip(sp) sp, pa, strip(ts) ts
      , parts, pgSz, strip(iPrefix) iPre, act
    from s
$@ if $dbSys == 'DVBP' then $@=[
    where not db in
         ( select db from s100447.telardrop
              where kind='disp req' and nm in ('disp07', 'disp08#2')
         )
$]
    order by 1, 2, 3
$]
call sql2St scanSqlIn2Stmt(), dbs
$<>
say timing() 'selected' m.dbs.0 'parts'
do dx=1 to m.dbs.0
    dy = 'DBS.'dx
    d1 = m.dy.db
    s1 = m.dy.sp
    t1 = m.dy.ts
    p1 = 0 + m.dy.pa
    n = d1'.'s1'#'p1
    m.s2x.d1.s1.p1 = dx
    m.dy.cDs = 0
    m.dy.hu  = 0
    m.dy.ha  = 0
    if \ datatype(m.dy.pgSz, 'n') then do
          say 'bad pgSize' m.dy.pgSz n
          m.dy.pgSz = 4
          end
    if \ datatype(m.dy.act, 'n') then do
          if m.dy.act == m.sqlNull then
              say 'rts null' m.dy.act n
          else
              say 'bad nActive ' m.dy.act n
          m.dy.act = 0
          m.dy.noRts = 1
          end
    end
say timing() 'check1' m.dbs.0 'parts'
m.bad.0 = 0
do dx=1 to m.dbs.0          $** check partitions
    dy = 'DBS.'dx
    d1 = m.dy.db
    s1 = m.dy.sp
    t1 = m.dy.ts
    p1 = 0 + m.dy.pa
    n = d1'.'s1'#'p1
    if s1 == t1 then do /* tablePart */
        if m.dy.parts <> 0 then do
            if p1 <= 0 | p1 > m.dy.parts then
                call err 'part' p1 'in' m.dy.parts 'parts ts' n
            else do px=1 to m.dy.parts
                if symbol('m.s2x.d1.s1.px') \== 'VAR' then
                    call err 'part' px 'missing in ts' n
                end
            end
        else if p1 <> 0 then
            call err 'part' p1 'in nopartitioned ts' n
        end
    else do
        px = m.dy.parts > 0
        if symbol('m.s2x.d1.t1.px') \== 'VAR' then
            call err 'ts' t1'.'px 'missing for ix' n
        if m.dy.parts <> 0 then do
            if p1 < 0 | p1 > m.dy.parts then
                call err 'part' p1 'in' m.dy.parts 'parts ix' n
            else if p1 <> 0 then do
                if symbol('m.s2x.d1.sp.0') == 'VAR' then
                    call err 'part' p1 '& 0 in' m.dy.parts 'parts ix' n
                if p1 > 1 & symbol('m.s2x.d1.s1.1') \== 'VAR' then
                    call err 'part 1 missing in ix' n
                px = p1-1
                if px > 0 & symbol('m.s2x.d1.s1.px') \== 'VAR' then
                    call err 'part' px 'missing in ix' n
                end
            end
        else if p1 <> 0 then
            call err 'part' p1 'in nopartitioned ix' n
        end
    end
say timing() 'check2' m.dbs.0 'parts'
call csiOpen csi, $dbSys'*.DSNDBD.**',
               , copies('XHARBADS XHURBADS', $wRBA)
cNoDb = 0
aUse = 0
aAlc = 0
nUse = 0
nAlc = 0
do c=0 while csiNext(csi, nx)
    if $wRBA then $@[
$** say c2x(m.nx.Xharbads) c2x(m.nx.Xhurbads) m.nx
    if m.nx.xhaRBAds == 'ffffffffffffffff'x ,
     | m.nx.xhuRBAds == 'ffffffffffffffff'x then do
        a1 = 0
        u1 = 0
        say 'bad rba' m.nx
        end
    else do
        a1 = c2d(m.nx.xharbads)
        u1 = c2d(m.nx.xhurbads)
        end
    aUse = aUse + u1
    aAlc = aAlc + a1
    $]
    ee = ''
    parse var m.nx with . '.' . '.' d1 '.' s1 '.' l5 '.' l6
    if translate(l5, 'I', 'J') \== 'I0001' then
        ee = 'l5'
    else if translate(l6, '000000000AAAA', '123456789BCDE') ,
            \== 'A000' then
        ee = 'l6'
    else do
        if \ datatype(translate(l6, '01234', 'ABCDE'), 'n') then do
            trace ?r
            say 'l6' l6 translate(l6, '01234', 'ABCDE')
            say m.nx
            end
        p1 = translate(l6, '01234', 'ABCDE') + 0
    $** say d1'?'s1'==>'m.nx
        if symbol('m.s2x.d1.s1.p1') == 'VAR' then
            dy = 'DBS.'m.s2x.d1.s1.p1
        else if symbol('m.s2x.d1.s1.0') \== 'VAR' then
            ee = 'notInDb2'
        else do
            dy = 'DBS.'m.s2x.d1.s1.0
            if m.dy.ts == s1 & m.dy.parts > 0 then
                ee = 'part0inPartTS'
            end
        end
    if ee == '' then
        if \ abbrev(l5, m.dy.iPre) then
            ee = 'iPrefix'
        else if m.dy.noRts == 1 then
            ee = 'noRTS'
    if ee \== '' then do
        if ee \==  'noRTS' then
            say left(ee, 20) '==>' m.nx
        if symbol('m.bad.ee') \== 'VAR' then do
            bx = m.bad.0 + 1
            m.bad.0 = bx
            m.bad.ee = bx
            m.bad.bx.type = ee
            m.bad.bx.cDs = 0
            m.bad.bx.hu  = 0
            m.bad.bx.ha  = 0
            end
        dy = 'BAD.'m.bad.ee
        end
$**    say m.nx '==>' dy m.dy.db m.dy.sp m.dy.pa m.dy.iPre
    m.dy.cDs = m.dy.cDs + 1
    m.dy.hu  = m.dy.hu + u1
    m.dy.ha  = m.dy.ha + a1
    end
say timing() 'after' c 'DSNs'
bc = 0
do bx=1 to m.bad.0
    say f('bad @TYPE%20c @CDS%7i @HU%kbiB @HA%kbiB', 'BAD.'bx)
    bc = bc + m.bad.bx.cDs
    end
say bc 'bad Dsns'
cDi = 0
sDs = 0
sHu = 0
sHa = 0
sRt = 0
do dx=1 to m.dbs.0          $** check partitions
    dy = 'DBS.'dx
    d1 = m.dy.db
    s1 = m.dy.sp
    t1 = m.dy.ts
    p1 = 0 + m.dy.pa
    n = d1'.'s1'#'p1
    sDs = sDs + m.dy.cDs
    sHu = sHu + m.dy.Hu
    sHa = sHa + m.dy.Ha
    rSz = m.dy.act * m.dy.pgSz
    if m.dy.pgSz < 100 then
        rSz = rSz * 1024
    sRt = sRt + rSz
    if rSz <> m.dy.hu then do
        say f('%kbiB %+kbiB @3.HU%kbiB @HA%kbiB @CDS%4i %c' ,
             , rSz, m.dy.hu - rSz, dy, n) ,
             m.dy.cDs (m.dy.noRTS==1) m.dy.pgsz
        cDi = cDi + 1
        end
    end
say cDi 'differences in' m.dbs.0 'parts with' sDs 'DSNs'
say f('rts %kbiB, huRBA %kbiB, haRba %kbiB', sRt, sHu, sHa)
say timing() 'vsamCheck end' $dbSys f('%t E')
$#out                                              20141125 08:20:53