Tuesday, November 11, 2008

Use CLIST to submit JCL to batch delete dataset

In mainframe MVS ISPF option 3.4 panel, one can easily delete a dataset. However, if the dataset is already migrated to tape, such a deletion will hold up your session until the dataset is recovered from taped.

To avoid this, I have written a CLIST (called QDEL) to submit batch job JCL to do the deletion. Using batch job, there is no need to wait for those migrated dataaset.

Also, tranditonally, one cannot delete tape dataset in the foreground ISPF 3.4. But, since QDEL will submit a JCL, it can delete tape dataset.

But looking at the coding, it can also delete alias. Sorry that I cannot remember what exactly it is because the CLIST is written more than 10 years ago and I am now no longer working in mainframe platform.

As far as I remember, using this QDEL, I can delete many datasets in the background using batch JCL. I do not need to care whether the dataset is a tape or not, or whether it is migrated, ... etc.

QDEL is one of my favorite utilities. I usually put it as a member of a CLISTLIB which is usually the first allocated dataset of SYSPROC.

Here is the CLIST QDEL :

PROC 1 INDD DEBUG DELETE GDG(N) GEN() CLASS(H) USER()
CONTROL NOFLUSH NOMSG
IF &DEBUG = DEBUG THEN CONTROL MSG LIST NOFLUSH CONLIST SYMLIST
/* ******************************************************************
/* Licence Information:
/* --------------------
/* This coding is offered at no charge for 
/* NON-COMMERCIAL PERSONAL USE only.
/* The coding is copyright.
/* Reproduction of this coding in whole or in part 
/* in any form without the express written permission 
/* of the author is strictly prohibited. 
/* ******************************************************************
/* Disclaimer : 
/* ------------
/* This coding is distributed "as is" and is UNSUPPORTED.
/* NO WARRANTY of any kind is expressed or implied.
/* You use AT YOUR OWN RISK.
/* The author will not be liable for any data loss,
/* damages, and loss of profits or any other kind of
/* tangible or intangible loss while using or 
/* misusing this coding.
/* ******************************************************************
/* NAME   : QDEL
/* PURPOSE: BATCH DELETE DSN
/* AUTHOR : ALVIN SIU
/* *******************************************************************
/* MDIFICATIONS:
/* -------------
/* 1. ADD FUNCTION TO DELETE ALIAS
/* 2. ADD DOUBLE CONFIRMATION "DELETE"
/* 3. FIX SMALL BUG ON ALIAS CHECKING
/* 4. ADD ENVIRONMENT SAVE/RESTORE AND QUITING
/*    IN ORDER TO HANDLE THOSE PROFILE-PREFIX
/* 5. DO NOT DELETE A MEMBER OF PDS
/*    BECAUSE DELETE DDNAME(MEMBER) WILL
/*    ACTUALLY DELETE THE WHOLE "DDNAME" DATASET
/* *******************************************************************
NGLOBAL PARM0
NGLOBAL OPREFIX
SET PARM0 = QDEL
SET MYDD = &STR(&INDD)

/* ---------------- */
/* SAVE ENVIRONMENT */
/* ---------------- */
SET OPREFIX = &SYSPREF
PROFILE NOPREFIX

/* ------------ */
/* DISPLAY HELP */
/* ------------ */
IF &STR(&MYDD) = &STR(?) OR &STR(&MYDD) = &STR(HELP) THEN +
DO
  CLEAR
  SYSCALL USAGE
  SYSCALL QUITING 0
END

