|
View previous topic :: View next topic
|
| Author |
Message |
balaji81_k
Active User
Joined: 29 Jun 2005 Posts: 155
|
|
|
|
Hi ,
I have written Rexx routine to create JCL statements which does delete datasets using IEFBR14 utlity . Rexx routine reads the input file which has list of datasets needs to be deleted . Problem is , i couldn't able to see the JCL statements which i coded under iterative loop condition in output file . Can any one help me in correcting the logic issue .
| Code: |
address tso
user = userid()
fi = user || "." ||dslist ||"."||output
fo = user || "." ||jcljob ||"."||output
address tso
"alloc da('"fi"') fi(myindd) shr reuse"
say 'alloc rc indd ->' rc
"execio * diskr myindd (stem indata. finis"
say 'read indd rc->' rc
"free fi(myindd)"
say 'free indd rc->' rc
final = indata.0
last_str = strip(indata.final)
y = msg('off')
x = sysdsn("'"fo"'")
if x = ok then
do
address tso "delete" "'"fo"'"
say rc
end
address tso
"allocate fi(jclx) da('"fo"') new tracks",
"reuse space(5,5) dir(0) dsorg(ps) recfm(f,b) lrecl(80) blksize(0)"
say rc
/* writing jcl */
jclx.1 = "//"user"DL" "JOB (XXXX),'DELJCL',NOTIFY=&SYSUID,"
jclx.2 = "// CLASS=B,MSGCLASS=R,MSGLEVEL=(1,1),"
jclx.3 = "// TIME=NOLIMIT"
jclx.4 = "//*"
if final <= 10 then
do
call cr_single_Step_jcl
end
cr_single_step_jcl:
stepno = 1
jclx.5 = "//STEP"stepno "EXEC PGM=IEFBR14"
i = 0
cnt = 5
cnt = cnt + 1
done = "NO"
do while done = "NO"
cnt = cnt + 1
do i = 1 to final
jclx.cnt = "//DD"i "DD DSN="indata.i"," , -> Not written in output file
"// DISP=(MOD,DELETE,DELETE)," , -> Not written
"// SPACE=(0,0)" -> not written in output file
say jclx.cnt
cnt = cnt + 1
say 'i->' i
end
if i >= final then
done = "YES"
else
done = "NO"
end
cnt = cnt + 1
jcl.cnt = "//*"
trace i
address tso "execio * diskw jclx (stem jclx. finis"
if rc > 0 then
do
say 'error in updating file '
exit 4
end
exit 0
|
|
|
| Back to top |
|
 |
prino
Senior Member

Joined: 07 Feb 2009 Posts: 1323 Location: Vilnius, Lithuania
|
|
|
|
| If you had traced ("TRACE ?R") your exec you would have immediately seen what's wrong! |
|
| Back to top |
|
 |
don.leahy
Active Member
Joined: 06 Jul 2010 Posts: 767 Location: Whitby, ON, Canada
|
|
|
|
| My preferred approach for this type of task would be to use File Tailoring services rather than writing the JCL using Rexx code. Generating JCL is what File Tailoring was designed for. |
|
| Back to top |
|
 |
Pedro
Global Moderator

Joined: 01 Sep 2006 Posts: 2624 Location: Silicon Valley
|
|
|
|
Note: I did not actually test your code.
There are multiple logic problems in the code:
Here, you have what should be three lines of JCL put into one line of the stem variable. The result will be only one line of JCL.
| Code: |
jclx.cnt = "//DD"i "DD DSN="indata.i"," , -> Not written in output file
"// DISP=(MOD,DELETE,DELETE)," , -> Not written
"// SPACE=(0,0)" -> not written in output file |
Here, you have a different stem variable than used elsewhere.
Here, I do not think you need the DO WHILE statement. The nested DO will process all of your input records. You only need to process them once.
| Code: |
do while done = "NO"
cnt = cnt + 1
do i = 1 to final |
But your question is about missing records...
Here, you increment the counter twice without saving any records. That might result in a null record.
| Code: |
cnt = cnt + 1
done = "NO"
do while done = "NO"
cnt = cnt + 1 |
Later, when you issue EXECIO *, it will stop at the first null record
Prino's suggestion was to run with a TRACE... what were the results? |
|
| Back to top |
|
 |
