Portal | Manuals | References | Downloads | Info | Programs | JCLs | Mainframe wiki | Quick Ref
IBM Mainframe Forum Index
 
Register
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Memberlist Profile Log in to check your private messages Log in
 
Dynamically split large DSN list into different PDS-E member

 
Post new topic   Reply to topic    IBMMAINFRAMES.com Support Forums -> CLIST & REXX
View previous topic :: :: View next topic  
Author Message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Tue Sep 17, 2019 8:24 pm    Post subject: Dynamically split large DSN list into different PDS-E member
Reply with quote

Good morning,

I would have a problem to submit.
I have a member of a PDS-E library that contains a large list of dataset names, I would like to be able to dynamically create, in the same PDS-E libraries, output members that contain 5 datasets each.
I want to create everything with a REXX, and not use Sort or Icetool.
The Rexx I created works, but it creates 1 member for each line read from the Input file, so it creates me 15 Run, I would like to be able to create 3 Runs from 5 datasets each.

Below I attach the input member with 15 dataset name: INP
Of course I also attach the Rexx I created.

Thanks for any support



Member used as INPUT in the PDS-E library: INP

Code:

***************************** Top of Data ******************************
XA1MVS.REC.D12214.DOC.001
XB1MPS.REC.D12214.DOC.002
XC1MVS.REC.D12214.DOC.003
XD1MVS.REC.D12214.DOC.004
XE1MVS.REC.D12214.DOC.005
XF1MVS.REC.D12214.DOC.006
XG1MVS.REC.D12214.DOC.007
XH1MVS.REC.D12214.DOC.008
XI1MVS.REC.D12214.DOC.009
XL1MVS.REC.D12214.DOC.010
XM1MVS.REC.D12214.DOC.011
XN1MVS.REC.D12214.DOC.012
XO1MVS.REC.D12214.DOC.013
XP1MVS.REC.D12214.DOC.014
XQ1MVS.REC.D12214.DOC.015
**************************** Bottom of Data ****************************



REXX, attention to try it, the INPUT and OUTPUT must be replaced:
Code:

inpdset = 'name.pdse ('Inp')'
outdset = 'name.pdse'




Full REXX:
Code:

/* REXX  -----------------------------------------------------------*\
\*------------------------------------------------------------------*/

inpdset = 'name.pdse('Inp')'
outdset = 'name.pdse'

count   = 1
temp    = 1

"ALLOC DDN(INFILE) DSN('"inpdset"') SHR"
"EXECIO * DISKR INFILE(STEM Record. FINIS)"
"FREE DDN(INFILE)"

/*-------------------------------------------------------------------*/
Do RowX=1 to Record.0
   Load_Rec = Record.0
   Out.Temp = Record.RowX
   NextRow  = RowX + 1
   NextRecd = Record.NextRow
   Dsname   = Word(NextRecd,1)

If Dsname ^= '' and NextRow <= 5 then
   Do
     OutDS = outdset!!'('!!'Run'!!count!!')'
     OutDS = strip(OutDS)
       say 'OutDS----->' OutDS
   /*---------------------------------------------*/
      "ALLOC DDN(OFILE) DSN('"OutDS"')NEW ",
      "LIKE('"inpdset"')"
      "FREE DDN(OFILE)"

      "ALLOC DDN(OFILE) DSN('"OutDS"') SHR"
      "EXECIO * DISKW OFILE(STEM OUT. FINIS)"
      "FREE DDN(OFILE)"
     Drop Out.
     Temp = 0
     Count = Count + 1
   /*---------------------------------------------*/
   End
   Temp = Temp + 1
End

   say 'End Process'
Exit

/*---------------------------------------------------------------*/ 
Back to top
View user's profile Send private message

Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2255
Location: Hampshire, UK

PostPosted: Tue Sep 17, 2019 8:42 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Why do you write out when your counter is <= 5? You surely want it to write out when you have reached 5.
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Tue Sep 17, 2019 8:47 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Hi Nic,

you're right, I tried so many versions that I probably missed the typing error.
Sorry
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Tue Sep 17, 2019 8:55 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

