Wednesday, May 25, 2011

Online project with COBOL and Rexx

Hi guys, I got one real-time processing project with COBOL and Rexx. This project is using ISPF services to invoke the load module. we say this is an ultra mini project, since we do not have any complicated code or operations in it. Since we are invoking the load module dynamically (using ispf services), we cannot use jcl to allocate the data set for our program; so I have use “PUTENV” to allocate the vsam file for our program.

Bullet points of Project.

1. using Dynamic vsam file allocation.

2. Dynamically invoking load module using rexx.

Step 1 Download source and dependent data sets

I have xmitted the binary files of the project from my mainframe and uploaded to some file sharing service, you can download the zipped files from the below link.

http://www.mediafire.com/?zlozknvj77z5vmd

The Project source codes are free of cost and there is nothing will stop you from downloading the code.

Step 2 Upload binary files to mainframe and expand them

Download the zip file from the above link, unzip into your local folder. then you can upload them using a mainframe emulator or FTP service of windows or Linux. Please read the Step 2. Uploading files and Step 3 Inflating binary files of our first project from the below link.

http://mainframegeek.wordpress.com/2011/04/25/mainframe-projects/

Files contained in the Zip file

INDEXFLE.SRCE
INDEXFLE.JCLS
INDEXFLE.EXECPGM

Once you did Step 3. inflating binary files, by default the files will be stored in the below names.

TSHRCI.INDEXFLE.EXECPGM
TSHRCI.INDEXFLE.JCLS
TSHRCI.INDEXFLE.SRCE

Step 3 lets have a look on data sets.

TSHRCI.INDEXFLE.EXECPGM is a ps and it is a Rexx code which is used to invoke the load module from TSHRCI.LOAD.LIB .

Following code is the heart of our program, which is invoking indxfle (load module) from TSHRCI.LOAD.LIB pds.

address ispexec
"libdef ispllib dataset id('TSHRCI.LOAD.LIB')"
pgm=indxfle
"select pgm("pgm")"

TSHRCI.INDEXFLE.JCLS is a pds and contained fillowing members

BATCHCOB
COBCPL
VSAMGEN

Batchcob and COBCPL are two different compile JCL’s for Cobol compiler. BATCHCOB Since I’ve been working on a internal mainframe connection the proc was different So I had to use a customized JCL to compile my code, they have modified IGYWCL proc according to their needs. COBCPL   This should work on almost all mainframes with Cobol ver 4.1, since its making use of default IGYWCL.

VSAMGEN. Is used to generate the Vsam file which we are using in our project. Once you executed the JCL, you can see that the following files has been generated. which is a must before executing our program.

TSHRCI.INDXFLE.FILE1
TSHRCI.INDXFLE.FILE1.DATA
TSHRCI.INDXFLE.FILE1.INDEX

/* DELETE KSDS CLUSTER, IF IT EXISTS                      */
DELETE TSHRCI.INDXFLE.FILE1 CLUSTER PURGE
/* DEFINE KSDS CLUSTER                                    */
DEFINE CLUSTER (                                          -
NAME(TSHRCI.INDXFLE.FILE1)                   -
VOLUMES(ETRU06)                              -
RECORDSIZE(80 80)                            -
RECORDS(50 10)                               -
KEYS(02 0)                                   -
INDEXED )                                    -
DATA (                                             -
NAME(TSHRCI.INDXFLE.FILE1.DATA) )            -
INDEX (                                            -
NAME(TSHRCI.INDXFLE.FILE1.INDEX) )
IF LASTCC = 0 THEN                                        -
LISTCAT ALL LEVEL(TSHRCI.INDXFLE)

Above code is the important part of VSAMGEN, It will delete vsam cluster if existing, create new cluster, index and data data sets.If you are running the JCL for the first time you will get Maxcc 8, since cluster is not existing in system. The line which marked in red color is not mandatory if your mainframe is  SMS managed. “ETRU06” is the DASD vol ser# where we need our vsam file. Read Redbook on below link to know more about SMS.

http://www.redbooks.ibm.com/abstracts/sg245484.html

TSHRCI.INDEXFLE.SRCE, is a pds and contained “INDXFLE” which is source code of our project. As I said this project is very small and does not have any complicated logics or functionalities in it. The advantages are we are using Dynamic vsam file allocation and invoking load module dynamically using ispexec service.