enrico-sorichetti
Superior Member

Joined: 14 Mar 2007 Posts: 10900 Location: italy
|
|
|
|
read here why using EXECIO * DISKW is dangerous/improper
www.ibmmainframes.com/viewtopic.php?t=60269&highlight=execio
here are two snippets which achieve the same in a better IMHO way
stem handling with a work variable
| Code: |
/* REXX */
/* arbitrary setting for the number of input things */
data.0 = 24
/* arbitrary setting for number of deletes in each coun */
coun = 10
do i = 1 to data.0
data.i = "some.dataset.s"i
end
jclx.1 = "//JOBNAME JOB (XXXX),'DELJCL',NOTIFY=&SYSUID,"
jclx.2 = "// CLASS=B,MSGCLASS=R,MSGLEVEL=(1,1),"
jclx.3 = "// TIME=NOLIMIT"
jclx.4 = "//* - - - - - - - - - - - - - - - - - - - - - - - - - - -"
jclx.0 = 4
if coun = 0 then do
j = jclx.0 + 1
jclx.j = "//*"
j = j + 1
jclx.j = "//DELETE EXEC PGM=IEFBR14"
jclx.0 = j
end
do i = 1 to data.0
if coun \= 0 then do
if i // coun = 1 then do
stepno = i % coun + 1
j = jclx.0 + 1
jclx.j = "//*"
j = j + 1
jclx.j = "//STEP"stepno "EXEC PGM=IEFBR14"
jclx.0 = j
end
end
j = jclx.0 + 1
jclx.j = "//DD"i "DD DSN="data.i","
j = j + 1
jclx.j = "// DISP=(MOD,DELETE,DELETE),"
j = j + 1
jclx.j = "// SPACE=(0,0)"
jclx.0 = j
,
end
do i = 1 to jclx.0
say jclx.i
end
return
|
stem handling without a work variable using INTERPRET
| Code: |
/* REXX */
/* arbitrary setting for the number of input things */
data.0 = 24
/* arbitrary setting for number of deletes in each step */
coun = 10
do i = 1 to data.0
data.i = "some.dataset.s"i
end
/* THE JOBCARD */
jclx.0 = 0
interpret "jclx."jclx.0+1" = '//JOBNAME JOB (XXXX),'DELJCL',NOTIFY=&SYSUID,'"
interpret "jclx."jclx.0+2" = '// CLASS=B,MSGCLASS=R,MSGLEVEL=(1,1),'"
interpret "jclx."jclx.0+3" = '// TIME=NOLIMIT'"
interpret "jclx."jclx.0+4" = '//* - - - - - - - - - - - - - - - - - - - - - - - - - - -'"
jclx.0 = jclx.0 + 4
if coun = 0 then do
interpret "jclx."jclx.0+1" = '//*'"
interpret "jclx."jclx.0+2" = '//DELETE EXEC PGM=IEFBR14'"
jclx.0 = jclx.0 + 2
end
do i = 1 to data.0
if coun \= 0 then do
if i // coun = 1 then do
stepno = i % coun + 1
interpret "jclx."jclx.0+1" = '//*'"
interpret "jclx."jclx.0+2" = '//STEP"stepno "EXEC PGM=IEFBR14'"
jclx.0 = jclx.0 + 2
end
end
interpret "jclx."jclx.0+1" = '//DD"i "DD DSN="data.i",'"
interpret "jclx."jclx.0+2" = '// DISP=(MOD,DELETE,DELETE),'"
interpret "jclx."jclx.0+3" = '// SPACE=(0,0)'"
jclx.0 = jclx.0+3
end
do i = 1 to jclx.0
say jclx.i
end
return
|
|
|
| Back to top |
|
 |