My wish would be to get to this:

Member into Library:
Code:

Command ===>
           Name     Prompt       Size   Created
_________ INP                      15  2019/09/17
_________ RUN1                      5  2019/09/17
_________ RUN2                      5  2019/09/17
_________ RUN3                      5  2019/09/17
          **End**



Member: RUN1
Code:

***************************** Top of Data *
XA1MVS.REC.D12214.DOC.001
XB1MPS.REC.D12214.DOC.002
XC1MVS.REC.D12214.DOC.003
XD1MVS.REC.D12214.DOC.004
XE1MVS.REC.D12214.DOC.005
**************************** Bottom of Data



Member: RUN2
Code:

***************************** Top of Data *
XF1MVS.REC.D12214.DOC.006
XG1MVS.REC.D12214.DOC.007
XH1MVS.REC.D12214.DOC.008
XI1MVS.REC.D12214.DOC.009
XL1MVS.REC.D12214.DOC.010
**************************** Bottom of Data



Member: RUN3
Code:

***************************** Top of Data *
XM1MVS.REC.D12214.DOC.011
XN1MVS.REC.D12214.DOC.012
XO1MVS.REC.D12214.DOC.013
XP1MVS.REC.D12214.DOC.014
XQ1MVS.REC.D12214.DOC.015
**************************** Bottom of Data
Back to top
View user's profile Send private message
Willy Jensen

Active User


Joined: 01 Sep 2015
Posts: 328
Location: Denmark

PostPosted: Tue Sep 17, 2019 10:32 pm    Post subject:
Reply with quote

I will suggest a slightly different approach, using the stack and using BPXWDYN for allocate and free:
Code:
 lib='xx.test.lib'                                                     
 cc=bpxwdyn('alloc da('lib'(zdslist)) shr rtddn(dd1)')                 
 "execio * diskr" dd1 "(stem dsl. finis)"                             
 cc=bpxwdyn('free dd('dd1')')                                         
                                                                       
 "newstack"                                                           
 outn=0                                                               
 do dsn=1 to dsl.0                                                     
   queue dsl.dsn                                                       
   if queued()//5=0 then call write  /* recno divisible by 5 */
 end                                                                   
 if queued()>0 then call write                                         
 cc=bpxwdyn('free dd('dd1')')                                         
 "delstack"                                                           
 exit 0                                                               
                                                                       
Write:                                                                 
 outn=outn+1                                                           
 say 'new ds' outn 'at record' dsn 'will contain' queued() 'records'   
 cc=bpxwdyn('alloc da('lib'(run'outn')) shr dd('dd1') reuse')         
 "execio" queued() "diskw" dd1 "(finis)"                               
 return 0                                                             

I understood it so that the new members are written to the same library as the datasetlist.
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Wed Sep 18, 2019 12:33 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Hi Willy, the method you proposed is fantastic, it works very well.
I had never tried the bpxwdyn method, so thank you for making me new methods.

How can I put [Solved] in this discussion?

Thanks again Willy for the support.
Back to top
View user's profile Send private message
Willy Jensen

Active User


Joined: 01 Sep 2015
Posts: 328
Location: Denmark

PostPosted: Wed Sep 18, 2019 1:17 pm    Post subject:
Reply with quote

You are welcome. I prefer the BPXWDYN command to ALLOC as it has some very usefull features, plus it is a function so can be placed in an expression.
BPXWDYN is described in the 'Using REXX and z/OS UNIX System Services' manual.
I dont think that you can 'solve' a discussion, but your latest entry should make it clear.
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Wed Sep 18, 2019 1:51 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Hi Willy thanks for the explanations.
I have already downloaded the 'Using REXX and z / OS UNIX System Services' manual.

Thanks again Willy for the support.
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Thu Sep 26, 2019 6:11 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Thanks to the help and support of Willy I managed to complete REXX as I wanted.
I make it available to everyone if it can be used by some other user.
REXX can also be modified to launch other HSM commands, such as Recall, Recover, Migration.