Step 4 Key parts of Program

.

Dynamic File allocation.

01  FILE-DATA.
05  FILE-PTR                POINTER.
05  FILE-NAME.
10                      PIC X(12)
VALUE 'DYNVSAM=DSN('.
10  dsname              PIC X(60).
10                      PIC XX VALUE Z' '.
05  RC                      PIC S9(9) BINARY VALUE 0.
05  in-name                 pic x(40).

In order to allocate file, we need to tell which file we need to allocate and how we need to do it (Disp) So we need to have the above code in working storage section. once the allocation is done the return code (from PUTENV) will be stores in RC. 10                      PIC XX VALUE Z' '. is filler and says that it null terminated string.

move 'TSHRCI.INDXFLE.FILE1'
to in-name.
string in-name delimited by space
') SHR' delimited by size into dsname.

Above code will concatenate vsam cluster dsn with disposition and other data and move to fFILE-NAME data name.

set file-ptr                to address of file-name.
CALL 'PUTENV'
USING BY VALUE FILE-PTR
RETURNING RC.

Above line sets the address pointer of file name to FILE-PTR and calls PUTENV using FILE-PTR. PUTENV will allocate the file wich FILE-PTR points and  return the status of allocation, which will be stored in RC, if RC is –1 then allocation was failure, 0 means allocation was success.

Step 5. Compile and execute the program

Compile

Run BATCHCOB and JCL should return MAXCC 0, and will happen with the provided source code.

Create TSHRCI.LOAD.LIB if not existing before you compile the project.

Executing project

Execute TSHRCI.INDEXFLE.EXECPGM rexx code by putting an “EX” before the file name.

image

and Press Enter which will invoke INDXFLE from TSHRCI.LOAD.LIB, if the compilation was failure then which will give you an error. Please verify that you have created TSHRCI.,LOAD.LIB before compiling the source code and the compilation was successful.

image

Its the fist line in our Project which is to bring up the options in a brand new screen, press enter to continue.

image

Chose any of the options by entering the number and hit enter.

image

image

image

image

image

press enter to come out of this screen. When ever we are performing some actions on data set, our program will set the return code of our Project based on the file status. And the rexx code will evaluate the return code of the project.

image

Friday, May 13, 2011

Setting MAXCC in JCL using IDCAMS

Day to day programming life we will face a lot situations where we need to set MAXCC or return code of JCL whether conditionally or unconditionally. There a are lot of possible ways to do achieve this when we execute program like (set return-code in Cobol, set RC in REXX etc..). but what we will do when we need to set MAXCC using JCL?, how to achieve this??.

One possible solution is set MAXCC using IDCAMS, since IDCAMS is available all the shops there are no pre-requisites for this. .

How to setup MAXCC of JCL using IDCAMS?

You just need to code SET MAXCC=<return code> in the SYSIN dataset of IDCAMS.

What are the limits for SET MAXCC command of IDCAMS

You can use any value as return code from 0 to 16, all the values out of this range will cause a MAXCC 16  for the JCL

Sample JCL to set MAXCC

d ===>                                                  Scroll ===> CSR 
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
***************************** Top of Data ******************************
//R0318BMJ  JOB  (ACCNT#,&SYSUID),'SHIBU THANNIKKUNNATH',NOTIFY=&SYSUID
//          EXEC PGM=IDCAMS                                            
//SYSPRINT  DD   SYSOUT=A                                              
//SYSIN     DD   *                                                     
   /* CHANGE THE BELOW MAXCC TO A NUMBER BETWEEN 0 AND 16*/             
   SET MAXCC=16                                                         
