Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

TechTip - Analyze Your Programs and Applications, Part II - System Administration - IT Infrastructure 3

Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

concat MLCHGt end Upddate,MLMTXT FROM jpltools.

mbrlist WHERE MLCHGc

<> '' ) select upd.* from upd exception join cpl on odsrcm = mlname

Figure 10: Here's a list of sources without objects.

Now you'll want the list of sources modi ed but not recompiled:

with cpl as (

SELECT ODOBNM, ODSRCM , case when odsrcc = '' then ' ' else trim(char(
ODSRCC+ 19)) concat ODSRCD concat '-' concat odsrct end cpldate ,
ODOBTX FROM jpltools.objs WHERE odsrcm <> '' and odsrcc <> ''

), upd as (

SELECT MLNAME, case when MLCHGc = '' then ' ' else trim(char(
MLCHGC+ 19)) concat MLCHGD concat '-' concat MLCHGt end
Upddate,MLMTXT FROM jpltools.mbrlist WHERE MLCHGc <> ''

) select ODOBNM "Object", ODSRCM "Src Mbr",

cpldate concat case when upddate = cpldate then '' else ' was updated
' concat upddate end "Compiled_date"

, case when mlmtxt = odobtx then ' ' concat odobtx else '>> '
concat odobtx concat ' changed to ' concat mlmtxt end "Text"

from cpl join upd on odsrcm = mlname and (cpldate <> upddate

or odobtx <> mlmtxt)                                                                                           

                                            

Figure 11: These are the sources modi ed but not recompiled.

 I changed my machine; we see the traces dated 2010-11-12-20:41:42.

Remember that these analyses are based on the fact that program and source code members
have the same name. It is common, but not 100 percent accurate.

Program Cross-Reference
I'm gaining momentum, and after getting so much information from two system commands,
other questions have quickly come to mind:

 
How can we tell if a program or le is no longer used? Explore DSPPGMREF. Obviously, we cannot
answer this question if the program name is determined dynamically in the application.

Here's a more di cult question: A program that should not be used remains called in some
programs (last-used date is recent, days-used count continues to grow…). How can we get an
impact analysis of deleting  this program? The answer is again provided by SQL—speci cally by
the recursive SQL on the DSPPGMREF out le.

In the same way and by writing the recursion in the opposite direction, I have obtained for a given
program a list of all programs and les it uses. SQL recursion has been available since V5R4.

This is the DSPPGMREF, simple version:

DSPPGMREF PGM(JPLTOOLS/*ALL) OUTPUT(*OUTFILE) OBJTYPE(*ALL)

OUTFILE(JPLTOOLS/PGMREF)

Why a "simple version"? Because there's a complex version. Indeed, DSPPGMREF allows you to
nd cross-references—not only PGM, but also SQLPKG, SRVPGM, MODULE, and QRYDFN. Yes,
but with several minor problems.

First problem: The structure of the DSPPGMREF out le does not give the type of the object
scanned. This information is actually provided by the column WHSPKG:

WHSPKG Type

P *PGM

S *SQLPKG

V *SRVPGM

M *MODULE

Q *QRYDFN

This forces us to, at least, require that the transformation be able to make joins with the
DSPOBJD le:

alter table jpltools.pgmref add column whptyp char (10 ) not null with
default ;

update jpltools.pgmref set whptyp = case

when whspkg ='P' then '*PGM'

when whspkg ='S' then '*SQLPKG'

when whspkg ='V' then '*SRVPGM'


when whspkg ='M' then '*MODULE'

when whspkg ='Q' then '*QRYDFN' end    

Second problem: Variable names are exposed (dynamically called programs). We may want to
ignore them. And the modules overlap program references, so they are not useful.

Third problem: DSPPGMREF provided a list of all formats, especially for DSPF. My analysis of
cross-references does not descend to the le format level; this information is then simply useless
duplicates.

Fourth problem: Depending on whether the target application uses the library list or the quali ed
objects, joins will, or will not, integrate the objects  library.

Fifth problem: WHLNAM and WHFNAM columns for the library and the referenced object are 11
characters instead of 10, causing some errors in the joins on WHLIB and WHPNAM

Embedding SQL transformation (needed to correct these problems) in the recursive SQL would
make the SQL statement not understandable. There are two methods to deal with this problem:
Either build a view on jpltools/pgmref, or do an insert into another table. I chose the insert.

Which brings us to this SQL to repackage the PGMREF le:

drop table jpltools.root ;

create table jpltools.root as (

select distinct –- solve duplicates on file name

whlib caller_lib

, whpnam caller

, cast (case

when whspkg ='P' then '*PGM'

when whspkg ='S' then '*SQLPKG'

when whspkg ='V' then '*SRVPGM'

when whspkg ='M' then '*MODULE'

when whspkg ='Q' then '*QRYDFN' end as char(10)) as caller_type

, cast(whlnam as char(10)) called_lib -- resize correctly called

, cast(whfnam as char(10)) called

, whotyp called_type

, cast( '' as char(30) ) caller_key

, cast( '' as char(30) ) called_key


from jpltools.pgmref

where whspkg <> 'M'

) with data including column defaults

update jpltools.root set

caller_key = --caller_lib concat -– don't use object lib in join

caller concat caller_type

,called_key = --called_lib concat

called concat called_type

The Caller_key and Called_key columns are used to simplify the writing of recursive joins.

It is likely that you already have a scheduled batch job that runs DSPPGMREF. I suggest that you
either compile the three samples of SQL above by using CRTQMQRY and then add these three
with a repackaging STRQMQRY in the same batch, or copy the three samples of SQL above in a
source member and then add one repackaging RUNSQLSTM in the same batch. 

Cascading Caller to Called


This recursive SQL takes as root all the lines of repackaged DSPPGMREF (ROOT le). The
Title_Caller column is used to keep track of the path and also to detect loops in the recursive
calls. The Title_Called column is used to power the previous one. Level column can master the
infernal loops and the too-deep analysis.

with cascade (caller, title_caller, called, title_called

, level, called_key) as (

select caller,

cast(trim(caller_lib) concat '/' concat trim(caller)

as varchar(1000) ) title_caller

, called

, cast(trim(called_lib) concat '/' concat trim(called)

as varchar(21) ) title_called

, 1 level

, called_key

from jpltools.root

/* here choose the caller to analyze */

-- where caller='MYPGM'

union all
select

cascade.caller

, cascade.title_caller concat ' > '

concat cascade.title_called

, child.called

, cast(trim(child.called_lib) concat '/'

concat trim(child.called)

as varchar(21) ) title_called

, level + 1

, child.called_key

from cascade, jpltools.root child

where cascade.called_key = child.caller_key

/* here is a loop stopper */

and cascade.title_called not like '% ' concat


trim(child.called) concat ' %'

/* here is another loop stopper */

and cascade.level <= 20

/* here choose the called to follow */

--

) select cascade.* from cascade order by title_caller

Figure 12: Cascade caller to called.

 
Now, the same recursion, but the other way. This analysis allows you to, for example, search to
nd whether a le or program is still present that should have disappeared, understand the
impact of a change, or prepare a test plan.

with cascade (caller, title_caller, called, title_called

, level, caller_key) as (

select caller,

cast(trim(caller_lib) concat '/' concat trim(caller) as


varchar(21) ) title_caller

, called

, cast(trim(called_lib) concat '/' concat trim(called) as


varchar(1000) ) title_called

, 1 level

, caller_key

from jpltools.root

/* here choose the caller to analyze */

-- where whpnam='MYPGM'

union all

select

child.caller

, cast(trim(child.caller_lib) concat '/' concat


trim(child.caller) as varchar(21) ) title_caller

, cascade.called

, cascade.title_called concat ' < ' concat cascade.title_called

, level + 1

, child.caller_key

from cascade, jpltools.root child where cascade.caller_key =


child.called_key

/* here is a loop stopper */ and cascade.title_called not like '%'


concat trim(child.caller) concat '%'

/* here is another loop stopper */ and cascade.level <= 20

/* here choose the called to follow */

) select title_called, called, caller, level from cascade order by


title_called

You might also like