Copying MVS Datasets to Unix files

Recently I had to get some people started with a few utilities. I thought to share this here. They will be in the next few posts for searchability reasons.

There are more ways to Rome, as we say here, so please feel free share you variants in a comment. (I unfortunately need manually curate comments to filter out the spam which is even with this small site overwhelming.)

//STEP1 EXEC PGM=IKJEFT01
//INMVS DD DSN=TEST.TRADMVS.DATA,
// DISP=SHR
//OUTFILE DD FILEDATA=TEXT,
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=SIRWXU,
// PATH='/mydir/myunixfile.txt’
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*//SYSTSIN DD *
 OCOPY IND(INMVS) OUTDD(OUTFILE)
//*

Here’s a link to the IBM documentation on OCOPY.

Running a MVS or TSO Rexx program from the z/OS Unix environment

You probably know that you can use Rexx programs in z/OS Unix.

What you may not know is that you can also run a TSO or MVS Rexx program from the z/OS Unix environment.

There is a unix command called tso for this. It works as simple as this:

tso –t “exec ‘YOUR.MVS.REXXPDS(TESTREXX)’ EXEC”

will execute your TESTREXX program.

You may want or need to allocate TSO datasets or other datasets in order to execute the Rexx.

You can simply allocate these through the export command.

export ddname=YOUR.MVS.DATASET

You can add these exports to you shell script, or add them to your .profile.

z/OS Container Extensions Live demo

On 2 December, in a session organized by the Dutch GSE, the IBM User Group, specialists from the IBM Garage in Montpellier performed a presentation and live demonstration of running Linux containers in a z/OS Container Extension (zCX). After the session, there was a short discussion about use cases for z/OS Container Extensions, introduced by a view on this topic by Rabobank.

You can find the presentation in the GSE Google Drive: Link to the presentation

And we’ve also recorded the whole event, so you can watch it on the GSE NL YouTube channel:

Executing operator command froms batch – using Rexx and SDSF

One of the many way to execute an operator command from a batch rexx program.

With this solution here, with Rexx and SDSF, you can embed the commands in more complex business logic, and use Rexx variables to dynamically establish values for the commands to be issued.

By the way I have started a repository on GitHub on which I will share assets in the future.

https://github.com/execpgm/execpgm-assets

I have added this tool here:

https://github.com/execpgm/execpgm-assets/tree/master/Tools

Direct link:

https://github.com/execpgm/execpgm-assets/blob/master/Tools/OperatorCommandSDSFbatch.txt

//GENER   EXEC PGM=IEBGENER 
//SYSPRINT DD SYSOUT=* 
//SYSIN DD ,BLKSIZE=800,LRECL=80 
 GENERATE 
 LABELS DATA=ALL 