/*                                                                     
**************************** Bottom of Data ****************************

Screen shots

image

image

Thursday, May 12, 2011

Steps in a COBOL-DB2 Program

When I started exploring DB2-COBOL programs over internet,  I realized that we haven’t got a lot of tutorials for Cobol-db2 programs over there. So I thought I can share some of my programs with all of you. My Cobol-DB2 program is very small, but it could help us to understand the structure, how to compile, how to bind and how to run very well.

 

Step 1. DB2 Table structure.

---------+---------+
SEQ  NAME          
---------+---------+
001  SHIBU         
002  SABU          
003  BALANKRISHNAN 
004  SREEMATHY
     

This is my table it has only two columns, first 3 var char for sequence numbrs and next 15 var char for Name field.

Create table:

Go to SPUFI create our table using the following SQL statements.

CREATE TABLE MYNAM        
    ( SEQ    VARCHAR(03), 
      NAME   VARCHAR(15));

INSERT INTO MYNAM VALUES(‘001’,’SHIBU’);
INSERT INTO MYNAM VALUES(‘002’,’SABU’);
INSERT INTO MYNAM VALUES(‘003’,’BALAKRISHNAN’);
INSERT INTO MYNAM VALUES(‘004’,’SREEMATHY’);

COMMIT;

Step 2. Execute DCL gen to create copybook for table.

Navigate to DB2I primary options and select DCLGEN

image

Now Enter table name (mynam) in source table name, location for copybook ( 'TSHRCI.PGMG.CICOB(mynam)' in our program )on dataset name field and type ADD in action field .You can leave default values in rest of the fields. Then press enter.

image

You can verify that, whether copy book generated on the given pds.

Step 3. Code the application. ( cobol db2 sample code)

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
***************************** Top of Data ******************************
       IDENTIFICATION DIVISION.                                        
       PROGRAM-ID. MYTAB.                                              
       AUTHOR.     SHIBU.T                                             
       DATA DIVISION.                                                  
       WORKING-STORAGE SECTION.                                        
 
          EXEC SQL                                                    
             INCLUDE MYNAM                                             
           END-EXEC.
                                                   
           EXEC SQL                                                    
             INCLUDE SQLCA                                             
           END-EXEC.
                                                   
       01  WS-ROLL-NO                         PIC X(3)
VALUE IS '000'. 
       01  WS-ROLL-N1                         PIC 9(3).                
       01  WS-NAME                            PIC X(15).               
       01  WS-SQLCODE                         PIC --------9.           
       PROCEDURE DIVISION.                                             
       PARA-00100-MAIN.                                                
           DISPLAY 'EXECUTION STARTED.'.                               
           MOVE 0                             TO WS-ROLL-N1.           
           PERFORM UNTIL WS-ROLL-NO = '001'                            
             COMPUTE WS-ROLL-N1 = WS-ROLL-N1 + 1                       
             MOVE WS-ROLL-N1                  TO WS-ROLL-NO            
             PERFORM PARA-00200-FETCH THRU PARA-00200-FETCH-EXIT       
           END-PERFORM.                                                
           STOP RUN.                                                   
                                                                       
       PARA-00200-FETCH.                                               
           DISPLAY 'PARA-00200-FETCH.'.                                
          
EXEC SQL                                                    
             SELECT *                                                  
               INTO : DCLMYNAM                                          
             FROM MYNAM                                                
             WHERE SEQ = : WS-ROLL-NO                                   
           END-EXEC.
                                                   
          
IF SQLCODE = 0                                              
             DISPLAY 'EXECUTION SUCESS!'                               
             PERFORM PARA-00300-PRINT THRU PARA-00300-PRINT-EXIT       
           ELSE                                                        
             DISPLAY 'FETCH FAILED!, PROGRAMM TERMINATING.'            
             MOVE SQLCODE                     TO WS-SQLCODE            
             DISPLAY 'SQL CODE FROM LAST FETCH: ' WS-SQLCODE           
           END-IF.
                                                     
       PARA-00200-FETCH-EXIT.                                          
           EXIT.                                                       
                                                                       
       PARA-00300-PRINT.                                               
           DISPLAY 'NAME IS >> ' NAME ' <<'.                           
       PARA-00300-PRINT-EXIT.                                          
           EXIT.

Step 4. key elements of COBOL DB2 program.

a) Include tables copy book and SQLCA.

We have to include the copy book of table which we desired to use on our app. syntax is follows

EXEC SQL       
  INCLUDE MYNAM
END-EXEC.      

Also it is important that including SQL communication area copybook into our program. Syntax follows.

EXEC SQL        
  INCLUDE SQLCA 
END-EXEC.       

Read more about SQL CA on IBM redbooks

b) Define Host variables and variable for SQL.

Hold on! best practice ahead.  High five High five High five High five High five High five High five

It will be readlly good if you declare SQLCODE variable as following.

01  WS-SQLCODE                         PIC --------9.

So whenever a value move into SQLCA, all the negative sql codes will have a – symbol and positive sql codes will be just number, so that we can differentiate both error codes.

Since it is sample program and the intention is to describe the flow of Cobol-DB2 program, I haven’t included the cursors or complex sql statements on our program, I’ll be adding more programs in coming days.

Step 4 Compile and BIND COBOL-DB2 Program

image

Above Diagram is pretty well describes the whole process of compiling a cobol DB2 program. As I mentioned in the image, precompile step I sno longer required in the latest releases of Cobol, the compiler itself is capable of doing this task.

Step 5. RUN Program

When COBOL-DB2 Program executes, the plan and Package must specified in the SYSIN, When the first sql statement of our program executes, db2 search the collections and consistency token in the provided plan using the provided package name, if the consistency token is not matching gDB2 throw a -805 Error.

 

Cobol-DB2-Compile-BIND-RUN JCL.

//R0318BDJ JOB (12345678),MSGCLASS=H,REGION=4M,                    
//        MSGLEVEL=(1,1),CLASS=A,NOTIFY=&SYSUID                   
//*                                                               
//JOBLIB    DD DSN=DSN910.DB9G.SDSNEXIT,DISP=SHR                  
//          DD DSN=DSN910.SDSNLOAD,DISP=SHR                       
//*****************************************************************
//* SQL PREPROC AND COBOL COMPILATION:                            
//*****************************************************************
//*-NB---SQL PREPROC NOW IS NOW DONE BY THE COBOL COMPILER:       
//*****************************************************************
//COB     EXEC  PGM=IGYCRCTL,                                     
//            PARM=(SQL,LIB,NOTERM,NOSEQUENCE,LIB,XREF,DYN,'')    
//STEPLIB   DD DSN=IGY410.SIGYCOMP,DISP=SHR                       
//          DD DSN=DSN910.SDSNLOAD,DISP=SHR                       
//DBRMLIB   DD DSN=TSHRCI.PGMG.DBRM(MYTAB),DISP=SHR  <<Desired DBRM Loc
//SYSIN     DD DSN=TSHRCI.PGMG.COBOL(MYTAB),DISP=SHR <<SRCE LIB      
//SYSLIB    DD DSN=TSHRCI.PGMG.COBOL,DISP=SHR <<CPYBK LIB                
//SYSLIN    DD DSN=&&LOADSET,DISP=(MOD,PASS),UNIT=SYSDA,          
//             SPACE=(800,(500,500))                              
//SYSPRINT  DD SYSOUT=*                                           
//SYSUDUMP  DD SYSOUT=*                                           
//SYSUT1    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//SYSUT2    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//SYSUT3    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//SYSUT4    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//SYSUT5    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//SYSUT6    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//SYSUT7    DD SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA           
//*****************************************************************
//*            LINKEDIT                                           
//*****************************************************************
//LKED    EXEC PGM=IEWL,PARM='XREF',COND=(4,LT,COB)               
//SYSLIB   DD  DISP=SHR,DSN=CEE.SCEELKED                          
//         DD  DISP=SHR,DSN=DSN910.SDSNLOAD                       
//         DD  DISP=SHR,DSN=DFH320.CICS.SDFHLOAD                  
//         DD  DISP=SHR,DSN=ISP.SISPLOAD                          
//         DD  DISP=SHR,DSN=GDDM.SADMMOD                          
//SYSLIN    DD DSN=&&LOADSET,DISP=(OLD,DELETE)                    
//          DD DDNAME=SYSIN                                        
//SYSLMOD   DD DSN=TSHRCI.LOAD.LIB,DISP=SHR <<desired LOAD LIB 
//SYSPRINT  DD  SYSOUT=*                                           
//SYSUDUMP  DD  SYSOUT=*                                           
//SYSUT1    DD  SPACE=(1024,(50,50)),UNIT=SYSDA                    
//SYSIN     DD *                                                   
     NAME MYTAB(R)  << Program Name                                 
/*                                                                 
//*****************************************************************
//* BIND                                                           
//*****************************************************************
//BIND    EXEC PGM=IKJEFT01,DYNAMNBR=20,COND=(4,LT)                
//DBRMLIB   DD DSN=TSHRCI.PGMG.DBRM,DISP=SHR                       
//SYSTSPRT  DD SYSOUT=*                                            
//SYSPRINT  DD SYSOUT=*                                            
//SYSUDUMP  DD SYSOUT=*                                            
//SYSOUT    DD SYSOUT=*                                            
//SYSTSIN   DD *                                                   
  DSN SYSTEM(DB9G) <<Change this to your DB2 subsystem>>    
  BIND PLAN(MYTABP) MEMBER(MYTAB) -                                
        ACT(REP) ISO(CS) ENCODING(EBCDIC)                          
  END                                                              
/*                                                                 
//*****************************************************************
//* RUN PGM                                                        
//*****************************************************************
//RUNPGM   EXEC PGM=IKJEFT01,DYNAMNBR=20 COND=(4,LT)               
//STEPLIB  DD DSN=DSN910.SDSNLOAD,DISP=SHR                         
//SYSTSPRT DD SYSOUT=*                                             
//SYSPRINT DD SYSOUT=*                                             
//SYSUDUMP DD SYSOUT=*                                             
//SYSOUT   DD SYSOUT=*                                             
//SYSTSIN DD *                                                     
DSN SYSTEM(DB9G) <<Change it to your db2 subsystem>>        
RUN PROGRAM(MYTAB) PLAN(MYTABP) LIB('TSHRCI.LOAD.LIB')            
END                                                               
//*

Screen shots

image

image

Thursday, May 5, 2011

String and Unstring

Today we are are gonna discuss the String and Unstring statements of Cobol. These statements are used for concatenate or parse a string/or characters. These statements are utilizing Identification division to get the desired results. these statements will remove the multiple instances of delimiter character.All the embedded spaces will be treated as a single space. A new field or a string is created with the leading spaces removed and all multiple embedded spaces reduced to a single space. The length of the actual text within the output field is also provided.

Unstring.

Is used to split the given string into a single or multiple data names, with a delimiter character( lets say space) .

Syntax: unstring <input_data_name>  delimited by space  into <data_name_1> <data_name_2>

e.g. UNSTRING WS-FULL-NAME       DELIMITED BY SPACE  INTO WS-FIRST-NAME WS-LAST-NAME.

String.

String used to concatenate to or more data names.

Syntax: string <dataname_i> delimited by space <dataname_2> into <output_data-name>

e.g. STRING WS-FIRST-NAME   DELIMITED BY SPACE  WS-LAST-NAME DELIMITED BY SPACE INTO WS-FULL-NAME.

Code:

Sample Program:

IDENTIFICATION DIVISION.                                        
PROGRAM-ID. VSTRING.                                            
AUTHOR    . SHIBU.T.                                            
*                                                                
DATA DIVISION.                                                  
WORKING-STORAGE SECTION.                                        
77  WS-FULL-NAME                PIC X(30).                      
77  WS-FIRST-NAME               PIC X(05).                      
77  WS-LAST-NAME                PIC X(15).                      
*                                                                
EJECT.                                                          
PROCEDURE DIVISION.                                             
A00100-MAIN-LINE.                                               
     DISPLAY '***STRING***'.                                     
     MOVE 'SHIBU'                TO WS-FIRST-NAME.               
     MOVE 'THANNIKKUNNATH'       TO WS-LAST-NAME.                
     STRING WS-FIRST-NAME        DELIMITED BY SPACE              
            ' '                  DELIMITED BY SIZE               
            WS-LAST-NAME         DELIMITED BY SPACE              
                                 INTO WS-FULL-NAME.              
     DISPLAY 'FIRST NAME: ' WS-FIRST-NAME.                       
     DISPLAY 'LAST  NAME: ' WS-LAST-NAME.                        
     DISPLAY 'FULL  NAME: ' WS-FULL-NAME.                        
     DISPLAY '**UNSTRING***'.                                    
     MOVE SPACES TO WS-FIRST-NAME, WS-LAST-NAME.                 
     UNSTRING WS-FULL-NAME       DELIMITED BY SPACE              
                                 INTO WS-FIRST-NAME WS-LAST-NAME.
     DISPLAY 'FULL  NAME: ' WS-FULL-NAME.                        
     DISPLAY 'FIRST NAME: ' WS-FIRST-NAME.                       
     DISPLAY 'LAST  NAME: ' WS-LAST-NAME.                        
     EXIT.                                                       
     STOP RUN.                                                   

 

outputs:

image