NESUG 15 Posters

PC TVS - - Say What? Process, Connect, Transfer, Validate, Send (email) Stephen Rhoades IMS HEALTH Inc., Plymouth Meeting, Pa. reporting. The MVS system can easily handle ABSTRACT large volumes of data with relative ease, while the system provides on demand Ever process on one platform and send data processing. to another? How do you know all of your data has actually arrived? How do you let everyone SAS provides a great way to allow for know the data has been sent and is ready for processing on one platform, connecting to use? SAS has a way. another, downloading to it, verifying the results and notifying concerned parties that Time to break down 'PC TVS’; it's not the data is ready to use. Personal computers and televisions. It stands for PROCESS, CONNECT to another The process involves upfront processing on computer, TRANSFER data, VERIFY the the MVS mainframe, which automatically data has been sent and received, and then sends data to the desired destination on Unix. SEND e-mails to let everyone know the data is The record counts are verified and e-mails are ready for use. This can all be done sent as notification. automatically using SAS Connect, some macros and the Base SAS e-mail capabilities. MVS (an IBM mainframe) uses JCL ( In case you have been using FTP, this is ) to run jobs, it will be better. You know for sure what was sent is briefly covered at the end of the paper, at this what was received and manually contacting juncture just be aware of these facts. The interested parties is eliminated. jobs are automated; file names and some parameters are passed into the following SAS program via the JCL. INTRODUCTION In today’s world of computing, the platform you create files on, and where they are used can be very different. Some companies PROCESS restrict access to production computers; final /*------*/ results are made available somewhere else. /* MOVE FILES FROM MVS TO UNIX*/ /*------*/ Sometimes only a particular computer has key software needed to complete a process. For example SAS Enterprise Miner may be /*------*/ installed on an NT server and may be needed /* If an error abend the job */ by your process that is running on an MVS or /*------*/ Unix system. Sometimes it just may be easier OPTIONS ERRORABEND; or faster to work with the results on another computer. Whatever the reason, working /*------*/ with multiple computers is very commonplace /* Include contains IP address*/ nowadays. /*------*/ %INCLUDE I4UNXCDE; In our case we have a system running on an MVS system and the end data users need it on RUN; a Unix system. The MVS portion of the The “%INCLUDE I4UNXCDE” brings in system is primarily stored on cartridges. The a text file of SAS code containing the Unix system is primarily a disk file system IP address of the remote host. The IP containing final results used for custom

1 NESUG 15 Posters

address contains a number used by the /*------*/ /* PASS UNIX LIBRARY FROM -*/ system to locate the Unix computer. /* SYSPARM BY SETTING IT UP IN*/ Since this address changes on occasion /* VARIABLE */ it was put in a single location and is /*------*/ included in all jobs needing it. When UNIXLIB=SUBSTR(SYSPARM(),5); PUT UNIXLIB=; the IP address changes, a quick change CALL SYMPUT('UNIXLIB',UNIXLIB); to this file eliminates a lot of RUN; headaches. As long as SAS and SAS For those of you unfamiliar with Connect are on a platform and the SYSPARM, it provides a way of passing “spawner” is up and running, specifying values to the SAS program. In this the IP address will be the same case this program runs a number of although the actual number will be times with different data year files. different. See NOTE1 for the Also the directory path on Unix changes I4UNXCDE contents. from run to run. See NOTE2 to see