/*
//SYSUT1  DD *  
/* REXX /  
RC=ISFCALLS('ON')  
YOURSTC = "MYSTC"  
ADDRESS SDSF "ISFEXEC '/P "YOURSTC"'"  
ISFDELAY="5"  /* REPLY IS IN STEM ISFULOG. */ 
/*
//SYSUT2  DD  DSNAME=&&DS1(CMD),DISP=(NEW,PASS), 
//       UNIT=SYSDA,SPACE=(TRK,(5,,2)) 
//* 
//RDWRJ    EXEC PGM=IKJEFT01 
//SYSPRINT DD SYSOUT=* 
//SYSPROC  DD DISP=SHR,DSN=&&DS1 
//SYSTSPRT DD SYSOUT=* 
//SYSTSIN DD * 
 CMD 
/* 
//

COBOL 60 by one of the early adopters, Wim Ebbinkhuijsen

This year COBOL was delivered 60 years ago as one of the first general purpose, cross-platform programming languages.

On 8 January 1960 the ‘COBOL Executive Committee’ formally approved the design of the programming language “COBOL 60”.

One of the very early adopters of the programming language in the Netherlands, and long time member of the COBOL standard, Wim Ebbinkhuijsen, did a very nice talk at the event organized by Ordina. He went through the history of COBOL through the past 60 years. As a close observer and influencer of the programming language you get a great insight in this recent history of computing. Slides can be found here.

cobol arrives in the netherlands - slide by wim ebbinkhuijsen

A very short summary of replication solutions (for Db2)

Some time ago I did a short summary presentation on my experience with replication solutions for Db2 on z/OS. The pictures and text are quite generic, so I thought it might be worthwhile sharing the main topics here. The picture below summarizes the options visually:

Queue replication

Synchronizes tables. The synchronization process on the capture side reads the Db2 transaction log, and puts the updates for which a “subscription” is defined on a queue. On the apply side, the tool retrieves the updates from the queue and applies them to the target database.

SQL replication

Also synchronizes tables. In this case the capture process stores the updates in an intermediate or staging table, from which the apply process takes the updates and applies them to the target tables.

Data Event Publishing

Takes the updates to the tables for which a subscription is defined and produces a comma-delimited or xml message from it which is put on a queue. The consumer of the message can be any user-defined program.

Change Data Capture

CDC provides a flexible solution that can push data updates to multiple forms of target media, whether tables, messages or an ETL tool.

Requirements

After my short summary, we dug a little in the requirement’s for the specific problem this team was aiming to address. They needed:

  • A lean operational database for the primary processes.
  • Ad-hoc and reporting queries on archival tables, where data in archive table can be kept over several years.
  • The amount of data is relatively large: it should support tens to hundreds of millions of database updates per day, with a peak of tens of millions in an hour.
  • Target database management system was not decided yet; could be Db2 or Oracle.

So a solution should replicate the operational database to an archive database, while data must be very current, demanding near-realtime synchronization.

We focused a it on the Queue Replication solution. The target DBMS for Queue replication can be Db2, Oracle and SQL Server (and a few more). Furthermore, in my experience this solution can support:

  • High volumes in peak periods: millions of row inserted/updated in short period of time
  • Latency can remain within seconds, even in peak periods – this does require tuning of the solution, such as spreading messages over queues.For selected table you can specify suppress deletes, which allows for building up of historical data. 

There are a few concerns in the Queue Replication solution:

  • Data model changes will require coordination of changes in source, Queue Replication configuration and target data model.
  • Very large transactions (not committing often enough) may be a problem for Queue Replication (and also a very bad programming practice).

Hope this helps with your replication needs.

$ZOOM – Mother of all EDIT macro’s

The most useful ISPF EDIT macro ever. I think it was written by Paul van Goethem from Belgium, somewhere before 1993. It has quickly spread through many sites.

Point your cursor at at dataset name in a file your are editing en executing the macro will launch an EDIT session of that file.
I always put in under PF key PF4 which by default has the not very useful default value RETURN.

Note the value of the variable INVALID in the below may be corrupted. It should contain any character that is not valid as part of a dataset. The binary values it can contain are not very portable.

/****************************REXX***********************************/
/* FUNCTION: RECURSIVE EDIT OF BROWSE VIA DSNAAM AND,OR MEMBER     */
/*  SPECIFIED VIA CURSOR SENSITIVE EDIT MACRO                      */
/* FORMATS ACCEPTED:                                               */
/*  DATA.SET.NAME   : EDIT/BROWSE OF THIS                          */
/*  DATA.SET.NAME(MEMBER) : EDIT/BROWSE THIS                       */
/*  MEMBER    : EDIT/BROWSE IN SAME LIBRARY AS INDEX               */
/****************************REXX***********************************/  
ADDRESS ISPEXEC    INVALID= ",'\<\>,:;+��▖!�%�-="
ADDRESS ISREDIT 'MACRO (FUNCTIE)'
FUNCTIE = TRANSLATE(FUNCTIE)  
IF SUBSTR(FUNCTIE,1,1)='B'
THEN FUNCTIE='BROWSE'
ELSE FUNCTIE='EDIT' 
LIN=0 
ADDRESS ISREDIT '(LIN,COL) = CURSOR'  
ADDRESS ISREDIT '(CLINE) = LINE 'LIN   
/* FIND CURRENT WORD */ 
T=SUBSTR(CLINE,1,COL)  
T =TRANSLATE(T,' ',INVALID)    
Y=LASTPOS(' ',T) 
IF Y=0
THEN T=CLINE    
ELSE T=SUBSTR(CLINE,Y+1)
PARSE VAR T WOORD  .   
WOORD =TRANSLATE(WOORD,' ',INVALID)
"CONTROL ERRORS RETURN"
IF INDEX(WOORD,'(') /= 0 THEN DO /* TAKE DSN IF SPECIFIED */
  PARSE VAR WOORD  DSNAME '('  MEMBER ')' 
  FUNCTIE" DATASET('"SPACE(DSNAME)"("MEMBER")')" 
  FRC=RC
  END
ELSE DO
  IF INDEX(WOORD,'.')/=0 THEN DO   
    PARSE VAR WOORD  DSNAME . 
    FUNCTIE" DATASET('"SPACE(DSNAME)"')" 
    END  
  ELSE DO         
    ADDRESS ISREDIT "(DSNAME) = DATASET"  
    WOORD = SPACE(TRANSLATE(WOORD,' ','.()'))
    FUNCTIE" DATASET('"DSNAME"("WOORD")')"  
    END    
  FRC=RC   
  END  
ADDRESS ISPEXEC "CONTROL ERRORS CANCEL"  
IF FRC> 4 & SYMBOL(ZERRMSG)/= 'LIT' THEN DO      
  MSG= ZERRMSG':'ZERRLM            
  "SETMSG MSG(ZOM000A)"            
  END                           
RETURN