balaji81_k
Active User
Joined: 29 Jun 2005 Posts: 155
|
|
|
|
| Thanks Enrico for your valuable advise on EXECIO * DISKW . Now i am able to understand what was the issue in my logic . |
|
| Back to top |
|
 |
Pedro
Global Moderator

Joined: 01 Sep 2006 Posts: 2624 Location: Silicon Valley
|
|
|
|
I prefer this other approach:
| Code: |
J = 0
Call AddLine "//JOBNAME JOB (XXXX),'DELJCL',NOTIFY=&SYSUID,"
Call AddLine "// CLASS=B,MSGCLASS=R,MSGLEVEL=(1,1),"
Call AddLine "// TIME=NOLIMIT"
Call AddLine "//* - - - - - - - - - - - - - - - - - - - - - - - - - - -"
If coun = 0 Then Do
Call AddLine "//*"
Call AddLine "//DELETE EXEC PGM=IEFBR14"
End
. . .
/* add a line to the the output stem*/
AddLine:
Parse arg newline
j = j + 1
jclx.j = newline
jclx.0 = j
Return |
By moving the repetitive index logic to a subroutine, the main routine looks more simple. It will be easier to understand when you revisit the program in the future. |
|
| Back to top |
|
 |
balaji81_k
Active User
Joined: 29 Jun 2005 Posts: 155
|
|
|
|
Hi Pedro,
Thanks for your code. Now i am working on logic to split steps based on the no of input files available for delete. for example if i have 50 files to be deleted then i am creating 5 steps to do it .10 files for each step .I am facing the issue when the no of input files is multiples of 10 and i have marked arrow where is the problem.Can you please help me to overcome this issue.
Here is the code sample that i have written for the same.
| Code: |
/* rexx */
trace ?r
tot_no_files = X
div_by_10 = 10
integer_quot = tot_no_files % div_by_10
remainder = tot_no_files // div_by_10
say 'integer_quot' integer_quot
say 'remainder' remainder
if remainder > 0 then
do
step_cnt = integer_quot + 1
end
else
do
step_cnt = integer_quot
end
say 'step_cnt' step_cnt
total_steps = 0
total_ddcnt = 0
do i = 1 to step_cnt
total_steps = total_steps + 1
if total_steps = step_cnt then
if remainder > 0 then
remain_ddstps = remainder
else
remain_ddstps = integer_quot * 10 <-
else
remain_ddstps = 10
say "//STEP" total_steps "statement = IEFBR14 "
do j = 1 to remain_ddstps
total_ddcnt = total_ddcnt + 1
say "DD"total_ddcnt "=file" total_ddcnt
end
end
exit 0 |
|
|
| Back to top |
|
 |
enrico-sorichetti
Superior Member

Joined: 14 Mar 2007 Posts: 10900 Location: italy
|
|
|
|
if You look at my snippets You will see that they implement the logic You are asking for ...
the variable coun tells how many deletes for each step |
|
| Back to top |
|
 |
Pedro
Global Moderator