Kind regards
Ghellar

Code:

/* REXX ______________________________________________________________
|                                                                     |
| This REXX takes INPUT a member of a Library in which it is          |
| a List of Datasets has been inserted (taken from a query).          |
| The dataset names MUST be in column 1, these DSNAMEs are read       |
| one by one and a Backup Delete HSM command will be created:         |
|                                                                     |
|       Queue ' HSEND BDELETE ('!!DsName!!') ALL'                     |
|                                                                     |
| These command lists will then be dynamically saved to a series      |
| of members (in the same library where the member of INPUT), with    |
| names chosen a priori before launching the REXX.                    |
| There are indeed variables that necessarily go valued before        |
| ANY LAUNCH, and are reported by following:                          |
| | | | | |                                                           |
| V V V V V                                                           |
|____________________________________________________________________*/
/*-------------------------------------------------------------------*/
/*Preparatory variables to be modified by hand before EEXEC launch   */
/*-------------------------------------------------------------------*/
 InpLib  = pds.library.name        /* Extended name of the library   */
 ZDSLIST = INP                     /* Member of INPUT in the library */
 NameRun = RUN$                    /* Partial name member: OUTPUT    */
 N$Split = 5                       /* Number DSN that will be split  */
/*********************************************************************/

/*-------------------------------------------------------------------*/
 CC=BPXWDYN('ALLOC DA('InpLib'('ZDSLIST')) SHR RTDDN(DD1)')
 "EXECIO * DISKR" DD1 "(STEM DSL. FINIS)"
 CC=BPXWDYN('FREE DD('DD1')')
/*-------------------------------------------------------------------*/
 "newstack"                        /*                                */
 Outn=0                            /* Clear the variable  OutNumber  */
 JobN=0                            /* Clear the variable: JobNumber  */
/*--------------------------------*/
 do dsn=1 to dsl.0                 /*                                */
    DsnName = WORD(DSL.dsn,1)      /*                                */

    QUEUE ' HSEND BDELETE ('!!DsnName!!') ALL'

    if queued()//N_Split=0 then call Write
 end                               /*                                */
    if queued()>0 then call write  /*                                */
      cc=bpxwdyn('free dd('dd1')') /*                                */
 "delstack"                        /*                                */
 exit 0                            /*                                */
/*-------------------------------------------------------------------*/
/* ---  Start call Write      -------------------------------------- */
/*-------------------------------------------------------------------*/
Write:
 Outn=Outn+1                       /*Add +1 to the OutNumber variable*/
 Jobn=Jobn+1                       /*Add +1 to the JobNumber variable*/

 say 'new ds' Outn 'at record' dsn 'will contain' queued() 'records'
 CC=BPXWDYN('ALLOC DA('InpLib'('NameRun''Outn')) SHR DD('DD1') REUSE')
 call JobCard                      /* CALL JobCard insert jcl card   */
 "EXECIO" QUEUED() "DISKW" DD1 "(FINIS)"
 Return 0
/*-------------------------------------------------------------------*/
/* ---  End   call Write      -------------------------------------- */
/*-------------------------------------------------------------------*/


/*-------------------------------------------------------------------*/
/* ---  Start call JobCard    -------------------------------------- */
/*-------------------------------------------------------------------*/
JobCard:

If Jobn>=1 or Jobn<=9 then         /*                                */
   do                              /*                                */
     Jobn='0'!!Jobn                /*                                */
   end                             /*                                */

jcl.1='//TMPJCL'Jobn' JOB MSGCLASS=8,CLASS=E,NOTIFY=&SYSUID        '
jcl.2='//*---------------------------------------------------------'!!,
        '------------'
jcl.3='//* JOB that deletes ALL obsolete files with alias: xxxxxx  '
jcl.4='//*---------------------------------------------------------'!!,
        '------------'
jcl.5='//BKDELETE EXEC PGM=IKJEFT01,DYNAMNBR=20                    '
jcl.6='//*        ----------------                                 '
jcl.7='//SYSPRINT DD SYSOUT=*                                      '
jcl.8='//SYSTSPRT DD SYSOUT=*                                      '
jcl.9='//SYSTSIN  DD *                                            '
jcl.0=9
                                   /*                                */