how this comes in from the JCL LPUT TO PASS MACRO VARS /***************************************/ stream. /* SYSLPUT IS THE OPPOSITE OF SYSRPUT.*/ /*SYSLPUT CREATES A MACRO VARIABLE IN */ /*THE REMOTE ENVIRONMENT. THE USER MUST*/ READING FILE RECORD COUNTS /*SPECIFY THE MACRO VARIABLE AND ITS */ /*------*/ /*VALUE. OPTIONALLY, THE USER MAY */ /*- READ IN RECORD COUNTS FOR */ /*SPECIFY THE REMOTE SESSION ID; THE */ /*- THE INPUT TAPE FILE -*/ /*DEFAULT SESSION IS CURRENT SESSION. */ /******************************* /*------*/ DATA _NULL_; %MACRO LPUT(MACVAR,MACVAL,REMOTE=); SET I1IN.PxxOBS_&DYR; OPTIONS NOSOURCE NONOTES; PUT _ALL_; %LET STR=%STR(RSUBMIT CALL &REMOTE;OPTIONS NOSOURCE;) SYMPUT("MVSCNTF",OBS_COUNT); %NRSTR(%LET) %STR(&MACVAR = RUN; &MACVAL;OPTIONS SOURCE;ENDRSUBMIT;); &STR; OPTIONS NOTES SOURCE; Since this example the SAS file resides %MEND LPUT; on tape, the record counts are not RUN; available. To solve this problem a file Normally a macro value from one containing a single record is created platform cannot be used on another. with the tape file record count on it This macro allows for exactly that. when the tape file is created. See The %LPUT macro is used later in the NOTE3 for the code that does this. program for sending the Unix directory, If your SAS file resides on disk this is data year and MVS file record count unnecessary, record counts are macro variables from MVS to the Unix available in the Dictionary.Tables, see system. code under heading “VALIDATE RECORD COUNTS” for an example. SYSPARM VALUES /*------*/ /*PASS IN DATAYEAR TO MACRO -*/ CONNECT /*------*/ /*------*/ /*- LOC OF UNIX SIGNON SCRIPT FILE*/ DATA _NULL_; /*------*/ LENGTH DYR $ 4 ; SIGNON I3RLINK ; DYR=SUBSTR(SYSPARM(),1,4); CALL SYMPUT('DYR',DYR); I3RLINK is what SAS uses to sign onto another platform. When the program

2 NESUG 15 Posters

runs, SAS goes to I3RLINK and reads SAS handles any translation issues; its contents. As new versions of SAS however, it does not make record are released, SAS and/or your site may counts available. modify this file. Also for maintenance it is better to only have one location to VALIDATE RECORD COUNTS change rather than every program that /*------*/ needs it. For more information /*- CHECK REC COUNTS OF UNIX */ /*- AND MVS FILES -*/ contact the author. /*------*/ %MACRO PASS MACRO VALUES TO UNIX CHKSEL(LIBNAM,MEMNAM,MVSCTR); /*------*/ /* PASS THE UNIX LIBRARY TO -*/ PROC SQL; /* The Unix System from MVS -*/ SELECT NOBS /*------*/ INTO :UNXCNT /*rec count*/ DATA _NULL_; FROM DICTIONARY.TABLES WHERE LIBNAME="&LIBNAM" AND %LPUT(UNIXLIB,&UNIXLIB,REMOTE=RMT); MEMNAME="&MEMNAM"; %LPUT(DYR,&DYR,REMOTE=RMT); QUIT; %LPUT(MVSCNTF,&MVSCNTF,REMOTE=RMT); RUN; /*RECORD COUNT ON MVS*/ RUN; %IF &UNXCNT EQ &MVSCTR %THEN %LPUT is sending macro variables from %DO; %LET ERRCNT=F; MVS to Unix containing the location of %END; the Unix directory, a four digit year to %ELSE %DO; use in the file names and the number of %LET ERRCNT=T; records being sent from MVS. %END; /*------*/ /*- SEND MACRO VALUES FROM */ RUNNING REMOTELY /*- UNIX TO MVS -*/ /*------*/ /*------*/ /* REMOTE SUBMIT FOR UPLOAD OF*/ %SYSRPUT ERRCNT=&ERRCNT; /* MAINFRAME FILES TO UNIX */ %SYSRPUT MEMNAM=&MEMNAM; /*------*/ %SYSRPUT UNXCNT=&UNXCNT; RSUBMIT I3RLINK ; %SYSRPUT MVSCTR=&MVSCTR;

LIBNAME RMTLIB "&UNIXLIB"; %PUT END OF MACRO CHKSEL ; RSUBMIT I3RLINK begins the %MEND CHKSEL ; processing on a remote system, in this RUN; case a Unix system. It continues until ENDRSUBMIT is encountered. Note the /*------*/ LIBNAME reference &UNIXLIB, it is /* CHECK THE FILE COUNTS OF */ /* SEND AND RECEIVED FILES */ the Unix directory name passed over /*------*/ from the MVS system using %LPUT. %CHKSEL(RMTLIB,xxF_&DYR,&MVSCNTF); RUN; TRANSFER PROC UPLOAD DATA=I1IN.xXF_&DYR /*------*/ OUT=RMTLIB.xXF_&DYR; /* END OF REMOTE SUBMIT */ /*------*/ Sending file from MVS to Unix system ENDRSUBMIT ; ! finished on Unix with Proc Upload. It is quick, easy and

3 NESUG 15 Posters

