The best (and last?) GDG to GDGE conversion method

This article is about an update on converting GDGs to GDGEs. I've talked about this a couple of times - with the help of one our good friends, Mr. Catalog (Steve Branch, from DFSMS) - and we've got some more information to share. I did talk about this at the SHARE conference in Ft. Worth, and I wanted to share this with a wider audience. This is turning out to be one of my pet projects, and with good reason.  I think GDGEs are a great function and would like to see more people use them. 

First, as you might have followed from a prior article ( Marna's Musing March 2017 ), there was no direct and easy way to convert a GDG to a GDGE. Steve had provided us some of the inside problems on why that is so. However, just because I haven't discussed this in a while doesn't mean that a very helpful customer hasn't been thinking about how to solve this problem! In fact, this nice customer has been talking with Steve, and they have done some testing and we now have a new method to do these conversions.

And the beauty of this solution is that there is none of the unpleasant restrictions that we had on the other methods. Seems like folks are really interested in converting GDGs to GDGEs, which thrills me, as I love to see new(-ish) functions being exploited by users!

Let's start at the beginning, for those that haven't been following this soap opera:

In z/OS V2.2, GDGE (GDG Extensions) were introduced. The limit on the number of GDGs is 255 - due to a 1 byte catalog field called the GDGLIMIT. We can now call these GDGs "classic GDG", since we have a new kind. GDGE can support 999 generations - using a 2 byte catalog field called GDGLIMTE.

You've got to be positioned to start using GDGEs, as you need to make sure your applications know to use the field GDGLIMTE (instead of GDGLIMIT) when dealing with GDGEs. Thankfully, the Generic Tracking Facility is a big help here. By default, the GDGE capability is not turned on, as to ensure that you control when your applications are ready to use GDGEs.

Originally, we had a couple of ways to convert GDGs to GDGEs:

1. Marna’s original method worked only on SMS-GDG’s. Migrated data sets were ok, but they were recalled, and tape data sets were not supported.  The method was a six step process using IDCAMS ALTERs with temporary GDGs.
2. Steve introduced an improvement that handled non-SMS-GDGs by using TSO RENAMEs, but could not handle tape data set and still resulted in data sets being recalled. There were still six steps, and a REXX program could help (thanks to customer Richard Jakobek, from the UK, which he shares here !).
.
Which brings us to now.  We have what is the best conversion method so far, a third method contributed by another customer. This method uses REPRO MERGECAT with a temporary catalog. It works with SMS-GDG and non-SMS GDGs, tape data sets, and  does not recall the data sets.  Steve shared the job he used for testing it, and Marna has been playing around with it and found it to be very helpful. This method still is multi-step, but runs pretty quickly. Let's look at the meaty part of this job:

In this example here "tps_gdg" is the name of the GDG you want to convert:

1.  Define a temporary usercat. This will be used to store hold the GDGs that you want to convert:

DEFINE UCAT(NAME (temp_cat) STORCLAS(STANDARD) CYL (1 1))

2.  REPRO the classic GDGs into the temporary usercat. Note that the data sets are not recalled, and are removed from the original usercat where they resided:

REPRO INDATASET(original_cat) OUTDATASET(temp_cat) ENTRIES(tps_gdg) MERGECAT

3. Define the GDGEs, and use the same name as they were in the original catalog:

DEFINE GDG(NAME(tps_gdg) EXTENDED LIMIT(999) SCRATCH PURGE)

4. Move the selected GDGE data sets from the temporary catalog into the original catalog. Note the data sets are not recalled, and the GDG name itself remains in temp_cat:

REPRO INDATASET(temp_cat) OUTDATASET(original_cat) ENTRIES(tps_gdg.*) MERGECAT

If you are interested in giving this a try, I'm going to put two sample JCL jobs below: one sets up some GDGs for testing, and the other actually does the conversion. These are the jobs that Steve and I have used to feel comfortable about using this conversion method.

I hope this soap opera for conversions is now over, with this very helpful third method.  Enjoy those 999 generations :).  

 

1 Comment

Sample JCL to test and convert

April 7, 2020 05:43 PM by Marna Walle

Sample JCL to set up a test:

//* SET UP TESTING FOR GDG TO GDGE CONVERSION
//*
//CLEANUP EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
/* CLEAN UP FROM PREVIOUS RUNS */
DELETE SMSA.GDGA.* NONVSAM PURGE SCRATCH
DELETE SMSA.GDGA GENERATIONDATAGROUP FORCE
DELETE SMSCAT USERCATALOG RECOVERY
DELETE TMPCAT USERCATALOG RECOVERY
SET MAXCC = 0
//DEFOCAT EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
/* DEFINE ORIGINAL CATALOG */


DEFINE -
UCAT -
(NAME (SMSCAT) STORCLAS(STANDARD) -
CYL (1 1))