do n=jcl.0 to 1 by -1              /*                                */
   push jcl.n                      /*                                */
end                                /*                                */

Return
/*-------------------------------------------------------------------*/
/*----  End   call JobCard    ---------------------------------------*/
/*-------------------------------------------------------------------*/
 
Back to top
View user's profile Send private message
enrico-sorichetti

Senior Member


Joined: 14 Mar 2007
Posts: 10639
Location: italy

PostPosted: Thu Sep 26, 2019 7:16 pm    Post subject:
Reply with quote

unfortunately the snippet posted is unreadable , too much clutter
the noise outsizes the info

do not over-comment
spaces are much much better than a bunch of "---...---"
space properly the lines for readability ( a blank line is better that an irrelevant comment, or a <comment box>

Code:
Outn=Outn+1                       /*Add +1 to the OutNumber variable*/

how does the comment help ??? do not comment the obvious
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Thu Sep 26, 2019 7:29 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Hi Enrico,

unfortunately I do not work all the days with the REXX, so I always comment on the projects being realized, because I might need to modify them after months or years, this explains the reason for the comments.
I will take your comment as a suggestion for future projects.
Many thanks
Back to top
View user's profile Send private message
sergeyken

Active Member


Joined: 29 Apr 2008
Posts: 635
Location: Maryland

PostPosted: Sat Sep 28, 2019 12:38 am    Post subject: Re: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Ghellar wrote:
Hi Enrico,

unfortunately I do not work all the days with the REXX, so I always comment on the projects being realized, because I might need to modify them after months or years, this explains the reason for the comments.
I will take your comment as a suggestion for future projects.
Many thanks

Enrico is absolutely right.
Comments must clarify some non-obvious ideas, but not just repeat obvious things in other words! It makes the code even less understandable, and impossible to read.
Code:
 A = A + 1 /* this REXX arithmetic statement is supposed to perform
              very critical operation. It takes the previous value
              of variable A, then performs arithmetic addition
              with value of 1, and places the result back
              to variable A.
              Before any change to this code please, consult with
              the author. */

Whenever I met comments of this style, my first desire was: how to kill the author?

Also endless use of '---------------------------------------------', or even '******************************' makes it much worse compared to simple blank lines.
Back to top
View user's profile Send private message
Willy Jensen

Active User


Joined: 01 Sep 2015
Posts: 328
Location: Denmark

PostPosted: Sat Sep 28, 2019 2:12 am    Post subject:
Reply with quote

Guys, he got his problem solved and was kind enough to share his solution with us. He uses more comments than you (and I) like to, but that does not neccessarily make it wrong. I have been been accused of using too few comments and writing much too compact code. At the end of the day it works for him.
If in the future someone faces a similar issue they can copy the program, stripping away what they deem superflous. Still easier that starting from scratch.
Just my 2 cents.
Back to top
View user's profile Send private message
Ghellar

New User


Joined: 01 Sep 2005
Posts: 22

PostPosted: Sat Sep 28, 2019 9:18 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Goodmorning everyone,

thank you for your opinions, sorry but I'm not as expert as you, I'm here to try to learn that's all. If you were an expert you know here in this forum to help others, and instead I am here asking for help from all of you for my lack of knowledge.
But I wouldn't want to have created a problem with these excessive comments, so to try to fix it, I simply attach the code without comments.

Thanks again to everyone.

Code:

/* REXX ______________________________________________________________
|                                                                     |
| This REXX takes INPUT a member of a Library in which it is          |
| a List of Datasets has been inserted (taken from a query).          |
| The dataset names MUST be in column 1, these DSNAMEs are read       |
| one by one and a Backup Delete HSM command will be created:         |
|                                                                     |
|       Queue ' HSEND BDELETE ('!!DsName!!') ALL'                     |
|                                                                     |
| These command lists will then be dynamically saved to a series      |
| of members (in the same library where the member of INPUT), with    |
| names chosen a priori before launching the REXX.                    |
| There are indeed variables that necessarily go valued before        |
| ANY LAUNCH, and are reported by following:                          |
| | | | | |                                                           |
| V V V V V                                                           |
|____________________________________________________________________*/

 InpLib  = pds.library.name       
 ZDSLIST = INP                     
 NameRun = RUN$                   
 N$Split = 5                       

 CC=BPXWDYN('ALLOC DA('InpLib'('ZDSLIST')) SHR RTDDN(DD1)')
 "EXECIO * DISKR" DD1 "(STEM DSL. FINIS)"
 CC=BPXWDYN('FREE DD('DD1')')

 "newstack"                       
 Outn=0                           
 JobN=0                           

 do dsn=1 to dsl.0                 
    DsnName = WORD(DSL.dsn,1)     

    QUEUE ' HSEND BDELETE ('!!DsnName!!') ALL'

    if queued()//N_Split=0 then call Write
 end                               
    if queued()>0 then call write 
      cc=bpxwdyn('free dd('dd1')')
 "delstack"                       
 exit 0                           

Write:
 Outn=Outn+1                       
 Jobn=Jobn+1                       

 say 'new ds' Outn 'at record' dsn 'will contain' queued() 'records'
 CC=BPXWDYN('ALLOC DA('InpLib'('NameRun''Outn')) SHR DD('DD1') REUSE')
 call JobCard                      /* CALL JobCard insert jcl card   */
 "EXECIO" QUEUED() "DISKW" DD1 "(FINIS)"
 Return 0


JobCard:
If Jobn>=1 or Jobn<=9 then         
   do                             
     Jobn='0'!!Jobn               
   end                             

jcl.1='//TMPJCL'Jobn' JOB MSGCLASS=8,CLASS=E,NOTIFY=&SYSUID        '
jcl.2='//*---------------------------------------------------------'!!,
        '------------'
jcl.3='//* JOB that deletes ALL obsolete files with alias: xxxxxx  '
jcl.4='//*---------------------------------------------------------'!!,
        '------------'
jcl.5='//BKDELETE EXEC PGM=IKJEFT01,DYNAMNBR=20                    '
jcl.6='//*        ----------------                                 '
jcl.7='//SYSPRINT DD SYSOUT=*                                      '
jcl.8='//SYSTSPRT DD SYSOUT=*                                      '
jcl.9='//SYSTSIN  DD *                                             '
jcl.0=9
                                   
do n=jcl.0 to 1 by -1             
   push jcl.n                     
end                               

Return

Back to top
View user's profile Send private message
enrico-sorichetti

Senior Member


Joined: 14 Mar 2007
Posts: 10639
Location: italy

PostPosted: Sat Sep 28, 2019 9:58 pm    Post subject: Reply to: Dynamically split large DSN list into different PDS-E member
Reply with quote

Quote:
But I wouldn't want to have created a problem with these excessive comments,


You have not created any problem...
I was just suggesting to keep things simple for better visual navigation of the sources
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic    IBMMAINFRAMES.com Support Forums -> CLIST & REXX All times are GMT + 6 Hours
Page 1 of 1

 

Search our Forum:

Similar Topics
Topic Author Forum Replies Posted
No new posts IEBCOPY - wild-card for member copies??? JPVRoff JCL & VSAM 2 Fri Nov 15, 2019 3:58 am
No new posts recursive SQL to generate list jzhardy DB2 5 Sun Apr 07, 2019 8:38 am
No new posts Split input file into multiple files ... srini24 DFSORT/ICETOOL 1 Sat Mar 30, 2019 9:39 pm
No new posts Split single i/p line into multiple l... elixir1986 DFSORT/ICETOOL 2 Wed Feb 27, 2019 12:47 am
No new posts REXX identify the last/latest created... sivatechdrive CLIST & REXX 7 Thu Jan 24, 2019 12:15 pm

Facebook
Back to Top
 
Job Vacancies | Forum Rules | Bookmarks | Subscriptions | FAQ | Polls | Contact Us