Joined: 01 Sep 2006 Posts: 2624 Location: Silicon Valley
|
|
|
|
I do not think you should care that the first step name is DELETE and others are named STEPnnn. Not caring simplifies then coding:
| Code: |
step# = 0
Do i = 1 To 35
If (I // 10) = 1 Then
Do
step# = step# + 1
Say '//*'
Say '//STEP'step# 'EXEC PGM=IEFBR14'
End
Say '//DD'i 'DD DSN='i
End |
per Enrico's example, you use the remainder function (//) to determine when a new EXEC statement is needed. |
|
| Back to top |
|
 |
balaji81_k
Active User
Joined: 29 Jun 2005 Posts: 155
|
|
|
|
| enrico-sorichetti wrote: |
if You look at my snippets You will see that they implement the logic You are asking for ...
the variable coun tells how many deletes for each step |
Thanks Enrico . Now i have logic to limit delete only for the files whose creation date is more than / equal = 90 days (>= 90). I have written logic to handle this difference. I have a doubt on this ,because i am not sure whether it will handle leap year logic also.
| Code: |
/* rexx */
/* to find difference between current time and sys creat time */
dsn = "'xxx.yyy.zzz'"
dsinfo = listdsi(dsn)
say 'syscreate ' syscreate
parse var syscreate 1 cc 3 yy '/' ddd .
jdate = yy||ddd
say jdate
gdate = date('u',jdate,'j')
say gdate
gdateb = date('base',gdate,'u')
today = Date('Base')
say 'gdate-base format->>' gdateb
say 'today-base format->>' today
ISOdate = Date('Standard', today, 'Base')
date1 = ISOdate
say 'date1->>>' date1
ISOdate = Date('Standard', gdateb, 'Base')
date2 = ISOdate
say 'date2->>>' date2
days_diff = date1 - date2
say 'days_diff' days_diff
exit 0 |
|
|
| Back to top |
|
 |
enrico-sorichetti
Superior Member

Joined: 14 Mar 2007 Posts: 10900 Location: italy
|
|
|
|
I guess I had a brain check ...
what is the exact format of the input list ?
an adrdssu dump delete with a dummy dump dataset might be the most practical solution
| Code: |
//jobname JOB ..........
//DSS EXEC PGM=ADRDSSU,REGION=0M,
// PARM='TYPRUN=NORUN'
//SYSPRINT DD SYSOUT=*
//DUMMYDS DD DUMMY,
// DCB=(RECFM=VB,LRECL=27994,BLKSIZE=27998)
//SYSIN DD *
DUMP DATASET( -
INCLUDE( -
dataset.one -
dataset.two -
...
dataset.umpteen -
) -
BY( REFDT LT (*,-xxx) ) -
OUTDDNAME(DUMMYDS) -
DELETE PURGE
/*
|
|
|
| Back to top |
|
 |
enrico-sorichetti
Superior Member

Joined: 14 Mar 2007 Posts: 10900 Location: italy
|
|
|
|
IMHO the date difference code is too much ...
why not use a simpler approach ???
something along the lines of ...
| Code: |
000009 ...
000010 dsirc = listdsi("some.existing.dataset")
000011 crtdt = substr(syscreate,3,2) || substr(syscreate,6,3)
000012 refdt = substr(sysrefdate,3,2) || substr(sysrefdate,6,3)
000013 crtage = date("b") - date("b",crtdt,"j")
000014 refage = date("b") - date("b",refdt,"j")
000015 say "crtage = "crtage
000016 say "refage = "refage
000017 ...
|
|
|
| Back to top |
|
 |
enrico-sorichetti
Superior Member

Joined: 14 Mar 2007 Posts: 10900 Location: italy
|
|
|
|
and here is a nice snippet which shows how to use translate
to reorder/select part of a string
| Code: |
000010 dsirc = listdsi("some.dataset")
000011 crtdt1 = substr(syscreate,3,2) || substr(syscreate,6,3)
000012 refdt1 = substr(sysrefdate,3,2) || substr(sysrefdate,6,3)
- - - - - - - - - - - - - - - - - - - 4 Line(s) not Displayed
000017 crtdt2 = translate(34678,syscreate,"12345678")
000018 refdt2 = translate(34678,sysrefdate,"12345678")
000019 say "crtdt1 / refdt1 => "crtdt1 "/" refdt1
000020 say "crtdt2 / refdt2 => "crtdt2 "/" refdt2
|
|
|
| Back to top |
|
 |
|
|
 |
All times are GMT + 6 Hours |
|