DEF ALIAS(NAME(SMSA) RELATE(SMSCAT))
//DEFGDG EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *

/* DEFINE GDG CLASSIC IN ORIGINAL CATALOG */

DEFINE GDG (NAME(SMSA.GDGA) LIMIT(255) SCRATCH PURGE)

//DEFGDSES EXEC PGM=IEFBR14
//DDO1 DD DSN=SMSA.GDGA(+1),DISP=(,CATLG),SPACE=(TRK,(1,1)),
// STORCLAS=STANDARD,

// DCB=(RECFM=FB,LRECL=80,BLKSIZE=800)
//DDO2 DD DSN=SMSA.GDGA(+2),DISP=(,CATLG),SPACE=(TRK,(1,1)),
// STORCLAS=STANDARD,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=800)
//DDO3 DD DSN=SMSA.GDGA(+3),DISP=(,CATLG),SPACE=(TRK,(1,1)),
// STORCLAS=STANDARD,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=800)
//DDO4 DD DSN=SMSA.GDGA(+4),DISP=(,CATLG),SPACE=(TRK,(1,1)),
// STORCLAS=STANDARD,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=800)
//DDO5 DD DSN=SMSA.GDGA(+5),DISP=(,CATLG),SPACE=(TRK,(1,1)),
// STORCLAS=STANDARD,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=800)
//DDO6 DD DSN=SMSA.GDGA(+6),DISP=(,CATLG),SPACE=(TRK,(1,1)),
// STORCLAS=STANDARD,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=800)
//LOADGDSS EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*

//DD1 DD *
001 DATA
/*
//SYSIN DD *

/* REPRO DATA INTO GDSES SO THERE IS SOMETHING TO MIGRATE */
REPRO INFILE(DD1) ODS(SMSA.GDGA.G0001V00)
REPRO INFILE(DD1) ODS(SMSA.GDGA.G0002V00)
REPRO INFILE(DD1) ODS(SMSA.GDGA.G0003V00)
REPRO INFILE(DD1) ODS(SMSA.GDGA.G0004V00)
REPRO INFILE(DD1) ODS(SMSA.GDGA.G0005V00)
REPRO INFILE(DD1) ODS(SMSA.GDGA.G0006V00)
/*
//HMIGRATE EXEC PGM=IKJEFT01
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *

/* MIGRATE SOME GDSES TO SHOW THEY ARE NOT RECALLED */
/* BY HSM PROCESSING */

HMIGRATE 'SMSA.GDGA.G0001V00' WAIT
HMIGRATE 'SMSA.GDGA.G0003V00' WAIT
HMIGRATE 'SMSA.GDGA.G0005V00' WAIT
HMIGRATE 'SMSA.GDGA.G0006V00' WAIT
/*
//*
//LISTCAT EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
LISTCAT ENTRY(SMSA.GDGA) ALL
//*
//* THE SET UP OF AN ORIGINAL CATALOG WITH A GDG AND SOME GDSES
//* IS COMPLETE AT THIS POINT.

 

Sample JCL to do the conversions:

//CONVERT EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *

/* DEFINE TEMPORARY CATALOG */

DEFINE -
UCAT -
(NAME (TMPCAT) STORCLAS(STANDARD) -
CYL (1 1))

/* REPRO GDG AND GDSES TO THE TEMPORARY CATALOG */

REPRO -
INDATASET(SMSCAT) -

OUTDATASET(TMPCAT) -
ENTRIES(SMSA.GDGA) -
MERGECAT
/* DEFINE GDG EXTENDED IN THE ORIGINAL CATALOG */

DEFINE GDG (NAME(SMSA.GDGA) EXTENDED LIMIT(999) SCRATCH PURGE)

/* REPRO GDSES BACK TO THE ORIGINAL CATALOG */

REPRO -
INDATASET(TMPCAT) -
OUTDATASET(SMSCAT) -
ENTRIES(SMSA.GDGA.*) -
MERGECAT

/* LISTCAT TO SHOW EVERYTHING BUILT CORRECTLY */
LISTCAT ENTRY(SMSA.GDGA) ALL

//HRECALL EXEC PGM=IKJEFT01
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *

/* PERFORM RECALLS TO SHOW THAT NEW GDGE IS WORKING */

HRECALL 'SMSA.GDGA.G0001V00'
HRECALL 'SMSA.GDGA.G0003V00'
HRECALL 'SMSA.GDGA.G0005V00'
HRECALL 'SMSA.GDGA.G0006V00'

/* LISTCAT TO SHOW EVERYTHING RECALLED CORRECTLY */
LISTCAT ENTRY(SMSA.GDGA) ALL NOPREFIX
/*
//*

Recent Stories
New Podcast Episode: New location, long episode, with correction

Our podcast's new home away from home

The best (and last?) GDG to GDGE conversion method