The above section of code contains and Rest of error report code removed ABORT ABEND 667; executes the CHKSEL macro then ends %MEND ERRABND1; the processing on the Unix system. RUN; MVS macros &DYR (4 digit data year) Macro ErraAbnd1 only executes if the and &MVSCNTF (MVS record count) are record counts of the sent and received passed into the &CHKSEL macro. The files do not match. It first writes an dictionary.table code yields record error report and then abends the job counts of the newly arrived Unix file, with a condition code of 667. It runs storing this in the macro variable from within the next macro Errrpt. UNXCNT. Using %SYSRPUT a number of macro variables are sent back to SEND MVS, including &ERRCNT, which /*------*/ indicates success or failure of the data /* MACRO ERRRPT -*/ transfer. The ENDRSUBMIT /* PRINT AN ERROR RPT IF THE -*/ statement ends the remote (Unix) /* FILE REC COUNTS DO NOT -*/ /* MATCH BETWEEN MVS AND UNIX-*/ processing and resumes local (MVS) /*------*/ processing. %MACRO ERRRPT;

BACK TO MVS %INCLUDE I5SENDTO; /*------*/ /* NOW BACK ON MVS */ %IF &ERRCNT EQ F %THEN %DO; /*------*/ %PUT COUNTS OF FILES MATCH %PUT ON MVS ERRCNT=&ERRCNT &UNXCNT = &MVSCTR; MEMNAM=&MEMNAM UNXCNT=&UNXCNT MVSCTR=&MVSCTR; DATA _NULL_; FILE MYMAIL; *------; PUT "DATA FILES FOR QUARTER *- THIS MACRO WILL ABEND THE JOB -; NOW AVAILABLE ON UNIX"; *- WHEN THE MVS REC COUNTDOES NOT -; RUN; *- EQ UNIX REC COUNT -; %END; *- PARAMETERS: -; %ELSE %DO; *- UNXCNT = NBR OF RECS ON UNX -; %PUT FILES DONT MATCH, UNIX *- MVSCTR = NBR OF RECS FROM MVS -; &UNXCNT NOT EQUAL MVS &MVSCTR; *- MEMNAM = SAS FILE NAME -; DATA _NULL_; *------; FILE MYMAIL; %MACRO PUT "DATA LOAD FOR QUARTER ERRABND1(UNXCNT,MVSCTR,MEMNAM); FAILED CALL OPERATIONS";

%PUT UNIX COUNT =****&UNXCNT***; CALL EXECUTE %PUT MVS COUNT =****&MVSCTR***; ('%ERRABND1('||"&UNXCNT"||','||" &MVSCTR" ||','||"&MEMNAM" |')'); DATA _NULL_; %END; FILE O8ABEND; LENGTH OUTTEXT $60 ; %MEND ERRRPT; ASTR=REPEAT('*',62); PUT @10 ASTR @73 '0667' @77 '0001'; RUN; PUT @11 'ERROR - RECS SENT TO /*------*/ UNIX DO NOT MATCH MVS COUNT' /* RUN ERRRPT MACRO -*/ @73 '0667' @77 '0001'; /*------*/ PUT @10 ' ' @73 '0667' @77 0001'; OUTTEXT = "ERROR - MVS RECORD COUNT %ERRRPT; = " || COMPRESS("&MVSCTR") || " " || RUN; 'UNIX RECORD CNT=' ||

4 NESUG 15 Posters

