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
Joined: 06 Jul 2010 Posts: 765 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.
Joined: 01 Sep 2006 Posts: 2593 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.
Code:
jcl.cnt = "//*"
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?
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
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
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.
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
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