/* ------------------------------- */
/* ENSURE CANNOT DELETE PDS MEMBER */
/* ------------------------------- */
SET LP = &STR((
SET RP = &STR())
IF &SYSINDEX(&STR(&LP),&INDD) GT 0 +
OR &SYSINDEX(&STR(&RP),&INDD) GT 0 THEN +
DO
  WRITE QDEL &INDD
  WRITE
  WRITE ERROR: CANNOT DELETE A MEMBER IN A PARTITION DATASET
  SYSCALL QUITING 20
END

/* ------------------- */
/* DOUBLE CONFIRMATION */
/* ------------------- */
IF &DELETE = DELETE THEN SET TMP = 0
ELSE DO
       WRITE QDEL
       WRITE ERROR: PLEASE ADD THE WORD "DELETE" AS A DOUBLE
       WRITE CONFIRMATION.
       SYSCALL QUITING 21
     END

/* ------------- */
/* REMOVE QUOTES */
/* ------------- */
SET QUOTED = NO
SET L = &LENGTH(&STR(&MYDD))
SET L1 = &L - 1
IF &STR(&SUBSTR(&L:&L,&STR(&MYDD))) = &STR(') THEN +
DO
  SET MYDD = &SUBSTR(1:&L1,&STR(&MYDD))
  SET QUOTED = YES
END
SET L = &LENGTH(&STR(&MYDD))
IF &STR(&SUBSTR(1:1,&STR(&MYDD))) = &STR(') THEN +
DO
  SET MYDD = &SUBSTR(2:&L,&STR(&MYDD))
  SET QUOTED = YES
END
IF &QUOTED = NO AND &OPREFIX ¬= THEN +
   SET MYDD = &OPREFIX..&MYDD
SET L = &LENGTH(&STR(&MYDD))

/* ------------------- */
/* FIND OUT THE SUFFIX */
/* ------------------- */
SET TMP = &STR(&MYDD)
SET I = 1
SET S = 1
SET J = -1
DO WHILE &I > 0
   SET I = &SYSINDEX(&STR(.),&STR(&TMP),&S)
   IF &I > 0 THEN SET J = &I
   SET S = &J + 1
END
IF &J = -1 THEN SET SUF = &STR(&MYDD)
           ELSE SET SUF = &SUBSTR(&S:&L,&STR(&MYDD))

/* -------------- */
/* CHECK IF ALIAS */
/* -------------- */
SET &SYSOUTTRAP = 1000
LISTCAT ENTRY(&MYDD) ALL
SET LINE001 = &&SYSOUTLINE1
SET &SYSOUTTRAP = 0
IF &STR(&SUBSTR(1:5,&STR(&LINE001 ))) = &STR(ALIAS) THEN +
     SET ISALIAS = Y
ELSE SET ISALIAS = N

/* ------------ */
/* CHECK IF GDG */
/* ------------ */
IF &STR(&GEN) = &STR() THEN SET J = 0
ELSE DO
       IF &GEN > 0 THEN +
       DO
         WRITE ERROR: INVALID OPTIONAL PARAMETER - GEN
         WRITE GEN SHOULD BE A NUMERIC GENERATION FOR GDG DATASET
         WRITE CURRENT VALUE IS <&GEN>
         WRITE BUT ITS VALUE SHOULD BE 0 OR NEGATIVE
         SYSCALL QUITING 22
       END
       SET MYDD = &STR(&MYDD(&GEN))
     END

/* ---------- */
/* SUBMIT JCL */
/* ---------- */
SET TMP1 =
IF      &ISALIAS = Y THEN SET TMP1 = ALIAS
ELSE IF &GDG = Y     THEN SET TMP1 = GDG
WRITE &PARM0 - DELETE &TMP1 DATASET &MYDD
SET XXX = &STR(//**)
SUBMIT * END($$)
//&SYSUID.D JOB (AAAAAA,BBBBBB),
//       '&SUBSTR(1:20,&STR(DELETE &SUF ))',
//       NOTIFY=&SYSUID,
//       CLASS=&CLASS,
//       MSGCLASS=X,MSGLEVEL=(1,1),
IF &USER ¬= THEN +
//       USER=&USER,
//       REGION=1M
&XXX
&XXX*******************************************************************
&XXX PURPOSE : BATCH DELETE DATASET
&XXX &STR(&MYDD)
&XXX JOB OWNER: &SYSUID
&XXX DATE : &SYSSDATE - &SYSTIME
&XXX*******************************************************************
&XXX
IF &ISALIAS = Y THEN DO
//DEL#ALIA EXEC PGM=IDCAMS
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
&STR( DELETE &STR(&MYDD) - )
&STR( ALIAS )
&STR(/* )
END
ELSE +
IF &GDG = Y THEN DO
//DEL#GDG EXEC PGM=IDCAMS
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
&STR( DELETE &STR(&MYDD) - )
&STR( GDG FORCE PURGE )
&STR(/* )
END
ELSE DO
//DEL#DD EXEC PGM=IEFBR14
//DD1 DD DISP=(OLD,DELETE,DELETE),
// DSN=&STR(&MYDD)
END
//
//
$$
WRITE JOB SUBMITTED
SYSCALL QUITING 0
END /* OF CLIST */


USAGE: PROC 0
/* ***************************************************************** */
/* PURPOSE: DISPLAY USAGE HELP
/* ***************************************************************** */
IF &OPREFIX = THEN SET PP =
          ELSE SET PP = &STR(&OPREFIX..)

WRITE &PARM0 - SUBMIT JCL TO DELETE A QSAM, A GDG BASE OR A GDG +
GENERATION
WRITE
WRITE EXAMPLE:
WRITE - &PARM0 MY.PROJECT.QSAM
WRITE DELETE THE QSAM DATASET '&STR(&PP)MY.PROJECT.QSAM'
WRITE - &PARM0 'MY.PROJECT.QSAM1'
WRITE DELETE THE QSAM DATASET 'MY.PROJECT.QSAM1'
WRITE - &PARM0 MY.PROJECT.GDGBASE GEN(0)
WRITE DELETE A GDG GENERATION '&STR(&PP)MY.PROJECT.GDGBASE(0)'
WRITE - &PARM0 MY.PROJECT.GDGBASE GEN(-1)
WRITE DELETE A GDG GENERATION '&STR(&PP)MY.PROJECT.GDGBASE(-1)'
WRITE - &PARM0 MY.PROJECT.GDGBASE GDG(Y)
WRITE DELETE A GDG BASE '&STR(&PP)MY.PROJECT.GDGBASE'
END /* OF PROC USAGE*/


QUITING: PROC 1 XCODE
/* ******************************************************************
/* PURPOSE: EXIT CLIST WITH ENVIRONMENT RESTORED
/* ******************************************************************
/* ------------------- */
/* RESTORE ENVIRONMENT */
/* ------------------- */
IF &OPREFIX ¬= THEN PROFILE PREFIX(&OPREFIX)

/* ---- */
/* EXIT */
/* ---- */
EXIT CODE(&XCODE)
END /* OF PROC QUITING */

With this CLIST, in the ISPF option 3.4 panel like this:

        ALVIN.PROJECT1.QSAM1                       DD1233
        ALVIN.PROJECT1.QSAM2                       DD1234
        ALVIN.PROJECT1.QSAM3                       DD1235
        ALVIN.PROJECT1.QSAM4                       MIGRAT
        ALVIN.PROJECT1.QSAM5                       MIGRAT
        ALVIN.PROJECT1.TAPE1                       T12345
        ALVIN.PROJECT1.TAPE2                       T12346
        ALVIN.PROJECT1.TAPE3                       T12347
I can do the following:
        ALVIN.PROJECT1.QSAM1                       DD1233
        ALVIN.PROJECT1.QSAM2                       DD1234
        ALVIN.PROJECT1.QSAM3                       DD1235
        ALVIN.PROJECT1.QSAM4                       MIGRAT
        ALVIN.PROJECT1.QSAM5                       MIGRAT
qdel / delete PROJECT1.TAPE1                       T12345
        ALVIN.PROJECT1.TAPE2                       T12346
        ALVIN.PROJECT1.TAPE3                       T12347
This will call QDEL to submit JCL to delete the tape dataset ALVIN.PROJECT1.TAPE1.



Alvin SIU
2008-11-11

Copyright/Licence Information:
All information and coding in this article is offered at no charge for NON-COMMERCIAL PERSONAL USE only.
This blog and the coding is copyright.
Reproduction of this blog and its coding in whole or in part in paper or digitally or in any other forms without the explicit written permission of the author is strictly prohibited.

Disclaimer:
All information in this article is distributed "as is" and is UNSUPPORTED.
NO WARRANTY of any kind is expressed or implied.
You use AT YOUR OWN RISK.
The author will not be liable for any data loss, damages, and loss of profits or any other kind of tangible or intangible loss while using or misusing wholly or partly of the information.

No comments:

Duplicate Open Current Folder in a New Window

Sometimes after I opened a folder in Win7, I would like to duplicate open the same folder again in another explorer window. Then, I can ope...