Macro ERRRPT compares record counts. APPENDIX: JCL & NOTES It sends emails to notify whether the file transfer was successful or not NOTE1: I4UNXCDE SAS CODE successful. The actual email addresses Data _NULL_; are kept in a text file and read into Length RMT $ 14; /*IP address len*/ the SAS stream through %include RMT="000.00.00.0"; /* HP UNIX*/ I5SENDTO, see NOTE4 for contents. Call Symput('RMT',RMT); If not successful, CALL EXECUTE is Run; used to run the ERRABND1 macro. OPTIONS REMOTE=RMT COMAMID=TCP; CALL EXECUTE allows a DATA step to The “%INCLUDE I4UNXCDE” brings in run while still within another. a text file of SAS code containing the IP address of the remote host. The IP /*------*/ address contains a number used by the /* SIGN OFF OF UNIX SYSTEM */ /*------*/ system to locate the remote computer. SIGNOFF I3RLINK; Since this address changes on occasion Sign off Unix and end the SAS Program it was put in a single location and read into all jobs needing this information. When the IP address changes, a quick CONCLUSION change to this file eliminates a lot of SAS provides some powerful tools to headaches. As long as SAS and SAS create an automated system to run Connect are on a platform and the between platforms and provide “spawner” is up and running, specifying instant notification when needed files the IP address with SAS can be done are ready to use. In this paper the use as shown. of SAS Connect and SAS base email capabilities provided the means to build a system that is completely JCL AND PROC CODE automated. Once a year some parameters are changed and the jobs //XXXUQ40 JOB 12345,'FILE DOWNLOAD',CLASS=Z,MSGCLASS=W run on a regular schedule. Using //JOBLIB these techniques reduce manpower DSN=IMS.LOADLIB,DISP=SHR requirements and potential human //J01DNLD EXEC XXXU040, // PYEAR4=2001, error. Although this was written for // P1YEAR4=2000, MVS and Unix, it can be easily // P2YEAR4=1999, adapted for other systems, as the SAS // P3YEAR4=1998, // YEAR4=2002, code would stay pretty much intact. If #JI,ID=030 you have multi-platform applications // QTR=1 #JI,ID=060 you may want to consider the // PATH='/abc31/', techniques covered here. // QTR=2 The above JCL starts the process and brings in the PROC, which contains most of the file information and programs to run. The JCL also allows passing of parameters to the rest of the JCL stream and into the SAS program.

5 NESUG 15 Posters

INFILE I2IN END=EOF; //XXXU040 PROC INDEXI1=ABC, INPUT @1 PRCT $CHAR01. HIGH LEVEL INDEX I/P @2 IDENT $CHAR22. // LTRQ='z', @24 SASGPT $CHAR01. PART OF UNIX PATH NAME // LIB1='/zz', // PATH='/abc32/', OBS_COUNT + 1; *Count of recs; // QTR=, OUTPUT O1SAS.xxF&YEAR4; // YEAR4= //* //S05A EXEC *Write temporary rec count file; PGM=SASXA1,REGION=4M, IF EOF THEN OUTPUT TEMP; The JCL calls in the Proc containing the files and locations of the programs *Write permanent rec count file; being run. Procs are usually located in DATA O1SAS.xxFOBS&YEAR4 ; SET TEMP (KEEP=OBS_COUNT); protected files that cannot be altered Since the SAS file header information directly. is written at the front of a SAS tape

file and the record count is only known NOTE2 passing SYSPARM() at the end, the number of observations in a file is missing. The choices are //PARM='SYSPARM=" rather limited if this information is &YEAR4&PATH&YEAR4<RQ&QTR&LIB1"' needed. Either the entire file can be //******************************* //*- MOVING DATA FILES FROM THE read or as the file is being created a //*- MVS MAINFRAME TO UNIX second output file containing a single //*- DOWNLOAD THE CURR YR FILE //******************************* record with the record count can be //SYSIN DD DSN= written as shown in the above code. IMS.SRCELIB,DISP=SHR, SUBSYS=(PANV,,XXXU401) //I1IN DD DSN= NOTE4: I5SENDTO Contents XXX.LQ11.XX.Q&QTR.&YEAR4,DISP=OLD FILENAME MYMAIL EMAIL //I2IN DD DSN= TO = ( XXX.LQ14.XX.Q&QTR.&YEAR4,DISP=OLD "[email protected]" //I3RLINK DD DSN=IS.PL(XX56),DISP=SHR //I4UNXCDE DD DSN=IS.PLIB(XX57),DISP=SHR "[email protected]" //I5SENDTO DD DSN=IS.PLIB(MLIST),DISP=SHR "[email protected]" //O8ABEND DD SYSOUT=W "[email protected]" //SASINCL8 INCLUDE MEMBER=SASINCL8 ) //* SUBJECT=RESULT OF DATA LOAD TO The JCL, Language, is UNIX AS OF &SYSDATE9" ; submitted automatically by the system The addresses of email recipients are based on a schedule. Anything kept in a text file allowing easy access beginning “&” is a passed variable for changes. resolved by the JCL. For instance &YEAR4 above is resolved to 2002 and CONTACT passed into the SAS program. &PASS is INFORMATION: resolved to either abc31 or abc32 Steve Rhoades depending on the quarter and like the IMS HEALTH Inc. &YEAR value, is passed into SAS. 660 W. Germantown Pike Plymouth Meeting, Pa. 19462 NOTE3: Create a rec count file Work Phone (610) 834-4614 DATA O1SAS.xxF&YEAR4 Email: (DROP=OBS_COUNT PROCCODE) [email protected] TEMP (KEEP=OBS_COUNT);

6