/* PARSTAT EXEC V2.8 Mike Poil IBM -------------------------------------------------------------------------------- This EXEC needs a complete re-write as it does a lot more than it was first designed to do, which was just to capture the data. -------------------------------------------------------------------------------- ******************************************************************************** IMPORTANT NOTES: ******************************************************************************** Always validate the thresholds against the customer CICS systems. Some are set quite high as the initial work was done for a large customer. Setting some lower may help you to get get a better picture of the activity. Find ***THRESHOLDS*** to see them. ******************************************************************************** For VSE compatibility use only columns 1 to 80. This EXEC is supplied by IBM as-is with no warranty implied or expressed. For any problems, contact: poilmike@uk.ibm.com This EXEC is a work-in-progress, so expect it to change as I think of things and find the time to do it. ******************************************************************************** It is designed to parse DFH0STAT print output and produces: 1. An analysis report, which provides data for a basic performance and Health Check analysis. Many of the messages are based on thresholds that you will find very early on in the EXEC, change them to suit your environment. The analysis of the data is intelligent, and is based on techniques used by myself and others. 2. CSV-format files that contain summary performance data. These are designed to be cumulative so that the data can be retained for a long time in order to provide trend analysis of CICS overall performance. You can use this exec to report on as many CICS partitions as you need to, it always adds the APPLID to the report and CSV files. ******************************************************************************** VM Format: PARSTAT fn ft fm <( <)>> The default options are (NOBP NOEXC NOINF LIM NOPROF THR NOCSV NOINDV) VSE Format: // EXEC REXX=PARSTAT,PARM='LST_jobname LST_class LST_jobnum <(options as above <)>>' ***************************************************************************** * IMPORTANT NOTE: For VSE, the JCL must be set up with the correct * * security to read the LST queue data. * ***************************************************************************** Options: They are processed in whatever order they appear, so the exec uses the last setting if you code mutually exclusive options. NOREP - No reports (there is no REP parameter). NOBP - No Best Practice messages in the report. NOEXC - No Exception messages in the report. Exceptions are for abnormal events that are usually reported no matter how many times they occur (zero thresholds are used). There is a fine line between exceptions and thresholds, and I am still not sure that I have the balance correct, so feel free to change this to suit your preferences. NOINF - No Information messages in the report. NOLIM - No Limit messages in the report. NOPROF - This excludes messages in ANALYSIS REPORT/REPOUT that produce a profile of cpu:dispatch ratio, cpu per transaction, EXCPs per transaction etc. NOTHR - No Threshold messages in the report. Thresholds are always count based. NOCSV - No CSV data produced. NOINDV - No individual report files on VM Return codes: (check for "Say" messages) 0 OK 8 A problem with the DFH0STAT data 16 A problem with creating one or more of the output files 20 Invalid options 998 Incorrect operating system used to run this EXEC e.g. TSO 999 Severe error in the EXEC VM Input : The values in these files are not checked. FILE EXCLUDE - VSAM files to be excluded from heavy usage and threshold analysis Lines that begin with an '*' are comments. The CICS applid must be the first word and the filename the second word. Lines that begin with an '*' are comments. The CICS applid must be the first word and the filename the second word. LSRPOOL EXCLUDE - LSR pools to be exluded from analysis. Lines that begin with an '*' are comments. The CICS applid must be the first word and the LSR pool number the second word. VM Output: applid date - A report on only the data you have just read (if INDV) ANALYSIS TXT - Accumulative report data ANALYSIS TXTDATE- Accumulative report data with the messages sorted by date within message type DTIO CSV - Data Table I/O statistics FILE CSV - VSAM file-level statistics Only reports files that have non-zero request counts LOADER CSV - Loader statistics LSRPOOL CSV - VSAM LSR pool statistics SUMMARY CSV - Overall CICS statistics TD CSV - Transient Data statistics TSQ CSV - Temporary Storage statistics Existing files are backed up before the new versions are created as fn BACKUP and are CMS-packed to save disk space. The new fn CSV and ANALYSIS TXT contain all the data of the previous file and have all duplicate data removed. VSE Input : The values in these files are not checked. These are library members and are read from PRD2.CONFIG unless the variable VSE_Sublibrary is changed. EXFILE.A - files to be excluded from heavy usage and threshold analysis Lines that begin with an '*' are comments. The CICS applid must be the first word and the filename the second word. EXLSR.A - LSR pools to be exluded from analysis. Lines that begin with an '*' are comments. The CICS applid must be the first word and the LSR pool number the second word. VSE SAM Input/Output: The EXEC reads the 'IN' file of the pair if it exists, and copies it to the 'OUT' file with the new data from this run. For each of the files, providing the 'IN' and 'OUT' files are defined correctly, the EXEC will ensure that the data is not duplicated. REPIN/REPOUT - A report on the data DTIN/DTOUT - Data Table I/O statistics CSV FILEIN/FILEOUT - VSAM file-level statistics CSV Only reports files that have non-zero request counts LDRIN/LDROUT - Loader statistics CSV LSRIN/LSROUT - VSAM LSR pool statistics CSV SUMMIN/SUMMOUT - Overall CICS statistics CSV TDIN/TDOUT - Transient Data statistics CSV TSQIN/TSQOUT - Temporary Storage statistics CSV e.g. // DLBL REPIN,'PARSTAT.REPORT', . . old data // DLBL REPOUT,'PARSTAT.REPORT', . . old data + new data // DLBL LSRIN,'PARSTAT.LSR.CSV', . . old data // DLBL LSROUT,'PARSTAT.LSR.CSV', . . old data + new data If VSAM-Managed SAM files are used, the 'IN' file should be DISP=OLD, and the 'OUT' file should be DISP=(NEW,KEEP). DISP=OLD for the 'OUT' file will only work if there is no 'IN' file. In this case the 'OUT' file is opened in EXTEND mode and the EXEC will write the new data after the old end-of-file. However, DISP=OLD may result in duplicate data as the EXEC needs to be able to combine the old and new data to be able to check for duplicates. Appending the data means that a history is maintained. It is important that use of the findings reported in ANALYSIS TXT/REPOUT be based on several week's worth of data (and preferably during a known peak), as activity and hence limit conditions can change from day-to-day. If you do not want a history, then just make sure that the input report and CSV files do not exist. On VM, just rename ANALYSIS TXT and * CSV. On VSE, supply // DLBL xxxxIN with a file-id that does not exist. ******************************************************************************** Usage notes: If you want to use this EXEC to accumulate CSV data over a period of time, you should aim for one set of DFH0STAT data per day and produce it before resets have occurred to capture as much data as possible. STATRCD=OFF stops CICS performing a reset at each standard interval, which is every 3 hours by default. However, CICS always performs a reset at its end-of-day time. You can use the CICS SPI in a PLTPI program to change the end-of-day to a time after the default of 00:00:00 a.m. (midnight) if that helps you to get more data. It is important to run DFH0STAT before VSAM files are closed, as CLOSE deletes all of the VSAM statistics for a dataset, and for the LSR pool when all files in that pool are closed. If DMF is active, CICS avoids the loss of the data by writing USS records to DMF for processing by DFHSTUP, Be careful when comparing CICS statistics EXCP counts to LISTCAT. When a file is opened, CICS stores the catalog EXCP counts in the FCT. When a reset or CLOSE is performed, CICS finds the EXCP counts that are maintained by VSAM in the partition, and the difference is what you see reported. This is all done by VSAM SHOWCB. ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** The EXCP counts that you see in CICS statistics for VSAM PATH definitions do NOT include the EXCP activity on the AIX. This is not a bug, it is a design limitation. ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** The companion PARSTUnn EXEC has been written to work with data produced by DFHSTUP so that resets can be correctly handled. PARSTUnn is not available for general use yet as it is incomplete. ******************************************************************************** Other notes: The exec can use the output from DFH0STAT at PM69135. The report date format is assumed to be mmddyy, see variable Dateform. This may be changed to 'ddmmyy' ******************************************************************************** Todo list: 1. Profile file requests per transaction? 2. Report on program usage below versus above? 3. V3 to change the message format to contain a message number and a sort that allows us to group the messages so that we can see the same message in ascending date sequence. Now we get the same message sorted on the message text and that does not allow us to see the differences over time, instead we see the lowest to highest numbers. E.g. this is how it is today: 20120516 Limit TS buffer wait 1111 times 20121119 Limit TS buffer wait 1134 times 20121107 Limit TS buffer wait 3738 times 20121016 Limit TS buffer wait 5662 times 20121101 Limit TS buffer wait 5907 times 20121105 Limit TS buffer wait 7738 times 4. V3 option to not produce individual analysis files on VM. ******************************************************************************** Change_log_start: 14.03.2013 V2.8 Many message content changes to reduce verbosity. Data Table candidates not identified hence no DATATABL EXCLUDE Avoid exceptions for FILE requests/EXCPs not being correct. Stop Profile messages for TCB elapsed ratios. MXT queuing now in minutes not seconds. Same for SOS. Heavily used files do not include ESDS. GETVIS below 16MB < threshold is now Best Practice. 02.07.2013 PROFILE transaction counts give % of all transactions 05.07.2013 Peak Transactions delayed by MXT reported only Handle zero CSKP_count 09.08.2013 Revise Profile messages for heavily used files and each LSR pool as a % of the total LSR activity 13.08.2013 Cpu per transaction when accumulated cpu is available is now based on RAlltrans not Proftrans 14.08.2013 CI compression removed from PROFILE. TS buffer hit % is also a PROFILE message PROFILE total cpu 15.08.2013 Heavily used files get reads etc. as % of all requests. 15.08.2013 Profile total EXCPs. 19.08.2013 Profile TCB cpu/tran always. 21.08.2013 Say how many LSRPOOL strings are needed Change "at least" to give the peak+1 Dispatcher cpu is now in hours not minutes and % of elapsed 23.08.2013 Replace ASA cc by space BICVR=1000 not 5000 TS buffer waits now included with TS peak users in buffer waits 30.08.2013 Monitor exception count is no a Profile message PRTYAGE now OK between 0 and BPRTYAGE 03.12.2013 Handle PM69135 changes for: Peak Queued User transactions. Moved "MXT delayed" check to further on in processing so we have the peak queued count. 12.12.2013 Cpu per transaction threshold 20.12.2013 Reset_possible now called reset_done, and is set to 1 if there is a difference between the total number of transactions since CICS started and the number since the last reset. Profile cpu % from total partition cpu only if there was no reset_done. 23.12.2013 Profile cpu% per transaction per second where possible. This gives an idea of the typical TPS that could be sustained when you consider that you want to keep a single CICS system to about 60% utilisation average during a peak hour. You also need to remember that when this is based on TCB cpu time, that TCB cpu can be a lot less than actual, so 60% from TCB cpu may be more like 80% or even higher when looking at the actual cpu utilisation. Change the reset_done check to allow for the case where the difference between the total number of transactions and the number since reset is within a couple of percent, and treat that as not a reset_done. Say when average cpu utilisation based on accumulated cpu cannot be calculated. 07.01.2014 Tell the user when "junk" argument values are supplied, e.g. PARSTAT fn ft fm BP INF is used instead of the correct format PARSTAT fn ft fm (BP INF, and continue with whatever options are set correctly. 24.03.2014 Change the LSR data and index buffer threshold analysis to say how many EXCPs would be saved by CI SIZE if the buffer hit ratio was the same as the threshold. Total them. FILE STRINGS max. increase is 200, document 255 limit and if total string waits is 999 show 999+. Extra message if max. string wait > ULFILEstrmax. LFILEstrmax > 0 and LFILEstrwait > 0 to eliminate borderline string issues. TD peak string usage threshold does not say to increase them. Add (max. strings 255) in many places. GETVIS above/below 0K now is a Limit condition. 06.04.2014 Change various message texts like 'consider increasing' instead of 'increase', 'by a value up to' instead of 'by a minimum of'. Restrict suggested FILE string increase to MXT * 20%. Profile CICS Performance Monitoring being active. *Bug* Performance and Exception Class not handled correctly. DMF errors are now a threshold. Profile monitoring ON but exception records OFF. 06.05.2014 High number of LSR buffers is now correctly checked against the CISZ buffer count and not the LSR total buffers. Profile percentage of LSR EXCPS vs NSR EXCPS. Message for Monitoring ON but Exception OFF is Best Practice. DFHAKP activity is now "PROFILE RECOVERY" and zero activity now produces a Best Practice to warn about no emergency restart. 23.05.2014 Heavily used is now sorted on EXCPs first. 'file' is replaced by the type e.g. 'KSDS'. ESDS are excluded. 'is heavily used' deleted. Index/Data EXCP ratio added with a maximum of 99.99. EXCP/Request ratio added with a maximum of 99.99. R/W EXEC CICS request ratio added with maximum 9999999.99. GET for UPDATE now separated as % value and not included with UPDATE. Change log deleted prior to release 2.8. 01.06.2014 TLSRbufferlim=1000 Change_log_end: */ Trace Off /* Version of this exec for an Information message */ Parstat_VRM = '2.8 1st June 2014' Numeric digits 20 /* Some defaults */ True = 1 False = 0 /* The default date format is mm/dd/yy. Assign any other value for the EXEC to assume dd/mm/yy. */ Dateform = 'mmddyy' /* <================= Change as required */ Parse Source Opsys . Select When Opsys = 'CMS' Then VM_env = True When Opsys = 'VSE' Then VM_env = False Otherwise Do Say Opsys 'is not a supported environment for this EXEC' Exit 998 End End If VM_env Then Do Arg fn ft fm junk '(' opts ')' . If junk <> '' Then Do Say 'The format of this exec is PARSTAT fn ft fm <(options<)>>.' Say 'The following values after fm have been ignored:' junk End 'PIPE STATE' fn ft fm If RC > 0 Then Do Say fn ft fm 'does not exist' Exit 8 End End Else Do Arg LST_jobname LST_class LST_jobnum junk '(' opts ')' . If junk <> '' Then Do Say 'The format of this Rexx is PARSTAT jobname class jobnumber', '<(options<)>>.' Say 'The following values after jobnumber have been ignored:' junk End If LST_jobname = '' | LST_class = '' | LST_jobnum = '' , | Datatype(LST_jobnum,'W') = False Then Do Say 'A jobname, class and numeric job number for the DFH0STAT', 'LST queue entry must be supplied' Exit 8 End VSE_Sublibrary = 'PRD2.CONFIG' /* <================= Change as required */ Dasd_BLKSIZE = 10796 /* <================= Change as required */ X = REXXMSG('OFF') X = ASSGN('STDOUT','SYSLST') End /* Set option defaults */ NOBP = True NOEXC = True NOINF = True NOLIM = False NOPROF = True NOTHR = False NOCSV = True NOINDV = True Opterr = False /* Check options, assuming that they are blank-delimited */ Do W = 1 to Words(opts) Parse Upper Var opts opt opts Select When opt = 'NOREP' Then Do NOBP = True NOEXC = True NOINF = True NOLIM = True NOPROF = True NOTHR = True End When opt = 'NOBP' Then NOBP = True When opt = 'BP' Then NOBP = False When opt = 'NOEXC' Then NOEXC = True When opt = 'EXC' Then NOEXC = False When opt = 'NOINF' Then NOINF = True When opt = 'INF' Then NOINF = False When opt = 'NOLIM' Then NOLIM = True When opt = 'LIM' Then NOLIM = False When opt = 'NOPROF' Then NOPROF = True When opt = 'PROF' Then NOPROF = False When opt = 'NOTHR' Then NOTHR = True When opt = 'THR' Then NOTHR = False When opt = 'NOCSV' Then NOCSV = True When opt = 'CSV' Then NOCSV = False When opt = 'NOINDV' Then NOINDV = True When opt = 'INDV' Then NOINDV = False Otherwise Say 'Option' opt 'is invalid' Opterr = True End End W If Opterr = True Then Do Say 'This EXEC has been terminated due to invalid options' Exit 20 End /* ***THRESHOLDS*** Set resource utilisation thresholds. It would be possible to externalise the changes by having an external file that contains Rexx statements that duplicate what we have here, and use Rexx Interpret to execute them. If they begin with "L" they apply to Limit conditions and are set to zero as even one is normally bad. Similarly "E" for Exceptions. You make then non-zero at your risk. "T" is for threshold. Please customize them to fit your requirements. "P" is a threshold for profiling, customize as required. "B" is for Best Practice. Beware, sometimes I change the use and forget to change the first character! */ TMXTpeakutran = 90 /* peak # user tasks/MXT % */ LMXTdelay = 0 /* # tasks delayed by MXT */ LMXTdelaytime = 0 /* # secs delayed by MXT */ TICV = 1000 /* minimum ICV (not used) */ BICVR = 1000 /* maximum ICVR, may still be too big */ TICVTSD = 250 /* maximum ICVTSD */ /* Tminelaps = (8*3600) Minimum CICS elapsed b4 warning */ TQRdispelapsed = 60 /* maximum QR dispatch:elapsed % */ /* before warning that CICS may be */ /* too busy for a single cpu, and it can*/ /* never use more than one on VSE. */ Edscpupcnt = 10 /* maximum % dispatcher cpu/TCB cpu */ /* before exception warning */ TGVsizelo = (10*1024)-4 /* minimum advised 24-bit Getvis 10MB */ /* less 4K for SIZE=DFHSIP */ TGVloused = 95 /* maximum 24-bit Getvis used % */ TGVlomax = 97 /* maximum 24-bit Getvis max used % */ TDSApeak = 90 /* maximum peak DSALIM used % */ LDSAnostg = 0 /* maximum DSA times nostg */ LDSAsusp = 0 /* maximum DSA times suspended */ LDSAcush = 0 /* maximum DSA times cushion released */ LDSASOS = 0 /* maximum DSA times at SOS */ LDSASOSt = 0 /* maximum DSA seconds at SOS */ EDSAviol = 0 /* maximum DSA storage violations */ TEDSApeak = 95 /* maximum peak EDSALIM used % */ LEDSAnostg = 0 /* maximum EDSA times nostg */ LEDSAsusp = 0 /* maximum EDSA times suspended */ LEDSAcush = 0 /* maximum EDSA times cushion released */ LEDSASOS = 0 /* maximum EDSA times at SOS */ LEDSASOSt = 0 /* maximum EDSA seconds at SOS */ EEDSAviol = 0 /* maximum EDSA storage violations */ TGVhiused = 95 /* maximum 31-bit Getvis used % */ TGVhimax = 97 /* maximum 31-bit Getvis max used % */ TLoadwait = 1000 /* maximum loader wait requests */ TLoadwaitt = 300 /* maximum loader wait time secs */ TLoadcompresslo = 0 /* maximum compressions < 16MB */ TLoadcompresshi = 0 /* maximum compressions > 16MB */ TTSQpeakmain = 2048 /* maximum TS peak main in K */ TTSQextn = 3 /* maximum TSQ extensions/created % */ TTSQCIpeak = 70 /* maximum TSQ CI peak/available % */ /* 75% is the magic number for 1.1.1 */ /* and TSQ compressions; use 70% to */ /* trigger before we get there. */ TTSQCIgt = 5 /* maximum TSQ writes>CIsize/putQ % */ TTSQCIgtcount = 10000 /* maximum TSQ writes>CIsize/putQ */ ETSQauxfull = 0 /* maximum times DFHTEMP full */ TTSQstringpeak = 80 /* maximum TSQ peak string/avail. % */ TTSQstringwait = 0 /* maximum TSQ string wait secs */ LTSQpeakuser = 0 /* maximum TSQ users string wait */ LTSQpeakbuffers = 0 /* maximum TSQ users buffer wait */ LTSQbufferwait = 0 /* maximum TSQ buffer waits */ /* CICS splits the buffers 50% for WRITE*/ /* and 50% for READ, so it is a good */ /* idea to increase in units of 2. */ TTSQbufferhit = 80 /* minimum TSQ buffer hit % */ TTSQVDISKorMAIN = 500000 /* DFHTEMP I/Os when buffer hit% is */ /* optimum at which you may want to */ /* consider VDISK or even MAIN only. */ /* This is just a prompt to think about */ /* it not to actually do it. */ ETSQformatwrite = 0 /* maximum TSQ format writes */ ETSQIOerr = 0 /* maximum TSQ I/O errors */ ETDformatwrite = 0 /* maximum TD format writes */ TTDCIpeak = 80 /* maximum TD CI peak/available % */ LTDfull = 0 /* maximum times DFHNTRA full */ TTDstringpeak = 80 /* maximum TD peak string/avail. % */ LTDstringwait = 0 /* maximum TD string wait secs */ LTDpeakuser = 0 /* maximum TD users string wait */ TTDbufferpeak = 80 /* maximum TD buf peak/available % */ LTDbufferwait = 0 /* maximum TD buffer waits */ LTDpeakbuffers = 0 /* maximum TD users buffer wait */ ETDIOerr = 0 /* maximum TD I/O errors */ TLSRstringpeak = 80 /* maximum LSR peak string/avail. % */ TLSRstringlow = 25 /* minimum LSR peak string/avail. % */ LLSRstringwait = 0 /* maximum LSR peak string waits */ TLSRbufferlim = 1000 /* maximum LSR buffers b4 BP message */ TLSRlowusagepool = 250000 /* minimum total IO to analyze LSR pool */ TLSRlowusageCISZ = 50000 /* minimum total IO to analyze LSR CISZ */ TLSRdbuffer = 80 /* minimum LSR data buffer hit % */ TLSRibuffer = 95 /* minimum LSR indx buffer hit % */ TLSRtotdio = 50000 /* minimum data requests to check W/R % */ TLSRratiowr = 33 /* minimum LSR write/read ratio % */ TLSRdnuserwrite = 0 /* maximum LSR non-user data write */ TLSRinuserwrite = 0 /* maximum LSR non-user indx write */ LFILEstrmax = 1 /* maximum peak # file string waits */ ULFILEstrmax = 100 /* maximum peak # file b4 extra msg */ LFILEstrwait = 9 /* maximum file # string waits */ TFILEactiveESDS = 100000 /* minimum requests to say busy ESDS */ TFILEactiveREM = 100000 /* minimum requests to say active remote*/ TFILEactiveNSR = 100000 /* minimum requests to say active NSR */ TFILEPIO = 250000 /* minimum EXCPs to profile the file */ TFILEDTratio = 90 /* minimum ratio to suggest a Data Table*/ TFILEPIOratio = 33 /* minimum EXCP:request ratio */ TRDTrequests = 250000 /* minimum Data Table requests remote */ /* i.e. file I/O within the AOR that */ /* uses the Data Table in the FOR. */ TLDTrequests = 0 /* minimum Data Table requests local */ /* i.e. file I/O within the FOR that */ /* owns the Data Table. */ TRDThitratio = 90 /* minimum Data Table hit ratio % remote*/ TLDThitratio = 0 /* minimum Data Table hit ratio % local */ TDTuseratiomin = 70 /* minimum Data Table records/maxnumrecs*/ TDTuseratiomax = 90 /* maximum Data Table records/maxnumrecs*/ TDTAddrej = 0 /* maximum Data Table adds rejected */ /* this may indicate DT storage full */ EDMFerrs = 0 /* number of DMF errors */ TMONexception = 0 /* number MONITOR exception records */ PFile_pool_pcnt = 10.00 /* Profile threshold for % of */ /* file EXCPs/total LSR pool EXCPs */ PFILEWritepcnt = 33 /* Profile % write requests/total */ /* requests for heavily used files */ BPRTYAGE = 250 /* PRTYAGE maximum */ TCPUpertran = 0.05 /* CPU per transaction */ /* ***THRESHOLDS*** end */ Signal on Syntax Name Runtime_error Signal on Novalue Name Runtime_error /* Read the whole file and check the content by looking at the first 20 records */ Call Readfile Found = False Do X = 1 to Min(20,Rec.0) by 1 Upper Rec.X If Pos('APPLID',Rec.X) > 0 Then Do Found = True Leave X End End X If Found = False Then Do Say 'The file does not appear to contain valid DFH0STAT report data' Exit 8 End /* Extract the CICS system details for the output data from this run */ Parse Var Rec.X . RApplid . RSysid . RJobname . Rdate . Rtime . /* Convert dd/mm/yy date to mm/dd/yy for simplicity */ If Dateform <> 'mmddyy' Then Do Rdate = Date('U',Rdate,'E') End RdateGreg = '20'||Substr(Rdate,7,2)||'-'||Substr(Rdate,1,2)||'-' , ||Substr(Rdate,4,2) Rdate = yyyymmdd(Rdate) /* Initialise other variables */ Call Initialise Call IN_Analysis '**** PARSTAT level used is' Parstat_VRM /* Call TH_Analysis '**** VSAM SHR(4) usage must be taken into consideration' , 'when applying any recommendations from the analysis' */ /*------------------------------------------------------------------ Main process for the data records. Look for keywords in the report to parse the data for analysis. Do not change the order of the Select When clauses as this may result in some data being used incorrectly. ----------------------------------------------------------------*/ Do I = X to Rec.0 by 1 If Substr(Rec.I,1,1) = 'C0'x Then Parse Var Rec.I 2 Rec.I If Substr(Rec.I,1,1) = '1' | , Substr(Rec.I,1,1) = '-' | , Substr(Rec.I,1,1) = '0' | , Substr(Rec.I,1,1) = '+' Then Rec.I = ' '||Substr(Rec.I,2) /* Always force UPPERCASE */ Upper Rec.I Current_rec = Rec.I Select /* Keyword in print line */ When Pos('VSE RELEASE',Rec.I) > 0 Then Call VSErel When Pos('STORAGE PROTECTION',Rec.I) > 0 Then Call STORprotect When Pos('REENTRANT PROGRAMS',Rec.I) > 0 Then Call RENTprotect When Pos('MONITORING .',Rec.I) > 0 Then Call Monitoring When Pos('EXCEPTION RECORDS SUPPRESSED',Rec.I) > 0 Then Call ExceptionclassRec When Pos('PERFORMANCE RECORDS SUPPRESSED',Rec.I) > 0 Then Call PerformanceclassRecSupp When Pos('PERFORMANCE CLASS RECORDS',Rec.I) > 0 Then Call PerformanceclassRec When Pos('EXCEPTION CLASS RECORDS',Rec.I) > 0 Then Call ExceptionclassRec When Pos('EXCEPTION CLASS.',Rec.I) > 0 Then Call Exceptionclass When Pos('PERFORMANCE CLASS.',Rec.I) > 0 Then Call Performanceclass When Pos('DMF ERRORS',Rec.I) > 0 Then Call DMFerrors When Pos('STATISTICS INTERVAL',Rec.I) > 0 Then Call Statinterval When Pos('STATISTICS RECORDING',Rec.I) > 0 Then Call Statrecording When Pos('TOTAL ACCUMULATED TRANSACTIONS SO FAR',Rec.I) > 0 Then Call Alltrans When Pos('ACCUMULATED TRANSACTIONS (SINCE RESET)',Rec.I) > 0 Then Call Tottrans When Pos('MAXIMUM TRANSACTIONS ALLOWED (MXT)',Rec.I) > 0 Then Call Mxt When Pos('TIMES AT MXT',Rec.I) > 0 Then Call Timesmxt When Pos('PEAK ACTIVE USER TRANSACTIONS',Rec.I) > 0 Then Call Peakutrans When Pos('TOTAL ACTIVE USER TRANSACTIONS',Rec.I) > 0 Then Call Totutrans /* This must come before the test for TRANSACTIONS DELAYED BY MXT */ When Pos('PEAK TRANSACTIONS DELAYED BY MXT',Rec.I) > 0 Then Call DelaypeakMXT When Pos('TRANSACTIONS DELAYED BY MXT',Rec.I) > 0 Then Call Delaymxt When Pos('TOTAL MXT QUEUEING TIME',Rec.I) > 0 Then Call Delaymxttime When Pos('TOTAL MXT QUEUING TIME',Rec.I) > 0 Then Call Delaymxttime When Pos('CURRENT QUEUED USER TRANSACTIONS',Rec.I) > 0 Then Call DelaymxtC When Pos('PEAK QUEUED USER TRANSACTIONS',Rec.I) > 0 Then Call DelaypeakMXT When Pos('TOTAL QUEUEING TIME FOR CURRENT QUEUED',Rec.I) > 0 Then Call DelaymxttimeC When Pos('TOTAL QUEUING TIME FOR CURRENT QUEUED',Rec.I) > 0 Then Call DelaymxttimeC When Pos('CURRENT ICV TIME',Rec.I) > 0 Then Do Call ICV InDispatcher = 1 End When Pos('CURRENT ICVR TIME',Rec.I) > 0 Then Call ICVR When Pos('CURRENT ICVTSD TIME',Rec.I) > 0 Then Call ICVTSD When Pos('CURRENT PRTYAGING TIME',Rec.I) > 0 Then Call Prtyage When Pos('JOB STEP CPU TIME',Rec.I) > 0 Then Call JScpu /* Alternative text */ When Pos('ACCUMULATED CPU TIME',Rec.I) > 0 Then Call JScpu When Pos('QR_SUBD',Rec.I) > 0 Then Call QRTCB When Pos('RO_SUBD',Rec.I) > 0 Then RROcpu = XXTCB() When Pos('SZ',Rec.I) > 0 & Pos('ACTIVE',Rec.I) > 0 Then RSZcpu = XXTCB() When Pos('SO_MODE',Rec.I) > 0 Then RSOcpu = XXTCB() When Pos(' SL_MODE',Rec.I) > 0 Then RSLcpu = XXTCB() When Pos('SSL_MODE',Rec.I) > 0 Then RSSLcpu = XXTCB() When Pos('TOTALS',Rec.I) > 0 & InDispatcher Then Do InDispatcher = 0 Call TotalTCB End When Pos('STORAGE BELOW 16MB',Rec.I) > 0 Then BelowAbove = 'B' When Pos('CURRENT DSA LIMIT',Rec.I) > 0 Then Call DSAlim When Pos('PEAK ALLOCATION FOR DSAS',Rec.I) > 0 Then Call DSApeak When Pos('TIMES NO STORAGE RETURNED',Rec.I) > 0 & BelowAbove = 'B' Then Call DSAnostg When Pos('TIMES REQUEST SUSPENDED',Rec.I) > 0 & BelowAbove = 'B' Then Call DSAsusp When Pos('TIMES CUSHION RELEASED',Rec.I) > 0 & BelowAbove = 'B' Then Call DSAcush When Pos('TIMES SHORT-ON-STORAGE',Rec.I) > 0 & BELOWABOVE = 'B' Then Call DSASOS When Pos('TOTAL TIME SHORT-ON-STORAGE',Rec.I) > 0 & BELOWABOVE = 'B' Then Call DSASOSt When Pos('STORAGE VIOLATIONS',Rec.I) > 0 & BELOWABOVE = 'B' Then Call DSAviol When Pos('PARTITION GETVIS AREA SIZE UNDER 16 MB',Rec.I) > 0 Then Call GVsizelo When Pos('PARTITION GETVIS USED AREA BELOW 16 MB',Rec.I) > 0 Then Call GVusedlo When Pos('PARTITION GETVIS MAXIMUM USED BELOW 16 MB',Rec.I) > 0 Then Call GVmaxlo When Pos('STORAGE ABOVE 16MB',Rec.I) > 0 Then BelowAbove = 'A' When Pos('CURRENT EDSA LIMIT',Rec.I) > 0 Then Call EDSAlim When Pos('CICS TRACE TABLE SIZE',Rec.I) > 0 Then Call Tracesize When Pos('PEAK ALLOCATION FOR EDSAS',Rec.I) > 0 Then Call EDSApeak When Pos('TIMES NO STORAGE RETURNED',Rec.I) > 0 & BelowAbove = 'A' Then Call EDSAnostg When Pos('TIMES REQUEST SUSPENDED',Rec.I) > 0 & BelowAbove = 'A' Then Call EDSAsusp When Pos('TIMES CUSHION RELEASED',Rec.I) > 0 & BelowAbove = 'A' Then Call EDSAcush When Pos('TIMES SHORT-ON-STORAGE',Rec.I) > 0 & BELOWABOVE = 'A' Then Call EDSASOS When Pos('TOTAL TIME SHORT-ON-STORAGE',Rec.I) > 0 , & BELOWABOVE = 'A' Then Call EDSASOSt When Pos('STORAGE VIOLATIONS',Rec.I) > 0 & BELOWABOVE = 'A' Then Call EDSAviol When Pos('PARTITION GETVIS AREA SIZE ABOVE 16 MB',Rec.I) > 0 Then Call GVsizehi When Pos('PARTITION GETVIS USED AREA ABOVE 16 MB',Rec.I) > 0 Then Call GVusedhi When Pos('PARTITION GETVIS MAXIMUM USED ABOVE 16 MB',Rec.I) > 0 Then Call GVmaxhi When Pos(' LIBRARY LOAD REQUESTS. .',Rec.I) > 0 Then Call Loadreq When Pos('LIBRARY LOAD REQUESTS THAT WAITED',Rec.I) > 0 Then Call Loadwait When Pos('TOTAL LIBRARY LOAD REQUEST WAIT TIME',Rec.I) > 0 Then Call Loadwaitt When Pos('PROGRAMS REMOVED BY COMPRESSION',Rec.I) > 0 Then Call Loadcompress When Pos('CSKP',Rec.I) > 0 Then Call CKSPcheck When Pos('CSMI',Rec.I) > 0 Then Call CSMIcheck When Pos('CSM1',Rec.I) > 0 Then Call CSM1check When Pos('CSM2',Rec.I) > 0 Then Call CSM2check When Pos('CSM3',Rec.I) > 0 Then Call CSM3check When Pos('CSM4',Rec.I) > 0 Then Call CSM4check When Pos('CSM5',Rec.I) > 0 Then Call CSM5check When Pos('MQGX',Rec.I) > 0 Then Call MQGXcheck When Pos('MQPX',Rec.I) > 0 Then Call MQPXcheck When Pos('PUT/PUTQ MAIN STORAGE REQUESTS',Rec.I) > 0 Then Do Call TSQPutmain InTS = 1 End When Pos('GET/GETQ MAIN STORAGE REQUESTS',Rec.I) > 0 Then Call TSQGetmain When Pos('PEAK STORAGE USED FOR TS MAIN',Rec.I) > 0 Then Call TSQpeakmain When Pos('PUT/PUTQ AUXILIARY STORAGE REQUESTS',Rec.I) > 0 Then Call TSQPutaux When Pos('GET/GETQ AUXILIARY STORAGE REQUESTS',Rec.I) > 0 Then Call TSQGetaux When Pos('TIMES TEMPORARY STORAGE QUEUE CREATED',Rec.I) > 0 Then Call TSQcreated When Pos('QUEUE EXTENSION THRESHOLD',Rec.I) > 0 Then Call TSQextnthresh When Pos('QUEUE EXTENSIONS CREATED',Rec.I) > 0 Then Call TSQextn When Pos('CONTROL INTERVALS IN THE DFHTEMP DATASET',Rec.I) > 0 Then Call TSQCI When Pos('PEAK CONTROL INTERVALS USED',Rec.I) > 0 & InTS = 1 Then Call TSQCIpeak When Pos('WRITES BIGGER THAN CONTROL INTERVAL SIZE',Rec.I) > 0 Then Call TSQgtCIsize When Pos('TIMES AUXILIARY STORAGE EXHAUSTED',Rec.I) > 0 Then Call TSQauxfull When Pos('NUMBER TEMPORARY STORAGE COMPRESSIONS',Rec.I) > 0 Then Call TSQcompress When Pos(' TEMPORARY STORAGE STRINGS',Rec.I) > 0 Then Call TSQstring When Pos('PEAK TEMPORARY STORAGE STRINGS IN USE',Rec.I) > 0 Then Call TSQstringpeak When Pos('TEMPORARY STORAGE STRING WAITS',Rec.I) > 0 Then Call TSQstringwait When Pos('PEAK USERS WAITING ON STRING',Rec.I) > 0 & InTS = 1 Then Call TSQpeakusers When Pos('TEMPORARY STORAGE BUFFERS',Rec.I) > 0 Then Call TSQbuffers When Pos('TEMPORARY STORAGE BUFFER WAITS',Rec.I) > 0 Then Call TSQbufferwait When Pos('PEAK USERS WAITING ON BUFFER',Rec.I) > 0 & InTS = 1 Then Call TSQpeakbuffers When Pos('TEMPORARY STORAGE BUFFER READS',Rec.I) > 0 Then Call TSQbufferread When Pos('TEMPORARY STORAGE BUFFER WRITES',Rec.I) > 0 Then Call TSQbufferwrite When Pos('FORCED BUFFER WRITES FOR RECOVERY',Rec.I) > 0 Then Call TSQbufferforce When Pos('FORMAT WRITES',Rec.I) > 0 Then Call TSQformatwrite When Pos('I/O ERRORS ON THE DFHTEMP DATASET',Rec.I) > 0 Then Call TSQIOerr When Pos('TRANSIENT DATA READS',Rec.I) > 0 Then Do Call TDRead InTS = 0 InTD = 1 End When Pos('TRANSIENT DATA WRITES',Rec.I) > 0 Then Call TDWrite When Pos('TRANSIENT DATA FORMATTING WRITES',Rec.I) > 0 Then Call TDformatWrite When Pos('CONTROL INTERVALS IN THE DFHNTRA DATASET',Rec.I) > 0 Then Call TDCI When Pos('PEAK CONTROL INTERVALS USED',Rec.I) > 0 & InTD = 1 Then Call TDCIpeak When Pos('TIMES NOSPACE ON DFHNTRA OCCURRED',Rec.I) > 0 Then Call TDfull When Pos(' TRANSIENT DATA STRINGS',Rec.I) > 0 Then Call TDstring When Pos('PEAK TRANSIENT DATA STRINGS IN USE',Rec.I) > 0 Then Call TDstringpeak When Pos('TIMES STRING WAIT OCCURRED',Rec.I) > 0 Then Call TDstringwait When Pos('PEAK USERS WAITING ON STRING',Rec.I) > 0 & InTD = 1 Then Call TDpeakusers When Pos(' TRANSIENT DATA BUFFERS',Rec.I) > 0 Then Call TDbuffers When Pos('PEAK TRANSIENT DATA BUFFERS IN USE',Rec.I) > 0 Then Call TDbufferpeak When Pos('TIMES BUFFER WAIT OCCURRED',Rec.I) > 0 Then Call TDbufferwait When Pos('PEAK USERS WAITING ON BUFFER',Rec.I) > 0 & InTD = 1 Then Call TDpeakbuffers When Pos('I/O ERRORS ON THE DFHNTRA DATASET',Rec.I) > 0 Then Call TDIOerr When Pos('POOL NUMBER :',Rec.I) > 0 Then Do Parse Var Rec.I ':' LSRpool . InLSR = 'Y' InTD = 0 End When Pos('MAXIMUM KEY LENGTH',Rec.I) > 0 & INLSR = 'Y' Then Call LSRkeylen When Pos('TOTAL NUMBER OF STRINGS',Rec.I) > 0 & INLSR = 'Y' Then Call LSRstring When Pos('PEAK CONCURRENTLY ACTIVE STRING',Rec.I) > 0 & INLSR = 'Y' Then Call LSRstringpeak When Pos('TOTAL REQUESTS WAITED FOR STRING',Rec.I) > 0 & INLSR = 'Y' Then Call LSRwait When Pos('PEAK REQUESTS WAITED FOR STRING',Rec.I) > 0 & INLSR = 'Y' Then Call LSRpeakwait When Pos('DATA BUFFERS',Rec.I) > 0 & INLSR = 'Y' Then Call LSRbuffers When Pos('SUCCESSFUL LOOK ASIDES',Rec.I) > 0 & INLSR = 'Y' Then Call LSRlookaside When Pos('BUFFER READS',Rec.I) > 0 & INLSR = 'Y' Then Call LSRbufferread When Pos(' USER INITIATED WRITES',Rec.I) > 0 & INLSR = 'Y' Then Call LSRuserwrite When Pos('NON-USER INITIATED WRITES',Rec.I) > 0 & INLSR = 'Y' Then Call LSRnuserwrite When Pos('DATA BUFFER STATISTICS',Rec.I) > 0 & INLSR = 'Y' Then Call LSRbufferstats When Pos('DATA AND INDEX BUFFER STATISTICS',Rec.I) > 0 & INLSR = 'Y' Then Call LSRbufferstats When Pos('FILENAME',Rec.I) > 0 & Pos('METHOD',Rec.I) > 0 Then Do If RAlltrans > 0 /* Trans since start as CICS does not reset LSR */ Then Do Call PM_Analysis 'LSRPOOL Buffer Hit per transaction is', Format(Total_LSRPOOL_BufferHit/RAlltrans,5,2) Call PM_Analysis 'LSRPOOL Buffer I/O per transaction is', Format(Total_LSRPOOL_BufferRW/RAlltrans,5,2) Call PM_Analysis 'LSRPOOL Buffer Read per transaction is', Format(Total_LSRPOOL_BufferR/RAlltrans,5,2) Call PM_Analysis 'LSRPOOL Buffer Write per transaction is', Format(Total_LSRPOOL_BufferW/RALLtrans,5,2) End Call FILEstatistics End When Pos('FILENAME',Rec.I) > 0 & Pos('TABLE',Rec.I) > 0 Then Call DatatableIO Otherwise End /* Select Keyword in record */ End I /*------------------------------------------------------------------ End of the main process for the data records. ----------------------------------------------------------------*/ /* Call Showvar */ Call LSRPROF Call EXCPSplit Call PM_Analysis '**** Total EXCP count for the profile calculations' , 'based on FILE statistics is' , Forbig(Total_FILES_EXCPs) /* Write the analysis report */ Call LogAnalysis /* Output the CSV-format data */ Call CreateCSV Exit 0 /*******************************************************************/ /* End of mainline. */ /*******************************************************************/ /* Show variables written to the CSV files - diagnostic mode only. */ Showvar: Trace Off Say 'RStatinterval = ' RStatinterval Say 'RTottrans = ' RTottrans Say 'RAlltrans = ' RAlltrans Say 'Rmxt = ' Rmxt Say 'Rtimesmxt =' Rtimesmxt Say 'RPeakutrans =' RPeakutrans Say 'RTotutrans =' RTotutrans Say 'Rdelaymxt = ' Rdelaymxt Say 'Rdelaymxttime = ' Rdelaymxttime Say 'RICV = ' RICV Say 'RICVR = ' RICVR Say 'RICVTSD = ' RICVTSD Say 'RPRTYAGE = ' RPRTYAGE Say 'RJScpu = ' RJScpu Say 'RCICSelapsed = ' RCICSelapsed Say 'RQRdispatch = ' RQRdispatch Say 'RQRcpu = ' RQRcpu Say 'RROcpu = ' RROcpu Say 'RSZcpu = ' RSZcpu Say 'RSOcpu = ' RSOcpu Say 'RSLcpu = ' RSLcpu Say 'RSSLcpu = ' RSSLcpu Say 'RGVsizelo = ' RGVsizelo Say 'RGVusedlo = ' RGVusedlo Say 'RGVmaxlo = ' RGVmaxlo Say 'RDSAlim = ' RDSAlim Say 'RDSApeak = ' RDSApeak Say 'RDSAnostg = ' RDSAnostg Say 'RDSAsusp = ' RDSAsusp Say 'RDSAcush = ' RDSAcush Say 'RDSASOS = ' RDSASOS Say 'RDSASOSt = ' RDSASOSt Say 'RDSAviol = ' RDSAviol Say 'REDSAlim = ' REDSAlim Say 'REDSApeak = ' REDSApeak Say 'REDSAnostg = ' REDSAnostg Say 'REDSAsusp = ' REDSAsusp Say 'REDSAcush = ' REDSAcush Say 'REDSASOS = ' REDSASOS Say 'REDSASOSt = ' REDSASOSt Say 'REDSAviol = ' REDSAviol Say 'RGVsizehi = ' RGVsizehi Say 'RGVusedhi = ' RGVusedhi Say 'RGVmaxhi = ' RGVmaxhi Say 'RLoadreq = ' RLoadreq Say 'RLoadwait = ' RLoadwait Say 'RLoadwaitt = ' RLoadwaitt Say 'RLoadcompresslo = ' RLoadcompresslo Say 'RLoadcompresshi = ' RLoadcompresshi Say 'RTSPutmain = ' RTSPutmain Say 'RTSQGetmain = ' RTSQGetmain Say 'RTSQpeakmain = ' RTSQpeakmain Say 'RTSQPutaux = ' RTSQPutaux Say 'RTSQGetaux = ' RTSQGetaux Say 'RTSQcreated = ' RTSQcreated Say 'RTSQthreshold = ' RTSQthreshold Say 'RTSQextn = ' RTSQextn Say 'RTSQCI = ' RTSQCI Say 'RTSQCIpeak = ' RTSQCIpeak Say 'RTSQgtCIsize = ' RTSQgtCIsize Say 'RTSQauxfull = ' RTSQauxfull Say 'RTSQstring = ' RTSQstring Say 'RTSQstringpeak = ' RTSQstringpeak Say 'RTSQstringwait = ' RTSQstringwait Say 'RTSQpeakusers = ' RTSQpeakusers Say 'RTSQbuffers = ' RTSQbuffers Say 'RTSQpeakbuffers =' RTSQpeakbuffers Say 'RTSQbufferwait = ' RTSQbufferwait Say 'RTSQbufferread = ' RTSQbufferread Say 'RTSQbufferwrite = ' RTSQbufferwrite Say 'RTSQformatwrite = ' RTSQformatwrite Say 'RTSQIOerr = ' RTSQIOerr Say 'RTDRead = ' RTDRead Say 'RTDWrite = ' RTDWrite Say 'RTDformatWrite = ' RTDformatWrite Say 'RTDCI = ' RTDCI Say 'RTDCIpeak = ' RTDCIpeak Say 'RTDfull = ' RTDfull Say 'RTDstring = ' RTDstring Say 'RTDstringpeak = ' RTDstringpeak Say 'RTDstringwait = ' RTDstringwait Say 'RTDpeakusers = ' RTDpeakusers Say 'RTDbuffers = ' RTDbuffers Say 'RTDbufferpeak = ' RTDbufferpeak Say 'RTDbufferwait = ' RTDbufferwait Say 'RTDpeakbuffers =' RTDpeakbuffers Say 'RTDIOerr = ' RTDIOerr Do V = 1 to 15 Say 'RLSRkeylen.'V RLSRkeylen.V Say 'RLSRstring.'V RLSRstring.V Say 'RLSRstringpeak.'V RLSRstringpeak.V Say 'RLSRwait.'V RLSRwait.V Say 'RLSRpeakwait.'V RLSRpeakwait.V Say 'RLSRdbuffers.'V RLSRdbuffers.V Say 'RLSRdlookaside.'V RLSRdlookaside.V Say 'RLSRdbufferread.'V RLSRdbufferread.V Say 'RLSRduserwrite.'V RLSRduserwrite.V Say 'RLSRdnuserwrite.'V RLSRdnuserwrite.V Say 'RLSRibuffers.'V RLSRibuffers.V Say 'RLSRilookaside.'V RLSRilookaside.V Say 'RLSRibufferread.'V RLSRibufferread.V Say 'RLSRiuserwrite.'V RLSRiuserwrite.V Say 'RLSRinuserwrite.'V RLSRinuserwrite.V End V Do V = 1 to FILEname.0 Say 'FILEname.'V FILEname.V Say 'FILEamethod.'V FILEamethod.V Say 'FILEtype.'V FILEtype.V Say 'FILELSRpool.'V FILELSRpool.V Say 'FILEstrmax.'V FILEstrmax.V Say 'FILEstrwait.'V FILEstrwait.V Say 'FILEread.'V FILEread.V Say 'FILEgetupdat.'V FILEgetupdate.V Say 'FILEbrowse.'V FILEbrowse.V Say 'FILEadd.'V FILEadd.V Say 'FILEupdate.'V FILEupdate.V Say 'FILEdelete.'V FILEdelete.V Say 'FILEdexcps.'V FILEdexcps.V Say 'FILEiexcps.'V FILEiexcps.V End V Do V = 1 to RDTname.0 Say 'RDTname.'V RDTname.V Say 'RDTtype.'V RDTtype.V Say 'RDTmaxnumrec.'V RDTmaxnumrec.V Say 'RDTread.'V RDTread.V Say 'RDTnrf.'V RDTnrf.V Say 'RDTaddread.'V RDTaddread.V Say 'RDTaddapi.'V RDTaddapi.V Say 'RDTaddrej.'V RDTaddrej.V Say 'RDTrewrite.'V RDTrewrite.V Say 'RDTdelete.'V RDTdelete.V Say 'RDTretry.'V RDTretry.V End V Return /********************************************************************/ /* Functions and subroutines. */ /* It is a bit of an overkill to have a subroutine per variable, */ /* but it gives scope for the analysis. */ /********************************************************************/ /* Readfile: read the whole file */ Readfile: Trace Off If VM_env Then Do 'PIPE <' fn ft fm '|UNPACK|STEM REC.' If RC <> 0 Then Do Say 'RC='RC 'from the PIPELINE to read the DFH0STAT' , 'input file' fn ft fm End End Else Do Call Read_LST End Return /* Read the DFH0STAT data from the LST queue. It is assumed that the JCL used for this job has the correct security to allow the LST queue entry to be read. */ Read_LST: Trace Off Address_env = Address() Address POWER 'GETQE LST JOBNAME' LST_jobname 'CLASS' LST_class 'JOBNUM' LST_jobnum , 'STEM REC.' If RC <> 0 Then Do Say 'RC='RC 'from the GETQE command to read the DFH0STAT LST queue' , 'entry' LST_jobname LST_class LST_jobnum End Address Value Address_env Return /* mm/dd/yy to yyyymmdd */ yyyymmdd: Procedure Trace Off Arg Indate . Return '20'||Substr(Indate,7,2)||Substr(Indate,1,2)||Substr(Indate,4,2) /* Initialise variables */ Initialise: Trace Off InDispatcher = 0 GVloissue = 0 GVhiissue = 0 Analysis. = '' Analysis.0 = 0 Loadccount = 0 Proftrans = 1 VSEvrm = '000' MN = 'OFF' MNEXC = 'OFF' MNPER = 'OFF' DMFerrors = 0 STATEOD = '00:00:00' STATINT = '03:00:00' Total_FILES_EXCPs = 0 Total_FILES_EXCPs_NSR = 0 Total_LSRPOOL_BufferRW = 0 Total_LSRPOOL_BufferR = 0 Total_LSRPOOL_BufferW = 0 Total_LSRPOOL_BufferHit = 0 RPeakMXTdelay = Bignum(0) /* In case the report value is missing */ RStatinterval = Bignum(0) RAlltrans = Bignum(0) RTottrans = Bignum(0) Rmxt = Bignum(0) Rtimesmxt = Bignum(0) RPeakutrans = Bignum(0) RTotutrans = Bignum(0) Rdelaymxt = Bignum(0) Rdelaymxttime = Bigsecs('00:00:00') RICV = Bignum(0) RICVR = Bignum(0) RICVTSD = Bignum(0) RPRTYAGE = Bignum(0) RJScpu = Bigsecs('00:00:00') RCICSelapsed = Bigsecs('00:00:00') RQRdispatch = Bigsecs('00:00:00') RQRcpu = Bigsecs('00:00:00') RROcpu = Bigsecs('00:00:00') RSZcpu = Bigsecs('00:00:00') RSOcpu = Bigsecs('00:00:00') RSLcpu = Bigsecs('00:00:00') RSSLcpu = Bigsecs('00:00:00') BelowAbove = 'B' RGVsizelo = Bignum(0) RGVusedlo = Bignum(0) RGVmaxlo = Bignum(0) RDSAlim = Bignum(0) RDSApeak = Bignum(0) RDSAnostg = Bignum(0) RDSAsusp = Bignum(0) RDSAcush = Bignum(0) RDSASOS = Bignum(0) RDSASOSt = Bigsecs('00:00:00') RDSAviol = Bignum(0) REDSAlim = Bignum(0) REDSApeak = Bignum(0) REDSAnostg = Bignum(0) REDSAsusp = Bignum(0) REDSAcush = Bignum(0) REDSASOS = Bignum(0) REDSASOSt = Bigsecs('00:00:00') REDSAviol = Bignum(0) RGVsizehi = Bignum(0) RGVusedhi = Bignum(0) RGVmaxhi = Bignum(0) RLoadreq = Bignum(0) RLoadwait = Bignum(0) RLoadwaitt = Bigsecs('00:00:00') RLoadcompresslo = Bignum(0) RLoadcompresshi = Bignum(0) RTSPutmain = Bignum(0) RTSQGetmain = Bignum(0) RTSQpeakmain = Bignum(0) RTSQPutaux = Bignum(0) RTSQGetaux = Bignum(0) RTSQcreated = Bignum(0) RTSQthreshold = Bignum(0) RTSQextn = Bignum(0) RTSQCI = Bignum(0) RTSQCIpeak = Bignum(0) RTSQgtCIsize = Bignum(0) RTSQauxfull = Bignum(0) RTSQstring = Bignum(0) RTSQstringpeak = Bignum(0) RTSQstringwait = Bignum(0) RTSQpeakusers = Bignum(0) RTSQbuffers = Bignum(0) RTSQpeakbuffers = Bignum(0) RTSQbufferwait = Bignum(0) RTSQbufferread = Bignum(0) RTSQbufferwrite = Bignum(0) RTSQformatwrite = Bignum(0) RTSQIOerr = Bignum(0) InTS = 0 InTD = 0 RTDRead = Bignum(0) RTDWrite = Bignum(0) RTDformatWrite = Bignum(0) RTDCI = Bignum(0) RTDCIpeak = Bignum(0) RTDfull = Bignum(0) RTDstring = Bignum(0) RTDstringpeak = Bignum(0) RTDstringwait = Bignum(0) RTDpeakusers = Bignum(0) RTDbuffers = Bignum(0) RTDbufferpeak = Bignum(0) RTDbufferwait = Bignum(0) RTDpeakbuffers = Bignum(0) RTDIOerr = Bignum(0) InLSR = '' Do V = 1 to 15 RLSRkeylen.V = Bignum(0) RLSRstring.V = Bignum(0) RLSRstringpeak.V = Bignum(0) RLSRwait.V = Bignum(0) RLSRpeakwait.V = Bignum(0) RLSRdbuffers.V = Bignum(0) RLSRdlookaside.V = Bignum(0) RLSRdbufferread.V = Bignum(0) RLSRduserwrite.V = Bignum(0) RLSRdnuserwrite.V = Bignum(0) RLSRibuffers.V = Bignum(0) RLSRilookaside.V = Bignum(0) RLSRibufferread.V = Bignum(0) RLSRiuserwrite.V = Bignum(0) RLSRinuserwrite.V = Bignum(0) LSR_total_EXCPS.V = 0 End V TLSRdbuffers = Bignum(0) TLSRibuffers = Bignum(0) FILEname.0 = 0 FILEamethod.0 = 0 FILEtype.0 = 0 FILELSRpool.0 = 0 FILEstrmax.0 = 0 FILEstrwait.0 = 0 FILEread.0 = 0 FILEgetupdate.0 = 0 FILEbrowse.0 = 0 FILEadd.0 = 0 FILEupdate.0 = 0 FILEdelete.0 = 0 FILEdexcps.0 = 0 FILEiexcps.0 = 0 RDTname.0 = 0 RDTtype.0 = 0 RDTmaxnumrec.0 = 0 RDTread.0 = 0 RDTnrf.0 = 0 RDTaddread.0 = 0 RDTaddapi.0 = 0 RDTaddrej.0 = 0 RDTrewrite.0 = 0 RDTdelete.0 = 0 RDTretry.0 = 0 /* Process FILE EXCLUDE */ Fexclude. = 0 If VM_env Then Do 'PIPE FILEFAST FILE EXCLUDE | STRNFIND /*/ | STEM DATA.' End Else Do Call Read_Member 'EXFILE.A' End Do X=1 to Data.0 Parse Var Data.X Eapplid Fname . Fname7 = Left(Fname,7) Fexclude.Eapplid.Fname7 = True End /* Process DATATABL EXCLUDE removed 14.03.2013 */ Signal Skip_DATATABL DTexclude. = 0 If VM_env Then Do 'PIPE FILEFAST DATATABL EXCLUDE | STRNFIND /*/ | STEM DATA.' End Else Do Call Read_Member 'EXDATA.A' End Do X=1 to Data.0 Parse Var Data.X Eapplid Fname . Fname7 = Left(Fname,7) DTexclude.Eapplid.Fname7 = True End Skip_DATATABL: /* Process LSRPOOL EXCLUDE */ LSRPOOLexclude. = 0 If VM_env Then Do 'PIPE FILEFAST LSRPOOL EXCLUDE | STRNFIND /*/ | STEM DATA.' End Else Do Call Read_Member 'EXLSR.A' End Do X=1 to Data.0 Parse Var Data.X Eapplid LSRnumber . LSRnumber = LSRnumber+0 LSRPOOLexclude.Eapplid.LSRnumber = True End Return /* Read a VSE library EXCLUDE member into stem DATA. If we get an error, no data is returned and the RC is ignored. */ Read_Member: Trace Off Arg Member_name . Data.= '' Data.0 = 0 'EXECIO * DISKR' VSE_Sublibrary||'.'||Member_name '(STEM Temp. FINIS' If RC <> 0 Then Return Do Mem = 1 to Temp.0 If Substr(Temp.Mem,1,1) = '*' Then Iterate Data.0 = Data.0 + 1 X = Data.0 Data.X = Temp.Mem End Mem Return /* Remove duplicates in the VSE CSV data */ De_dup_data: Trace Off Arg Start_col End_Col . /* Check for illogical stem size */ If Oldrec.0 < 1 Then Do Say 'Invalid stem variable size, Oldrec.0='Oldrec.0 'in De_dup_data' Exit 999 End /* Maybe nothing more than the header, if so just copy it */ If Oldrec.0 = 1 Then Do Newrec.0 = 1 Newrec.1 = Oldrec.1 Return End /* Sort the stem so we can check for duplicates */ FC = Sortstem('Oldrec.','ZONE' Start_Col End_col,,'RANGE 2' Oldrec.0) If FC <> 0 Then Do Say 'RC='FC 'from Sortstem in De_dup_data' Exit 999 End Newrec. = '' Newrec.0 = 1 Newrec.1 = Oldrec.1 Do Rec = 2 to Oldrec.0 X = Rec - 1 If Oldrec.Rec == Oldrec.X then Iterate Newrec.0 = Newrec.0 + 1 X = Newrec.0 Newrec.X = Oldrec.Rec End Rec Return /* Create all the CSV files */ CreateCSV: Trace Off If NOCSV Then Return Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'TottransReset' ||',' Hdr = Hdr||'Tottrans' ||',' Hdr = Hdr||'Mxt' ||',' Hdr = Hdr||'Timesmxt' ||',' Hdr = Hdr||'Peakutrans' ||',' Hdr = Hdr||'Totutrans' ||',' Hdr = Hdr||'Delaymxt' ||',' Hdr = Hdr||'Delaymxttime' ||',' Hdr = Hdr||'Jscpu' ||',' Hdr = Hdr||'CICSelapsed' ||',' Hdr = Hdr||'Qrdispatch' ||',' Hdr = Hdr||'Qrcpu' ||',' Hdr = Hdr||'Rocpu' ||',' Hdr = Hdr||'Szcpu' ||',' Hdr = Hdr||'Socpu' ||',' Hdr = Hdr||'Slcpu' ||',' Hdr = Hdr||'SSLcpu' ||',' Hdr = Hdr||'DSAlim' ||',' Hdr = Hdr||'DSApeak' ||',' Hdr = Hdr||'DSAnostg' ||',' Hdr = Hdr||'DSAsusp' ||',' Hdr = Hdr||'DSAcush' ||',' Hdr = Hdr||'DSASOS' ||',' Hdr = Hdr||'DSASOSt' ||',' Hdr = Hdr||'DSAviol' ||',' Hdr = Hdr||'EDSAlim' ||',' Hdr = Hdr||'EDSApeak' ||',' Hdr = Hdr||'EDSAnostg' ||',' Hdr = Hdr||'EDSAsusp' ||',' Hdr = Hdr||'EDSAcush' ||',' Hdr = Hdr||'EDSASOS' ||',' Hdr = Hdr||'EDSASOSt' ||',' Hdr = Hdr||'EDSAviol' ||',' Hdr = Hdr||'Gvsizelo' ||',' Hdr = Hdr||'Gvusedlo' ||',' Hdr = Hdr||'Gvmaxlo' ||',' Hdr = Hdr||'Gvsizehi' ||',' Hdr = Hdr||'Gvusedhi' ||',' Hdr = Hdr||'Gvmaxhi' Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||RTottrans ||',' Crec = Crec||RAlltrans ||',' Crec = Crec||Rmxt ||',' Crec = Crec||Rtimesmxt ||',' Crec = Crec||RPeakutrans ||',' Crec = Crec||RTotutrans ||',' Crec = Crec||Rdelaymxt ||',' Crec = Crec||Rdelaymxttime ||',' Crec = Crec||RJScpu ||',' Crec = Crec||RCICSelapsed ||',' Crec = Crec||RQRdispatch ||',' Crec = Crec||RQRcpu ||',' Crec = Crec||RROcpu ||',' Crec = Crec||RSZcpu ||',' Crec = Crec||RSOcpu ||',' Crec = Crec||RSLcpu ||',' Crec = Crec||RSSLcpu ||',' Crec = Crec||RDSAlim ||',' Crec = Crec||RDSApeak ||',' Crec = Crec||RDSAnostg ||',' Crec = Crec||RDSAsusp ||',' Crec = Crec||RDSAcush ||',' Crec = Crec||RDSASOS ||',' Crec = Crec||RDSASOSt ||',' Crec = Crec||RDSAviol ||',' Crec = Crec||REDSAlim ||',' Crec = Crec||REDSApeak ||',' Crec = Crec||REDSAnostg ||',' Crec = Crec||REDSAsusp ||',' Crec = Crec||REDSAcush ||',' Crec = Crec||REDSASOS ||',' Crec = Crec||REDSASOSt ||',' Crec = Crec||REDSAviol ||',' Crec = Crec||RGVsizelo ||',' Crec = Crec||RGVusedlo ||',' Crec = Crec||RGVmaxlo ||',' Crec = Crec||RGVsizehi ||',' Crec = Crec||RGVusedhi ||',' Crec = Crec||RGVmaxhi If VM_env = True Then Do /* For each CSV file, we backup, append data, then remove duplicates. If the CSV file does not exist, we create the file to contain just the header, then we can append to it. */ 'PIPE STATE SUMMARY CSV A' If RC = 0 Then 'COPYFILE SUMMARY CSV A = BACKUP = (REP OLDD PACK' Else 'EXECIO 1 DISKW SUMMARY CSV A (FINIS VAR HDR' /* This format of EXECIO appends data */ 'EXECIO 1 DISKW SUMMARY CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv appending to SUMMARY CSV A' Exit 16 End 'PIPE < SUMMARY CSV A | DROP 1 | SORT 1-31 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > SUMMARY CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated SUMMARY CSV A' Exit 16 End End Else Do /* For VSE we copy the input to the output and append the new data */ 'EXECIO * DISKR SUMMIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Oldrec.0 = Oldrec.0 + 1 X = Oldrec.0 Oldrec.X = CREC End Else Do Oldrec.0 = 2 Oldrec.1 = HDR Oldrec.2 = CREC End Call De_dup_data 1 31 'EXECIO' NEWREC.0 'DISKW SUMMOUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated SUMMOUT' Exit 16 End End Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'Loadreq' ||',' Hdr = Hdr||'Loadwait' ||',' Hdr = Hdr||'Loadwaitt' ||',' Hdr = Hdr||'Loadcompresslo' ||',' Hdr = Hdr||'Loadcompresshi' Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||RLoadreq ||',' Crec = Crec||RLoadwait ||',' Crec = Crec||RLoadwaitt ||',' Crec = Crec||RLoadcompresslo ||',' Crec = Crec||RLoadcompresshi If VM_env = True Then Do 'PIPE STATE LOADER CSV A' If RC = 0 Then 'COPYFILE LOADER CSV A = BACKUP = (REP OLDD PACK' Else 'EXECIO 1 DISKW LOADER CSV A (FINIS VAR HDR' 'EXECIO 1 DISKW LOADER CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv appending to LOADER CSV A' Exit 16 End 'PIPE < LOADER CSV A | DROP 1 | SORT 1-31 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > LOADER CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated LOADER CSV A' Exit 16 End End Else Do 'EXECIO * DISKR LDRIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Oldrec.0 = Oldrec.0 + 1 X = Oldrec.0 Oldrec.X = CREC End Else Do Oldrec.0 = 2 Oldrec.1 = HDR Oldrec.2 = CREC End Call De_dup_data 1 31 'EXECIO' NEWREC.0 'DISKW LDROUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated LDROUT' Exit 16 End End Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'TSPutmain' ||',' Hdr = Hdr||'TSQGetmain' ||',' Hdr = Hdr||'TSQpeakmain' ||',' Hdr = Hdr||'TSQPutaux' ||',' Hdr = Hdr||'TSQGetaux' ||',' Hdr = Hdr||'TSQcreated' ||',' Hdr = Hdr||'TSQextn' ||',' Hdr = Hdr||'TSQCI' ||',' Hdr = Hdr||'TSQCIpeak' ||',' Hdr = Hdr||'TSQgtCIsize' ||',' Hdr = Hdr||'TSQauxfull' ||',' Hdr = Hdr||'TSQstring' ||',' Hdr = Hdr||'TSQstringpeak' ||',' Hdr = Hdr||'TSQstringwait' ||',' Hdr = Hdr||'TSQpeakusers' ||',' Hdr = Hdr||'TSQbuffers' ||',' Hdr = Hdr||'TSQpeakbuffers' ||',' Hdr = Hdr||'TSQbufferwait' ||',' Hdr = Hdr||'TSQbufferread' ||',' Hdr = Hdr||'TSQbufferwrite' ||',' Hdr = Hdr||'TSQformatwrite' ||',' Hdr = Hdr||'TSQIOerr' Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||RTSPutmain ||',' Crec = Crec||RTSQGetmain ||',' Crec = Crec||RTSQpeakmain ||',' Crec = Crec||RTSQPutaux ||',' Crec = Crec||RTSQGetaux ||',' Crec = Crec||RTSQcreated ||',' Crec = Crec||RTSQextn ||',' Crec = Crec||RTSQCI ||',' Crec = Crec||RTSQCIpeak ||',' Crec = Crec||RTSQgtCIsize ||',' Crec = Crec||RTSQauxfull ||',' Crec = Crec||RTSQstring ||',' Crec = Crec||RTSQstringpeak ||',' Crec = Crec||RTSQstringwait ||',' Crec = Crec||RTSQpeakusers ||',' Crec = Crec||RTSQbuffers ||',' Crec = Crec||RTSQpeakbuffers ||',' Crec = Crec||RTSQbufferwait ||',' Crec = Crec||RTSQbufferread ||',' Crec = Crec||RTSQbufferwrite ||',' Crec = Crec||RTSQformatwrite ||',' Crec = Crec||RTSQIOerr If VM_env = True Then Do 'PIPE STATE TSQ CSV A' If RC = 0 Then 'COPYFILE TSQ CSV A = BACKUP = (REP OLDD PACK' Else 'EXECIO 1 DISKW TSQ CSV A (FINIS VAR HDR' 'EXECIO 1 DISKW TSQ CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv appending to TSQ CSV A' Exit 16 End 'PIPE < TSQ CSV A | DROP 1 | SORT 1-31 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > TSQ CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated TSQ CSV A' Exit 16 End End Else Do 'EXECIO * DISKR TSQIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Oldrec.0 = Oldrec.0 + 1 X = Oldrec.0 Oldrec.X = CREC End Else Do Oldrec.0 = 2 Oldrec.1 = HDR Oldrec.2 = CREC End Call De_dup_data 1 31 'EXECIO' NEWREC.0 'DISKW TSQOUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated TSQOUT' Exit 16 End End Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'TDRead' ||',' Hdr = Hdr||'TDWrite' ||',' Hdr = Hdr||'TDformatWrite' ||',' Hdr = Hdr||'TDCI' ||',' Hdr = Hdr||'TDCIpeak' ||',' Hdr = Hdr||'Tdfull' ||',' Hdr = Hdr||'Tdstring' ||',' Hdr = Hdr||'Tdstringpeak' ||',' Hdr = Hdr||'Tdpeakusers' ||',' Hdr = Hdr||'Tdstringwait' ||',' Hdr = Hdr||'Tdbuffers' ||',' Hdr = Hdr||'Tdbufferpeak' ||',' Hdr = Hdr||'Tdbufferwait' ||',' Hdr = Hdr||'Tdpeakbuffers' ||',' Hdr = Hdr||'TDIOerr' Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||RTDRead ||',' Crec = Crec||RTDWrite ||',' Crec = Crec||RTDformatWrite ||',' Crec = Crec||RTDCI ||',' Crec = Crec||RTDCIpeak ||',' Crec = Crec||RTDfull ||',' Crec = Crec||RTDstring ||',' Crec = Crec||RTDstringpeak ||',' Crec = Crec||RTDpeakusers ||',' Crec = Crec||RTDstringwait ||',' Crec = Crec||RTDbuffers ||',' Crec = Crec||RTDbufferpeak ||',' Crec = Crec||RTDbufferwait ||',' Crec = Crec||RTDpeakbuffers ||',' Crec = Crec||RTDIOerr If VM_env = True Then Do 'PIPE STATE TD CSV A' If RC = 0 Then 'COPYFILE TD CSV A = BACKUP = (REP OLDD PACK' Else 'EXECIO 1 DISKW TD CSV A (FINIS VAR HDR' 'EXECIO 1 DISKW TD CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv appending to TD CSV A' Exit 16 End 'PIPE < TD CSV A | DROP 1 | SORT 1-31 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > TD CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated TD CSV A' Exit 16 End End Else Do 'EXECIO * DISKR TDIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Oldrec.0 = Oldrec.0 + 1 X = Oldrec.0 Oldrec.X = CREC End Else Do Oldrec.0 = 2 Oldrec.1 = HDR Oldrec.2 = CREC End Call De_dup_data 1 31 'EXECIO' NEWREC.0 'DISKW TDOUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated TDOUT' Exit 16 End End Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'LSRpool' ||',' Hdr = Hdr||'LSRkeylen' ||',' Hdr = Hdr||'LSRstring' ||',' Hdr = Hdr||'LSRstringpeak' ||',' Hdr = Hdr||'LSRwait' ||',' Hdr = Hdr||'LSRpeakwait' ||',' Hdr = Hdr||'LSRdbuffers' ||',' Hdr = Hdr||'LSRdlookaside' ||',' Hdr = Hdr||'LSRdbufferread' ||',' Hdr = Hdr||'LSRduserwrite' ||',' Hdr = Hdr||'LSRdnuserwrite' ||',' Hdr = Hdr||'LSRibuffers' ||',' Hdr = Hdr||'LSRilookaside' ||',' Hdr = Hdr||'LSRibufferread' ||',' Hdr = Hdr||'LSRiuserwrite' ||',' Hdr = Hdr||'LSRinuserwrite' If VM_env = True Then Do 'PIPE STATE LSRPOOL CSV A' If RC = 0 Then 'COPYFILE LSRPOOL CSV A = BACKUP = (REP OLDD PACK' Else Do 'EXECIO 1 DISKW LSRPOOL CSV A (FINIS VAR HDR' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating LSRPOOL CSV A' Exit 16 End End End Else Do 'EXECIO * DISKR LSRIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Nop End Else Do Oldrec.0 = 1 Oldrec.1 = HDR End End Do V = 1 to 15 If RLSRkeylen.V = 0 Then Iterate Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||Right(V,2,'0') ||',' Crec = Crec||RLSRkeylen.V ||',' Crec = Crec||RLSRstring.V ||',' Crec = Crec||RLSRstringpeak.V ||',' Crec = Crec||RLSRwait.V ||',' Crec = Crec||RLSRpeakwait.V ||',' Crec = Crec||RLSRdbuffers.V ||',' Crec = Crec||RLSRdlookaside.V ||',' Crec = Crec||RLSRdbufferread.V ||',' Crec = Crec||RLSRduserwrite.V ||',' Crec = Crec||RLSRdnuserwrite.V ||',' Crec = Crec||RLSRibuffers.V ||',' Crec = Crec||RLSRilookaside.V ||',' Crec = Crec||RLSRibufferread.V ||',' Crec = Crec||RLSRiuserwrite.V ||',' Crec = Crec||RLSRinuserwrite.V If VM_env = True Then Do 'EXECIO 1 DISKW LSRPOOL CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv adding to LSRPOOL CSV A' Exit 16 End End Else Do Oldrec.0 = Oldrec.0 + 1 x = Oldrec.0 Oldrec.x = CREC End End V If VM_env = True Then Do 'PIPE < LSRPOOL CSV A | DROP 1 | SORT 1-36 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > LSRPOOL CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated LSRPOOL CSV A' Exit 16 End End Else Do Call De_dup_data 1 36 'EXECIO' NEWREC.0 'DISKW LSROUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated LSROUT' Exit 16 End End Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'FILEname' ||',' Hdr = Hdr||'FILEamethod' ||',' Hdr = Hdr||'FILEtype' ||',' Hdr = Hdr||'FILELSRpool' ||',' Hdr = Hdr||'FILEstrmax' ||',' Hdr = Hdr||'FILEstrwait' ||',' Hdr = Hdr||'FILEread' ||',' Hdr = Hdr||'FILEgetupdate' ||',' Hdr = Hdr||'FILEbrowse' ||',' Hdr = Hdr||'FILEadd' ||',' Hdr = Hdr||'FILEupdate' ||',' Hdr = Hdr||'FILEdelete' ||',' Hdr = Hdr||'FILEdexcps' ||',' Hdr = Hdr||'FILEiexcps' If VM_env = True Then Do 'PIPE STATE FILE CSV A' If RC = 0 Then 'COPYFILE FILE CSV A = BACKUP = (REP OLDD PACK' Else Do 'EXECIO 1 DISKW FILE CSV A (FINIS VAR HDR' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating FILE CSV A' Exit 16 End End End Else Do 'EXECIO * DISKR FILEIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Nop End Else Do Oldrec.0 = 1 Oldrec.1 = HDR End End Do V = 1 to Filename.0 Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||FILEname.V ||',' Crec = Crec||FILEamethod.V ||',' Crec = Crec||FILEtype.V ||',' Crec = Crec||FILELSRpool.V ||',' Crec = Crec||FILEstrmax.V ||',' Crec = Crec||FILEstrwait.V ||',' Crec = Crec||FILEread.V ||',' Crec = Crec||FILEgetupdate.V ||',' Crec = Crec||FILEbrowse.V ||',' Crec = Crec||FILEadd.V ||',' Crec = Crec||FILEupdate.V ||',' Crec = Crec||FILEdelete.V ||',' Crec = Crec||FILEdexcps.V ||',' Crec = Crec||FILEIexcps.V If VM_env = True Then Do 'EXECIO 1 DISKW FILE CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv adding to FILE CSV A' Exit 16 End End Else Do Oldrec.0 = Oldrec.0 + 1 x = Oldrec.0 Oldrec.x = CREC End End V If VM_env = True Then Do 'PIPE < FILE CSV A | DROP 1 | SORT 1-39 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > FILE CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated FILE CSV A' Exit 16 End End Else Do Call De_dup_data 1 39 'EXECIO' NEWREC.0 'DISKW FILEOUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated FILEOUT' Exit 16 End End Hdr = '' Hdr = Hdr||'Applid' ||',' Hdr = Hdr||'Sysid' ||',' Hdr = Hdr||'CICSDate' ||',' Hdr = Hdr||'CICSTime' ||',' Hdr = Hdr||'DTname' ||',' Hdr = Hdr||'DTtype' ||',' Hdr = Hdr||'DTmaxnumrec' ||',' Hdr = Hdr||'DTread' ||',' Hdr = Hdr||'DTnrf' ||',' Hdr = Hdr||'DTaddread' ||',' Hdr = Hdr||'DTaddapi' ||',' Hdr = Hdr||'DTaddrej' ||',' Hdr = Hdr||'DTrewrite' ||',' Hdr = Hdr||'DTdelete' ||',' Hdr = Hdr||'DTretry' If VM_env = True Then Do 'PIPE STATE DTIO CSV A' If RC = 0 Then 'COPYFILE DTIO CSV A = BACKUP = (REP OLDD PACK' Else Do 'EXECIO 1 DISKW DTIO CSV A (FINIS VAR HDR' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating DTIO CSV A' Exit 16 End End End Else Do 'EXECIO * DISKR DTIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' If RC = 0 Then Do Nop End Else Do Oldrec.0 = 1 Oldrec.1 = HDR End End Do V = 1 to RDTname.0 Crec = '' Crec = Crec||Left(RApplid,8) ||',' Crec = Crec||Left(RSysid,4) ||',' Crec = Crec||RdateGreg ||',' Crec = Crec||Rtime ||',' Crec = Crec||RDTname.V ||',' Crec = Crec||RDTtype.V ||',' Crec = Crec||RDTmaxnumrec.V ||',' Crec = Crec||RDTread.V ||',' Crec = Crec||RDTnrf.V ||',' Crec = Crec||RDTaddread.V ||',' Crec = Crec||RDTaddapi.V ||',' Crec = Crec||RDTaddrej.V ||',' Crec = Crec||RDTrewrite.V ||',' Crec = Crec||RDTdelete.V ||',' Crec = Crec||RDTretry.V If VM_env = True Then Do 'EXECIO 1 DISKW DTIO CSV A (FINIS VAR CREC' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv adding to DTIO CSV A' Exit 16 End End Else Do Oldrec.0 = Oldrec.0 + 1 x = Oldrec.0 Oldrec.x = CREC End End V If VM_env = True Then Do 'PIPE FILEFAST DTIO CSV A | DROP 1 | SORT 1-39 |' , 'UNIQUE FIRST | LITERAL 'Hdr'| > DTIO CSV A' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated DTIO CSV A' Exit 16 End End Else Do Call De_dup_data 1 39 'EXECIO' NEWREC.0 'DISKW DTOUT (FINIS STEM NEWREC. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in Createcsv creating de-duplicated DTOUT' Exit 16 End End Return /* Work out the VSE level. Version 6 is VSE/ESA V2, version 7 is z/VSE V3, 8 is z/VSE 4 etc. */ VSErel: Trace Off Parse Var Rec.I 'VSE/AF' VSEvrm . VSEvrm = Strip(VSEvrm) Select When Substr(VSEvrm,1,1) = '6' Then Do VSEvrm = '2'||Substr(VSEvrm,2) VSElevel = 'VSE/ESA' VSEvrm End When Substr(VSEvrm,1,1) = '7' Then Do VSEvrm = '3'||Substr(VSEvrm,2) VSElevel = 'z/VSE' VSEvrm End When Substr(VSEvrm,1,1) = '8' Then Do VSEvrm = '4'||Substr(VSEvrm,2) VSElevel = 'z/VSE' VSEvrm End When Substr(VSEvrm,1,1) = '9' Then Do VSEvrm = '5'||Substr(VSEvrm,2) VSElevel = 'z/VSE' VSEvrm End Otherwise VSElevel = 'Unknown z/VSE' VSEvrm End /* Select */ Call IN_Analysis '**** VSE software level is' VSElevel Return /* Check storage protection */ STORprotect: Trace Off Parse Var Rec.I ':' Status . If Status <> 'ACTIVE' Then Do Call BP_Analysis 'SIT STGPROT=NO is set, YES should be used' End Return /* Check reentrant program protection */ RENTprotect: Trace Off Parse Var Rec.I ':' Status . If Status <> 'PROTECT' Then Do Call BP_Analysis 'SIT RENTPGM=NOPROTECT is set, PROTECT should be used' End Return /* Check CICS monitoring */ Monitoring: Trace Off Parse Var Rec.I ':' MN . Return Exceptionclass: Trace Off Parse Var Rec.I ':' MNEXC . If MNEXC = 'OFF' & MN = 'ON' Then Do Call BP_Analysis 'MONITOR exception records are OFF' , 'but monitoring is ON' end Return ExceptionclassRec: Trace Off Parse Var Rec.I ':' MNEXCRec MNEXCRec=Bignum(MNEXCrec) If MNEXCRec > TMONexception Then Do Call TH_Analysis 'MONITOR exception records were produced,', Forbig(MNEXCRec) 'SOS/DFHTEMP/VSAM resource limit waits occurred' End Return Performanceclass: Trace Off Parse Var Rec.I ':' MNPER . Return /* Performance class records */ PerformanceclassRec: Trace Off Parse Var Rec.I ':' MNPERRec . MNPERRec=Bignum(MNPERRec) Return /* Performance class records suppressed */ PerformanceclassRecSupp: Trace Off Parse Var Rec.I ':' MNPERRecSupp . MNPERRecSupp=Bignum(MNPERRecSupp) If MNPERRec - MNPERRecSupp > 0 Then Do Call PM_Analysis 'CICS Performance Monitoring is active' End /* Check for TMON */ If MNPERRec - MNPERRecSupp = 0 & MNPERRec > 0 Then Do Call PM_Analysis 'TMON Performance Monitoring appears to be active' End Return /* Check DMF errors */ DMFerrors: Trace Off Parse Var Rec.I ':' DMFerrs . DMFerrs = Bignum(DMFerrs) If DMFerrs > EDMFerrs Then Do Call TH_Analysis 'DMF errors were reported, the total is' , Forbig(DMFerrs) 'and CICS monitoring is' MN End Return Statinterval: Trace Off Parse Var Rec.I ':' hh ':' mm ':' ss . If RStatinterval <> 0 Then Do Say '**** Possible duplicate data found by Statinterval ****' Call Execfail 'Possible duplicate data found by Statinterval' End Return Statrecording: Trace Off Parse Var Rec.I ':' Recording . /* Reset_done = 0 */ If Recording = 'ON' Then Do Call PM_Analysis '**** CICS statistics recording is ON,' , 'some of the PROFILE calculations may be incorrect' /* Reset_done = 1 */ End Return /* Total CICS and user transactions since CICS started */ Alltrans: Trace Off Parse Var Rec.I ':' Num . RAlltrans = Bignum(Num) Call IN_Analysis 'TRANSACTION total since CICS started ' Forbig(RAlltrans) Return /* Total CICS and user transactions (since reset) */ Tottrans: Trace Off Parse Var Rec.I ':' Num . RTottrans = Bignum(Num) Call IN_Analysis 'TRANSACTION total since the last reset' Forbig(RTottrans) Proftrans = RTottrans Call PM_Analysis '**** Transaction count for the profile calculations is', Forbig(Proftrans) 'unless specfied otherwise' /* Check if reset was likely to have been done */ Reset_done = 0 /* Handle the case where the total number of transactions is VERY close to the number of transactions since reset. If you don't like this, set Reset_fudge_factor to 1. */ Reset_fudge_factor = 0.98 Fudged_RAlltrans = Trunc(RAlltrans * Reset_fudge_factor) If Proftrans < Fudged_RAlltrans Then Do Reset_done = 1 Call PM_Analysis '**** A Statistics Data reset appears' , 'to have occurred' End Return /* Current MXT */ Mxt: Trace Off Parse Var Rec.I ':' Num . Rmxt = Bignum(Num) Return /* Times at MXT */ Timesmxt: Trace Off Parse Var Rec.I ':' Num . Rtimesmxt = Bignum(Num) Return /* Peak number of user transaction, these are subject to MXT. If we were at MXT, don't check for being close to it. */ Peakutrans: Trace Off Parse Var Rec.I ':' Num . RPeakutrans = Bignum(Num) Call PM_Analysis 'TRANSACTION MXT peak usage is' Forbig(RPeakutrans) If Rmxt > 0 Then Do If Format((RPeakutrans*100)/Rmxt,,0) > TMXTpeakutran , & Rtimesmxt = 0 Then Do Call TH_Analysis 'MXT peak usage is', Format((RPeakutrans*100)/Rmxt,3,0)||'% of MXT' Forbig(Rmxt) End End Return /* Number of transactions delayed by MXT */ Delaymxt: Trace Off Parse Var Rec.I ':' Num . Rdelaymxt = Bignum(Num) Return /* Number of transactions currently delayed by MXT */ DelaymxtC: Trace Off Parse Var Rec.I ':' Num . Rdelaymxt = Rdelaymxt + Bignum(Num) Return DelaypeakMXT: Trace Off Parse Var Rec.I ':' Num . RPeakMXTdelay = Bignum(Num) Return /* Time spent in MXT wait */ Delaymxttime: Trace Off Parse Var Rec.I ':' Num . Rdelaymxttime = Bigsecs(Num) Return DelaymxttimeC: Trace Off Parse Var Rec.I ':' Num . Rdelaymxttime = Rdelaymxttime + Bigsecs(Num) If Rdelaymxttime > LMXTdelaytime Then Do Call LI_Analysis 'MXT queuing time' Format(Rdelaymxttime/60,6,2) 'minutes' End /* Check MXT delays now we have all of the data */ If Rdelaymxt > LMXTdelay Then Do If RPeakMXTdelay > 0 Then Do Call LI_Analysis 'MXT delayed' Forbig(Rdelaymxt) 'transactions,' , 'consider increasing the current MXT' Forbig(Rmxt)||, ' the peak number of tasks queued was' Forbig(RPeakMXTdelay) End Else Do Call LI_Analysis 'MXT delayed' Forbig(Rdelaymxt) 'transactions,' , 'consider increasing the current MXT' Forbig(Rmxt) End End Return /* Total user transactions */ Totutrans: Trace Off Parse Var Rec.I ':' Num . Rtotutrans = Bignum(Num) Return /* ICV */ ICV: Trace Off /* 01.03.2012 Ignore ICV Parse Var Rec.I ':' Num . RICV = Msecs(Num) If RICV < TICV Then Do Call BP_Analysis 'SIT ICV' RICV+0 'is lower than the recommended' TICV+0 End */ Return /* ICVR */ ICVR: Trace Off Parse Var Rec.I ':' Num . RICVR = Msecs(Num) If RICVR > BICVR Then Do Call BP_Analysis 'SIT ICVR' RICVR+0 'is higher than the suggested' BICVR+0 End Return /* ICVTSD */ ICVTSD: Trace Off Parse Var Rec.I ':' Num . RICVTSD = Msecs(Num) If RICVTSD > TICVTSD Then Do Call BP_Analysis 'SIT ICVTSD' RICVTSD+0 'is higher than the recommended' , TICVTSD+0 End Return /* PRTYAGE */ Prtyage: Trace Off Parse Var Rec.I ':' Num . RPRTYAGE = Msecs(Num) If RPRTYAGE > BPRTYAGE Then Do Call BP_Analysis 'SIT PRTYAGE='||RPRTYAGE+0 'is set,' , 'a value between 0 and' BPRTYAGE 'is normally recommended' End Return /* Job Step cpu time is only collected if my modified versions of DFH0STAT and DFH$STAS are used */ JScpu: Trace Off Parse Var Rec.I ':' Num . RJScpu = Bigsecs(Num) Return QRTCB: Trace Off Parse Var Rec.I . . . VSEwaits wait dispatch cpu dscpu . RCICSelapsed = Bigsecs(wait) + Bigsecs(dispatch) RCICSelapsed = Forsecs(RCICSelapsed) RCICSelapsed = Format(RCICSelapsed,,0) /* Round up to seconds */ Call PM_Analysis '**** Elapsed time for the profile calculations is' , Format(RCICSelapsed/3600,6,4) 'hours' /* Not sure about this now. If Rdelaymxttime > LMXTdelaytime & RCICSelapsed > 0 Then Do Call LI_Analysis 'MXT queuing time' , Format((Rdelaymxttime*100)/RCICSelapsed,6,2)||'% of elapsed time' End */ /* May lose significant digits on number of waits */ If Substr(VSEwaits,1,1) ='0' Then do Call Em_Analysis 'QR_SUBD z/VSE wait count' VSEwaits , 'may have been truncated' End VSEwaits = Bignum(VSEwaits) Call PM_Analysis 'QR z/VSE wait count is' Forbig(VSEwaits) If Proftrans > 0 Then do Call PM_Analysis 'QR z/VSE wait count per transaction is' , Format(VSEwaits/Proftrans,6,5) End /* If RCICSelapsed < Tminelaps Then Do Call TH_Analysis '**** CICS elapsed time is less than the' , 'recommended' Tminelaps/3600 'hours, the data may not be useful' End */ If RCICSelapsed < 1 Then Do RCICSelapsed = 1 End /* Look out for bad dispatcher cpu time */ Select When Bigsecs(dscpu) > Bigsecs(cpu) , Then Do Call EM_Analysis 'DISPATCHER QR dispatcher cpu' dscpu 'is greater' , 'than TCB cpu' cpu', it has been set to zero' dscpu = '00:00:00.00000' End When Bigsecs(dscpu) > (Bigsecs(cpu) * (Edscpupcnt/100)) Then Do Call EM_Analysis 'DISPATCHER QR dispatcher cpu' dscpu 'may not' , 'be valid for TCB cpu' cpu', it has been used though' End Otherwise Nop End RQRdispatch = Bigsecs(dispatch) RQRcpu = Bigsecs(cpu) + Bigsecs(dscpu) RQRcpu = Forsecs(RQRcpu) QRdispelapsed = 0 If RCICSelapsed > 0 Then Do QRdispelapsed = Format((RQRdispatch*100)/RCICSelapsed,,0) End If QRdispelapsed > TQRdispelapsed Then Do Call TH_Analysis 'DISPATCHER QR TCB dispatch:elapsed ratio is' , Right(QRdispelapsed,3) ||'%,' , 'this may result in tasks queuing for cpu time' End TPS = 0 If RCICSelapsed > 0 Then Do TPS = Format(Proftrans/RCICSelapsed,5,2) Call PM_Analysis 'DISPATCHER average transactions per second is' TPS End If RQRdispatch > 0 Then Do Call PM_Analysis 'DISPATCHER QR cpu:dispatch ratio is' , Format((RQRcpu*100)/RQRdispatch,3,0)||'%' End Return /* TCBs other than QR */ XXTCB: Trace Off Parse Var Rec.I . . . . wait dispatch cpu dscpu . /* Look out for bad dispatcher cpu time */ Select When Bigsecs(dscpu) > Bigsecs(cpu) , Then Do Call EM_Analysis 'DISPATCHER non-QR dispatcher cpu' dscpu 'is greater' , 'than TCB cpu' cpu||', it has been set to zero' dscpu = '00:00:00.00000' End /* When Bigsecs(dscpu) > (Bigsecs(cpu) * (Edscpupcnt/100)) Then Do Call EM_Analysis 'DISPATCHER non-QR dispatcher cpu' dscpu 'may not be' , 'valid for TCB cpu' cpu||', it has been used though' End */ Otherwise Nop End Return Forsecs(Bigsecs(cpu) + Bigsecs(dscpu)) /* All TCBs */ TotalTCB: Trace Off Parse Var Rec.I . tdispatch tcpu tdscpu . /* Look out for bad dispatcher cpu time */ Select When Bigsecs(tdscpu) > Bigsecs(tcpu) , Then Do Call EM_Analysis 'DISPATCHER Total dispatcher cpu' tdscpu 'is greater' , 'than TCB cpu' tcpu||', it has been set to zero' tdscpu = '00:00:00.00000' End When Bigsecs(tdscpu) > (Bigsecs(tcpu) * (Edscpupcnt/100)) Then Do Call EM_Analysis 'DISPATCHER Total dispatcher cpu' tdscpu 'may not be' , 'valid for TCB cpu' tcpu||', it has been used though' End Otherwise Nop End Totcpu = Bigsecs(tcpu) + Bigsecs(tdscpu) Totdispatch = Bigsecs(tdispatch) CPUpertran = 0 If RJScpu <= 0 & Proftrans > 0 Then Do Call PM_Analysis 'DISPATCHER total cpu is' Format(Totcpu/3600,4,4), 'hours based on TCB cpu time', Format((Totcpu*100)/RCICSelapsed,5,2)'% average cpu utilisation' , Format(((Totcpu*100)/RCICSelapsed)/TPS,5,2)'%' , 'per transaction per second' CPUpertran = Format(Totcpu/Proftrans,,6) Call PM_Analysis 'DISPATCHER cpu per transaction is' , CPUpertran 'seconds based on TCB cpu time' /* No longer convinced about the next two being useful If RCICSelapsed > 0 Then Do /* Actual cpu:elapsed will be between the next two */ Call PM_Analysis 'DISPATCHER TCB cpu:elapsed ratio is' , Format((Totcpu*100)/RCICSelapsed,3,0)||'%' Call PM_Analysis 'DISPATCHER TCB dispatch:elapsed ratio is' , Format((Totdispatch*100)/RCICSelapsed,3,0)||'%' End */ End If RJScpu > 0 & RAlltrans > 0 Then Do If Reset_done = 0 /* We can show cpu% average if there was no reset as RCICSElapsed should match the whole CICS execution so far */ Then Do Call PM_Analysis 'DISPATCHER total cpu is' Format(RJScpu/3600,4,4), 'hours based on accumulated cpu time' , Format((RJScpu*100)/RCICSelapsed,5,2)'% average cpu utilisation' , Format(((RJScpu*100)/RCICSelapsed)/TPS,5,2)'%' , 'per transaction per second' End Else Do Call PM_Analysis 'DISPATCHER total cpu is' Format(RJScpu/3600,4,4), 'hours based on accumulated cpu time' , 'average cpu utilisation cannot been calculated due to a reset' End /* Base on RAlltrans (transactions since CICS started) not Proftrans */ CPUpertran = Format(RJScpu/RAlltrans,,6) Call PM_Analysis 'DISPATCHER cpu per transaction is' , CPUpertran 'seconds based on' , 'accumulated cpu time for' RAlltrans+0 'transactions' /* Base on Proftrans (transactions since reset) when we use TCB cpu */ Call PM_Analysis 'DISPATCHER cpu per transaction is' , Format(Totcpu/Proftrans,,6) 'seconds based on TCB' , 'cpu time' /* No longer convinced this is useful If RCICSelapsed > 0 Then Do Call PM_Analysis 'DISPATCHER Accumulated cpu time:elapsed ratio is' , Format((RJScpu*100)/RCICSelapsed,3,0)||'%' End */ End /* Cpu per transaction threshold */ If CPUpertran > TCPUpertran Then Do Call TH_Analysis 'DISPATCHER cpu per transaction' CPUpertran , 'seconds is greater than the threshold' TCPUpertran End /* Delete If RJScpu > 0 & Reset_done = 0 & Totcpu > 0 Then Do /* Adjust Job step cpu by QR cpu/Total TCB cpu */ Adj_RJScpu = RJScpu * (RQRcpu/Totcpu) Call PM_Analysis 'DISPATCHER QR cpu:dispatch ratio is approximately' , Min(Format((Adj_RJScpu*100)/RQRdispatch,3,0),100)||'% based on' , 'accumulated cpu time' /* Use all Job step cpu for QR cpu capture ratio */ Call PM_Analysis 'DISPATCHER QR cpu capture ratio is approximately' , Format((RQRcpu*100)/RJScpu,3,0)||'% based on' , 'accumulated cpu time' End */ Return /* Partition Getvis size below 16MB */ GVsizelo: Trace Off Parse Var Rec.I ':' Num 'K' . RGVsizelo = Bignum(Num) If RGVsizelo < TGVsizelo Then Do Call BP_Analysis 'GETVIS area size below 16MB is' , Forstor(RGVsizelo)', which is below the suggested' , Forstor(TGVsizelo) End Return /* Partition Getvis used below 16MB */ GVusedlo: Trace Off Parse Var Rec.I ':' Num 'K' . RGVusedlo = Bignum(Num) If RGVsizelo > 0 Then Do GVusedlopcnt = Format((RGVusedlo*100)/RGVsizelo,,0) If GVusedlopcnt > TGVloused Then Do If Forstor(RGVsizelo-RGVusedlo) <> '0K' Then Do Call TH_Analysis 'GETVIS below 16MB has only' , Forstor(RGVsizelo-RGVusedlo) 'available based on current usage' End Else Do Call LI_Analysis 'GETVIS below 16MB has ' , Forstor(RGVsizelo-RGVusedlo) 'available based on current usage' End GVloissue = 1 End End Return /* Partition Getvis maximum used below 16MB. Note that 100% is usually due to forgetting to issue VSE command: GETVIS xx,RESET */ GVmaxlo: Trace Off Parse Var Rec.I ':' Num 'K' . RGVmaxlo = Bignum(Num) If RGVsizelo > 0 Then Do GVmaxlopcnt = Format((RGVmaxlo*100)/RGVsizelo,,0) If GVmaxlopcnt > TGVlomax & GVmaxlopcnt < 100 Then Do If Forstor(RGVsizelo-RGVmaxlo) <> '0K' Then Do Call TH_Analysis 'GETVIS below 16MB has only' , Forstor(RGVsizelo-RGVmaxlo) 'available based on maximum usage' End Else Do Call LI_Analysis 'GETVIS below 16MB has ' , Forstor(RGVsizelo-RGVmaxlo) 'available based on maximum usage' End GVloissue = 1 End If GVmaxlopcnt >= 100 Then Do Call BP_Analysis 'GETVIS below 16MB maximum used is 100%,' , 'a GETVIS xx,RESET after CICS starts may be required' GVloissue = 1 End End Return /* Current DSALIM */ DSAlim: Trace Off Parse Var Rec.I ':' Num 'K' . RDSAlim = Bignum(Num) Return /* Peak DSALIM */ DSApeak: Trace Off Parse Var Rec.I ':' Num 'K' . RDSApeak = Bignum(Num) Call PM_Analysis 'DSALIM peak usage is' , Forstor(RDSApeak)||', DSALIM is' Forstor(RDSAlim) If RDSAlim > 0 Then Do DSApcnt = Format((RDSApeak*100)/RDSAlim,,0) Select When DSApcnt > 99 Then Do Call LI_Analysis 'DSALIM peak usage' , Format((RDSApeak*100)/RDSAlim,3,0)||'%,' , Forstor(RDSAlim-RDSApeak) 'is available' End When DSApcnt > TDSApeak Then Do Call TH_Analysis 'DSALIM peak usage' , Format((RDSApeak*100)/RDSAlim,3,0)||'%,' , Forstor(RDSAlim-RDSApeak) 'is available' End Otherwise End /* Potential storage avoids using the last available extent */ If GVloissue = 1 & (RDSAlim+0)-(RDSApeak+0)-256 > 0 Then Do Call IN_Analysis 'GETVIS CICS DSA potentially available for' , "Getvis based on today's data is" , Forstor((RDSAlim+0)-(RDSApeak+0)-256) End End Return /* Times no storage returned */ DSAnostg: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . RDSAnostg = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) RDSAnostg = Bignum(RDSAnostg) If RDSAnostg > LDSAnostg Then Do Call LI_Analysis 'DSALIM Getmain below requests had response' , '"No Storage" returned' Forbig(RDSAnostg) 'times' End Return /* Times suspended for storage */ DSAsusp: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . RDSAsusp = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) RDSAsusp = Bignum(RDSAsusp) If RDSAsusp > LDSAsusp Then Do Call LI_Analysis 'DSALIM Getmain below requests caused task' , 'suspends' Forbig(RDSAsusp) 'times' End Return /* Times cushion released - warning of SOS */ DSAcush: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . RDSAcush = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) RDSAcush = Bignum(RDSAcush) If RDSAcush > LDSAcush Then Do Call TH_Analysis 'DSALIM cushion released' Forbig(RDSAcush) 'times,' , 'CICS was approaching SOS below 16MB' End Return /* SOS */ DSASOS: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . RDSASOS = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) RDSASOS = Bignum(RDSASOS) If RDSASOS > LDSASOS Then Do Call LI_Analysis 'DSALIM SOS below 16MB' Forbig(RDSASOS) 'times' End Return /* Time spent in SOS */ DSASOSt: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . RDSASOSt = Bigsecs(Num1)+Bigsecs(Num2)+Bigsecs(Num3)+Bigsecs(Num4) RDSASOSt = Forsecs(RDSASOSt) If RDSASOSt > LDSASOSt Then Do Call LI_Analysis 'DSALIM SOS time below 16MB' Format(RDSASOSt/60,6,2) 'minu tes' End Return /* Storage violations */ DSAviol: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . RDSAviol = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) RDSAviol = Bignum(RDSAviol) If RDSAviol > EDSAviol Then Do Call EM_Analysis 'DSALIM storage violations below 16MB' , Forbig(RDSAviol) 'times' End Return /* Current EDSALIM */ EDSAlim: Trace Off Parse Var Rec.I ':' Num 'K' . REDSAlim = Bignum(Num) Return /* Trace table size */ Tracesize: Trace Off Parse Var Rec.I ':' Num 'K' . Trtabsz = Bignum(Num) If Trtabsz < 4096 Then Do Call BP_Analysis 'SIT TRTABSZ trace table size' Trtabsz+0||'K is less' , 'than the recommended 4,096K' End Return /* Peak EDSALIM */ EDSApeak: Trace Off Parse Var Rec.I ':' Num 'K' . REDSApeak = Bignum(Num) Call PM_Analysis 'EDSALIM peak usage is' , Forstor(REDSApeak)||', EDSALIM is' Forstor(REDSAlim) If REDSAlim > 0 Then Do EDSApcnt = Format((REDSApeak*100)/REDSAlim,,0) Select When EDSApcnt > 99 Then Do Call LI_Analysis 'EDSALIM peak usage' , Format((REDSApeak*100)/REDSAlim,3,0)||'%,' , Forstor(REDSAlim-REDSApeak) 'is available' End When EDSApcnt > TEDSApeak Then Do Call TH_Analysis 'EDSALIM peak usage' , Format((REDSApeak*100)/REDSAlim,3,0)||'%,' , Forstor(REDSAlim-REDSApeak) 'is available' End Otherwise End /* Potential storage avoids using the last available extent If GVhiissue Then Do Call IN_Analysis 'GETVIS CICS EDSA potentially available for' , "Getvis based on today's data is" , Forstor((REDSAlim+0)-(REDSApeak+0)-1024) End */ End Return /* Times no storage returned */ EDSAnostg: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . REDSAnostg = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) REDSAnostg = Bignum(REDSAnostg) If REDSAnostg > LEDSAnostg Then Do Call LI_Analysis 'EDSALIM Getmain above requests had response' , '"No Storage" returned' Forbig(REDSAnostg) 'times' End Return /* Times request suspended for storage */ EDSAsusp: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . REDSAsusp = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) REDSAsusp = Bignum(REDSAsusp) If REDSAsusp > LEDSAsusp Then Do Call LI_Analysis 'EDSALIM Getmain above requests caused task' , 'suspends' Forbig(REDSAsusp) 'times' End Return /* Times cushion released - warning of SOS */ EDSAcush: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . REDSAcush = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) REDSAcush = Bignum(REDSAcush) If REDSAcush > LEDSAcush Then Do Call TH_Analysis 'EDSALIM cushion released' Forbig(REDSAcush) 'times,' , 'CICS was approaching SOS above 16MB' End Return /* SOS */ EDSASOS: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . REDSASOS = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) REDSASOS = Bignum(REDSASOS) If REDSASOS > LEDSASOS Then Do Call LI_Analysis 'EDSALIM SOS above 16MB' Forbig(REDSASOS) 'times' End Return /* SOS time */ EDSASOSt: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . REDSASOSt = Bigsecs(Num1)+Bigsecs(Num2)+Bigsecs(Num3)+Bigsecs(Num4) REDSASOSt = Forsecs(REDSASOSt) If REDSASOSt > LEDSASOSt Then Do Call LI_Analysis 'EDSALIM SOS time above 16MB' Format(REDSASOSt/60,6,2) 'min utes' End Return /* Storage violations */ EDSAviol: Trace Off Parse Var Rec.I ':' Num1 Num2 Num3 Num4 . REDSAviol = Bignum(Num1)+Bignum(Num2)+Bignum(Num3)+Bignum(Num4) REDSAviol = Bignum(REDSAviol) If REDSAviol > EEDSAviol Then Do Call EM_Analysis 'EDSALIM storage violations above 16MB' , Forbig(REDSAviol) 'times' End Return /* Partition Getvis area size above 16MB */ GVsizehi: Trace Off Parse Var Rec.I ':' Num 'K' . RGVsizehi = Bignum(Num) Return /* Partition Getvis area used above 16MB */ GVusedhi: Trace Off Parse Var Rec.I ':' Num 'K' . RGVusedhi = Bignum(Num) If RGVsizehi > 0 Then Do GVusedhipcnt = Format((RGVusedhi*100)/RGVsizehi,,0) If GVusedhipcnt > TGVhiused Then Do If Forstor(RGVsizehi-RGVusedhi) <> '0K' Then Do Call TH_Analysis 'GETVIS above 16MB has only' , Forstor(RGVsizehi-RGVusedhi) 'available based on current usage' End Else Do Call LI_Analysis 'GETVIS above 16MB has ' , Forstor(RGVsizehi-RGVusedhi) 'available based on current usage' End GVhiissue = 1 End End Return /* Partition Getvis area maximum used above 16MB */ GVmaxhi: Trace Off Parse Var Rec.I ':' Num 'K' . RGVmaxhi = Bignum(Num) If RGVsizehi > 0 Then Do GVmaxhipcnt = Format((RGVmaxhi*100)/RGVsizehi,,0) If GVmaxhipcnt > TGVhimax Then Do If Forstor(RGVsizehi-RGVmaxhi) <> '0K' Then Do Call TH_Analysis 'GETVIS above 16MB has only' , Forstor(RGVsizehi-RGVmaxhi) 'available based on maximum usage' End Else Do Call LI_Analysis 'GETVIS above 16MB has ' , Forstor(RGVsizehi-RGVmaxhi) 'available based on maximum usage' End GVhiissue = 1 End End Return /* Total program load requests */ Loadreq: Trace Off Parse Var Rec.I ':' Num . RLoadreq = Bignum(Num) Return /* Load requests that waited */ Loadwait: Trace Off Parse Var Rec.I ':' Num . RLoadwait = Bignum(Num) If RLoadwait > TLoadwait Then Do Call TH_Analysis 'LOADER requests waited' Forbig(Rloadwait) 'times' End Return /* Time spent waiting for Load */ Loadwaitt: Trace Off Parse Var Rec.I ':' Num . RLoadwaitt = Bigsecs(Num) If RLoadwaitt > TLoadwaitt Then Do Call TH_Analysis 'LOADER request wait time' , Forsecs(RLoadwaitt) 'seconds' End Return /* Programs removed by compression */ Loadcompress: Trace Off Parse Var Rec.I ':' Num1 . ':' Num2 . RLoadcompresslo = RLoadcompresslo+Bignum(Num1) RLoadcompresslo = Bignum(RLoadcompresslo) RLoadcompresshi = RLoadcompresshi+Bignum(Num2) RLoadcompresshi = Bignum(RLoadcompresshi) Loadccount = Loadccount + 1 If Loadccount < 3 Then Return If RLoadcompresslo > TLoadcompresslo Then Do Call TH_Analysis 'DSALIM program compression activity removed' , Forbig(Rloadcompresslo) , 'programs, CICS was approaching SOS below' End If RLoadcompresshi > TLoadcompresshi Then Do Call TH_Analysis 'EDSALIM program compression activity removed' , Forbig(Rloadcompresshi) , 'programs, CICS was approaching SOS above' End Return /* CSKP actvity keypoint */ CKSPcheck: Trace Off Parse Var Rec.I CSKP DFHAKP . . CSKP_count . CSKP_count = Bignum(CSKP_count) If DFHAKP <> 'DFHAKP' | Datatype(CSKP_count,'W') = 0 Then Do Return End If RCICSelapsed > 0 & CSKP_count > 0 Then Do Call PM_Analysis 'RECOVERY average time between keypoints is' , Format((RCICSelapsed/CSKP_count)/60,5,2) 'minutes' End If RCICSelapsed > 0 & CSKP_count = 0 Then Do Call BP_Analysis 'RECOVERY AKPFREQ=0 appears to be used, in which case' , 'emergency restart is disabled' End Return /* CSMI actvity */ CSMIcheck: Trace Off Parse Var Rec.I CSMI DFHMIRS . . CSMI_count . CSMI_count = Bignum(CSMI_count) If DFHMIRS <> 'DFHMIRS' | Datatype(CSMI_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION CSMI count is' Forbig(CSMI_count) , Forbig(Format(CSMI_count*100/Proftrans),,0)'% of all transactions' Return /* CSM1 actvity */ CSM1check: Trace Off Parse Var Rec.I CSM1 DFHMIRS . . CSM1_count . CSM1_count = Bignum(CSM1_count) If DFHMIRS <> 'DFHMIRS' | Datatype(CSM1_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION CSM1 count is' Forbig(CSM1_count) , Forbig(Format(CSM1_count*100/Proftrans),,0)'% of all transactions' Return /* CSM2 actvity */ CSM2check: Trace Off Parse Var Rec.I CSM2 DFHMIRS . . CSM2_count . CSM2_count = Bignum(CSM2_count) If DFHMIRS <> 'DFHMIRS' | Datatype(CSM2_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION CSM2 count is' Forbig(CSM2_count) , Forbig(Format(CSM2_count*100/Proftrans),,0)'% of all transactions' Return /* CSM3 actvity */ CSM3check: Trace Off Parse Var Rec.I CSM3 DFHMIRS . . CSM3_count . CSM3_count = Bignum(CSM3_count) If DFHMIRS <> 'DFHMIRS' | Datatype(CSM3_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION CSM3 count is' Forbig(CSM3_count) , Forbig(Format(CSM3_count*100/Proftrans),,0)'% of all transactions' Return /* CSM4 actvity */ CSM4check: Trace Off Parse Var Rec.I CSM4 DFHMIRS . . CSM4_count . CSM4_count = Bignum(CSM4_count) If DFHMIRS <> 'DFHMIRS' | Datatype(CSM4_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION CSM4 count is' Forbig(CSM4_count) , Forbig(Format(CSM4_count*100/Proftrans),,0)'% of all transactions' Return /* CSM5 actvity */ CSM5check: Trace Off Parse Var Rec.I CSM5 DFHMIRS . . CSM5_count . CSM5_count = Bignum(CSM5_count) If DFHMIRS <> 'DFHMIRS' | Datatype(CSM5_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION CSM5 count is' Forbig(CSM5_count) , Forbig(Format(CSM5_count*100/Proftrans),,0)'% of all transactions' Return /* MQGX actvity */ MQGXcheck: Trace Off Parse Var Rec.I MQGX MQPXGET . . MQGX_count . MQGX_count = Bignum(MQGX_count) If MQPXGET <> 'MQPXGET' | Datatype(MQGX_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION MQGX count is' Forbig(MQGX_count) , Forbig(Format(MQGX_count*100/Proftrans),,0)'% of all transactions' Return /* MQPX actvity */ MQPXcheck: Trace Off Parse Var Rec.I MQPX MQPXPUT . . MQPX_count . MQPX_count = Bignum(MQPX_count) If MQPXPUT <> 'MQPXPUT' | Datatype(MQPX_count,'W') = 0 Then Do Return End Call PM_Analysis 'TRANSACTION MQPX count is' Forbig(MQPX_count) , Forbig(Format(MQPX_count*100/Proftrans),,0)'% of all transactions' Return /* TS queue processing */ TSQPutmain: Trace Off Parse Var Rec.I ':' Num . RTSPutmain = Bignum(Num) Return TSQGetmain: Trace Off Parse Var Rec.I ':' Num . RTSQGetmain = Bignum(Num) Return TSQpeakmain: Trace Off Parse Var Rec.I ':' Num 'K' . RTSQpeakmain = Bignum(Num) If RTSQpeakmain > TTSQpeakmain Then Do Call TH_Analysis 'TS Main peak storage threshold' TTSQpeakmain'K' , 'exceeded,' Forstor(RTSQpeakmain) 'was used' End Return TSQPutaux: Trace Off Parse Var Rec.I ':' Num . RTSQPutaux = Bignum(Num) Return TSQGetaux: Trace Off Parse Var Rec.I ':' Num . RTSQGetaux = Bignum(Num) Return TSQcreated: Trace Off Parse Var Rec.I ':' Num . RTSQcreated = Bignum(Num) Return TSQextnthresh: Trace Off Parse Var Rec.I ':' Num . RTSQthreshold = Bignum(Num) Return TSQextn: Trace Off Parse Var Rec.I ':' Num . RTSQextn = Bignum(Num) If RTSQcreated > 0 Then Do TSQextnpcnt = Format((RTSQextn*100)/RTSQcreated,,0) If TSQextnpcnt > 100 Then Return If TSQextnpcnt > TTSQextn Then Do Call TH_Analysis 'TS queue extensions occurred' , Right(TSQextnpcnt,3)||'%' , 'of the time, consider increasing SIT TSMGSET value' RTSQthreshold+0 End End Return TSQCI: Trace Off Parse Var Rec.I ':' Num . RTSQCI = Bignum(Num) Return TSQCIpeak: Trace Off Parse Var Rec.I ':' Num . RTSQCIpeak = Bignum(Num) If RTSQCI > 0 Then Do If Format((RTSQCIpeak*100)/RTSQCI,,0) > TTSQCIpeak Then Do Call TH_Analysis 'TS peak CI usage is' , Format((RTSQCIpeak*100)/RTSQCI,3,0)||'% of DFHTEMP,' , 'keeping peak usage below 75%' , 'may help to reduce TS compressions' End End Return TSQgtCIsize: Trace Off Parse Var Rec.I ':' Num . RTSQgtCIsize = Bignum(Num) If RTSQPutaux > 0 Then Do TSQgt = (RTSQgtCIsize*100)/RTSQPutaux /* 19.01.12 Add a threshold for the number */ If TSQgt > TTSQCIgt , | RTSQgtCIsize > TTSQCIgtcount Then Do Call TH_Analysis 'TS writes > CI size threshold exceeded,' , 'if possible, increase DFHTEMP CI size and space allocation' End End Return TSQauxfull: Trace Off Parse Var Rec.I ':' Num . RTSQauxfull = Bignum(Num) If RTSQauxfull > ETSQauxfull Then Do Call LI_Analysis 'DFHTEMP exhausted' Forbig(RTSQauxfull) 'times,' , 'consider increasing DFHTEMP space allocation' End Return TSQcompress: Trace Off Parse Var Rec.I ':' Num . TSQcompress = Bignum(Num) /* Remove Call PM_Analysis 'DFHTEMP CI compression count' Forbig(TSQcompress) If RTSQPutaux > 0 Then Do Call PM_Analysis 'DFHTEMP CI compressions:WRITEQ TS ratio' , Format(TSQcompress/RTSQPutaux,4,5) End */ Return TSQstring: Trace Off Parse Var Rec.I ':' Num . RTSQstring = Bignum(Num) Return TSQstringpeak: Trace Off Parse Var Rec.I ':' Num . RTSQstringpeak = Bignum(Num) If RTSQstring > 0 Then Do TSQstringpcnt = Format((RTSQstringpeak*100)/RTSQstring,,0) If TSQstringpcnt > TTSQstringpeak Then Do If TSQstringpcnt >= 100 Then Do Call LI_Analysis 'TS peak string usage is' , Format((RTSQstringpeak*100)/RTSQstring,3,0)||'%,' , 'consider increasing SIT TS number of strings' , Forbig(RTSQstring) , '(max. strings 255)' End Else Do Call TH_Analysis 'TS peak string usage is' , Format((RTSQstringpeak*100)/RTSQstring,3,0)||'%,' , 'consider increasing SIT TS number of strings' , Forbig(RTSQstring) , '(max. strings 255)' End End End Return TSQstringwait: Trace Off Parse Var Rec.I ':' Num . RTSQstringwait = Bignum(Num) If RTSQstringwait > TTSQstringwait Then Do Call LI_Analysis 'TS string wait' Forbig(RTSQstringwait) 'times' End Return TSQpeakusers: Trace Off Parse Var Rec.I ':' Num . RTSQpeakusers = Bignum(Num) If RTSQpeakusers > LTSQpeakuser Then Do Call LI_Analysis 'TS peak users in string wait' Forbig(RTSQpeakusers)||, ', consider increasing the SIT TS number of strings by a value up to' , RTSQpeakusers+1 '(max. strings 255)' End Return TSQbuffers: Trace Off Parse Var Rec.I ':' Num . RTSQbuffers = Bignum(Num) Return TSQpeakbuffers: Trace Off Parse Var Rec.I ':' Num . RTSQpeakbuffers = Bignum(Num) If RTSQpeakbuffers > LTSQpeakbuffers Then Do Call LI_Analysis 'TS peak users in buffer wait' Forbig(RTSQpeakbuffers)||, ', buffer waits' Forbig(RTSQbufferwait)||, ', consider increasing the SIT TS number of buffers by a value up to' , RTSQpeakbuffers+1 End Return TSQbufferwait: Trace Off Parse Var Rec.I ':' Num . RTSQbufferwait = Bignum(Num) /* Put this in peak users message If RTSQbufferwait > LTSQbufferwait Then Do Call LI_Analysis 'TS buffer wait' Forbig(RTSQbufferwait) 'times' End */ Return TSQbufferread: Trace Off Parse Var Rec.I ':' Num . RTSQbufferread = Bignum(Num) Return TSQbufferwrite: Trace Off Parse Var Rec.I ':' Num . RTSQbufferwrite = Bignum(Num) DFHTEMP_IO = RTSQbufferread + RTSQbufferwrite If RTSQPutaux + RTSQGetaux < 1 Then Return TSratio = ((DFHTEMP_IO) * 100) / , (RTSQPutaux + RTSQGetaux) TSratio = Format(100-TSratio,3,0) Call PM_Analysis 'TS buffer hit ratio is' TSratio'%' If TSratio < TTSQbufferhit Then Do Call TH_Analysis 'TS buffer hit ratio' TSratio'%' , 'is less than the recommended' TTSQbufferhit'%,' , 'consider increasing SIT TS number of buffers' RTSQbuffers+0 End Return TSQbufferforce: Trace Off Parse Var Rec.I ':' Num . Forcedwrites = Bignum(Num) If Forcedwrites > 0 Then Do Call PM_Analysis 'TS recoverable queues exist,' , 'SIT TS=(,0,0) must NOT be used' End Else Do Call PM_Analysis 'TS recoverable queues do not exist,' , 'SIT TS=(,0,0) may be used' End /* We may want to look at reducing the overhead/use of DFHTEMP. I/O is faster with VSE or VM VDISK, but forcing MAIN may be better still. I have no way to know if VDISK is already used or not nor how to calculate TS MAIN usage from DFHTEMP usage. */ /* If DFHTEMP buffering is not optimum, recalculate as if it was (i.e. lower) */ If DFHTEMP_IO < 1 Then Do Return End DFHTEMP_IO_Revised = DFHTEMP_IO If TSratio < TTSQbufferhit Then Do /* Not optimum */ DFHTEMP_IO_Revised = Format(DFHTEMP_IO * (TSratio/TTSQbufferhit),,0) End /* If we have recoverable queues we cannot use all TS MAIN */ If Forcedwrites > 0 Then Do Use_MAIN = 'or converting some to TS MAIN' End Else Do Use_MAIN = 'or converting some or all to TS MAIN' End If DFHTEMP_IO_Revised > TTSQVDISKorMAIN Then Do Call TH_Analysis 'TS I/O activity' Forbig(DFHTEMP_IO) 'is at a level', 'where you should consider using a VDISK' Use_MAIN End Return TSQformatwrite: Trace Off Parse Var Rec.I ':' Num . RTSQformatwrite = Bignum(Num) If RTSQformatwrite > ETSQformatwrite Then Do Call LI_Analysis 'TS format writes' Forbig(RTSQformatwrite) 'times,' , 'consider increasing DFHTEMP primary allocation' End Return TSQIOerr: Trace Off Parse Var Rec.I ':' Num . RTSQIOerr = Bignum(Num) If RTSQIOerr > ETSQIOerr Then Do Call EM_Analysis 'TS I/O errors' Forbig(RTSQIOerr) 'times' End Return /* Transient Data processing */ TDRead: Trace Off Parse Var Rec.I ':' Num . RTDRead = Bignum(Num) Return TDWrite: Trace Off Parse Var Rec.I ':' Num . RTDWrite = Bignum(Num) Return TDformatWrite: Trace Off Parse Var Rec.I ':' Num . RTDformatWrite = Bignum(Num) If RTdformatwrite > ETDformatwrite Then Do Call LI_Analysis 'TD format writes' Forbig(RTDformatwrite) 'times,' , 'consider increasing DFHNTRA primary allocation' End Return TDCI: Trace Off Parse Var Rec.I ':' Num . RTDCI = Bignum(Num) Return TDCIpeak: Trace Off Parse Var Rec.I ':' Num . RTDCIpeak = Bignum(Num) If RTDCI > 0 Then Do If Format((RTDCIpeak*100)/RTDCI,,0) > TTDCIpeak Then Do Call TH_Analysis 'TD peak CI usage is' , Format((RTDCIpeak*100)/RTDCI,3,0)||'% of DFHNTRA' End End Return TDfull: Trace Off Parse Var Rec.I ':' Num . RTDfull = Bignum(Num) If RTDfull > LTDfull Then Do Call LI_Analysis 'TD DFHNTRA exhausted' Forbig(RTDfull) 'times,' , 'consider increasing DFHNTRA primary allocation' End Return TDstring: Trace Off Parse Var Rec.I ':' Num . RTDstring = Bignum(Num) Return TDstringpeak: Trace Off Parse Var Rec.I ':' Num . RTDstringpeak = Bignum(Num) If RTDstring > 0 Then Do If Format((RTDstringpeak*100)/RTDstring,3,0) > TTDstringpeak Then Do Call TH_Analysis 'TD peak string usage is' , Format((RTDstringpeak*100)/RTDstring,3,0)||'%' End End Return TDstringwait: Trace Off Parse Var Rec.I ':' Num . RTDstringwait = Bignum(Num) If RTDstringwait > LTDstringwait Then Do Call LI_Analysis 'TD string wait' Forbig(RTDstringwait) 'times' End Return TDpeakusers: Trace Off Parse Var Rec.I ':' Num . RTDpeakusers = Bignum(Num) If RTDpeakusers > LTDpeakuser Then Do Call LI_Analysis 'TD peak users in string wait' Forbig(RTDpeakusers)||, ', consider increasing the SIT TD number of strings by a value up to' , RTDpeakusers+1 '(max. strings 255)' End Return TDbuffers: Trace Off Parse Var Rec.I ':' Num . RTDbuffers = Bignum(Num) Return TDbufferpeak: Trace Off Parse Var Rec.I ':' Num . RTDbufferpeak = Bignum(Num) If RTDbuffers > 0 Then Do If Format((RTDbufferpeak*100)/RTDbuffers,3,0) > TTDbufferpeak Then Do Call TH_Analysis 'TD peak buffer usage is' , Format((RTDbufferpeak*100)/RTDbuffers,3,0)||'%' End End Return TDbufferwait: Trace Off Parse Var Rec.I ':' Num . RTDbufferwait = Bignum(Num) If RTDbufferwait > LTDbufferwait Then Do Call LI_Analysis 'TD buffer wait' Forbig(RTDbufferwait) 'times' End Return TDpeakbuffers: Trace Off Parse Var Rec.I ':' Num . RTDpeakbuffers = Bignum(Num) If RTDpeakbuffers > LTDpeakbuffers Then Do Call LI_Analysis 'TD peak users in buffer wait' Forbig(RTDpeakbuffers)||, ', consider increasing the SIT TD number of buffers by a value up to' , RTDpeakbuffers+1 End Return TDIOerr: Trace Off Parse Var Rec.I ':' Num . RTDIOerr = Bignum(Num) If RTDIOerr > ETDIOerr Then Do Call EM_Analysis 'TD I/O errors' Forbig(RTDIOerr) 'times' End Return LSRkeylen: Trace Off Parse Var Rec.I ':' Num . RLSRkeylen.LSRpool = Bignum(Num) Return LSRstring: Trace Off Parse Var Rec.I ':' Num . RLSRstring.LSRpool = Bignum(Num) Return LSRstringpeak: Trace Off Parse Var Rec.I ':' Num . RLSRstringpeak.LSRpool = Bignum(Num) If RLSRstring.LSRpool < 1 Then Return If LSRPOOLexclude.RApplid.LSRpool = 1 Then Return If Format((RLSRstringpeak.LSRpool*100)/RLSRstring.LSRpool,,0) , > TLSRstringpeak Then Do If (RLSRstringpeak.LSRpool*100)/RLSRstring.LSRpool > 99 Then Do Call LI_Analysis 'LSRPOOL' Format(LSRpool,2,0) , 'peak string usage' , Format((RLSRstringpeak.LSRpool*100)/RLSRstring.LSRpool,3,0)||, '%, consider increasing number of strings' Forbig(RLSRstring.LSRpool) , '(max. strings 255)' End Else Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) , 'peak string usage' , Format((RLSRstringpeak.LSRpool*100)/RLSRstring.LSRpool,3,0)||, '%, consider increasing number of strings' Forbig(RLSRstring.LSRpool) , '(max. strings 255)' End End /* Ignore low string usage. If Format((RLSRstringpeak.LSRpool*100)/RLSRstring.LSRpool,,0) , < TLSRstringlow Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) , 'peak string usage' , Format((RLSRstringpeak.LSRpool*100)/RLSRstring.LSRpool,3,0)||, '% is low' End */ Return LSRwait: Trace Off Parse Var Rec.I ':' Num . RLSRwait.LSRpool = Bignum(Num) Return LSRpeakwait: Trace Off Parse Var Rec.I ':' Num . RLSRpeakwait.LSRpool = Bignum(Num) /* FCP checks for available LSR strings not VSAM. The peak number is the number of waiters, but each waiter will need 2 strings if the access is by a Path and "n" is an Upgrade Set is involved. */ If RLSRwait.LSRpool > LLSRstringwait Then Do Call LI_Analysis 'LSRPOOL' Format(LSRpool,2,0) , 'peak concurrent string waits' Forbig(RLSRpeakwait.LSRpool)|| , ', total string waits' Forbig(RLSRwait.LSRpool)|| , ', consider increasing LSRPOOL strings to' , Min(RLSRstring.LSRpool + RLSRpeakwait.LSRpool + 5,255) End Return LSRbuffers: Trace Off Parse Var Rec.I ':' Num1 . ':' Num2 . RLSRdbuffers.LSRpool = Bignum(Num1) RLSRibuffers.LSRpool = Bignum(Num2) TLSRdbuffers = TLSRdbuffers + Bignum(Num1) TLSRibuffers = TLSRibuffers + Bignum(Num2) If LSRPOOLexclude.RApplid.LSRpool = 1 Then Return If RLSRibuffers.LSRpool < 1 , Then Do Call BP_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'does not have' , 'index buffers allocated, LSR performance will be degraded' /* Make sure we get the message out */ If NOBP = True Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'index buffers' , 'are not allocated, LSR performance will be degraded' End End Return LSRlookaside: Trace Off Parse Var Rec.I ':' Num1 . ':' Num2 . RLSRdlookaside.LSRpool = Bignum(Num1) RLSRilookaside.LSRpool = Bignum(Num2) Total_LSRPOOL_BufferHit = Total_LSRPOOL_BufferHit + Bignum(Num1) + Bignum(Num2) Return LSRbufferread: Trace Off Parse Var Rec.I ':' Num1 . ':' Num2 . RLSRdbufferread.LSRpool = Bignum(Num1) RLSRibufferread.LSRpool = Bignum(Num2) Total_LSRPOOL_BufferRW = Total_LSRPOOL_BufferRW + Bignum(Num1) + Bignum(Num2) Total_LSRPOOL_BufferR = Total_LSRPOOL_BufferR + Bignum(Num1) + Bignum(Num2) This_LSRPOOL_BufferRW = Bignum(Num1) + Bignum(Num2) If LSRPOOLexclude.RApplid.LSRpool = 1 Then Return /* Ignore low usage LSR pools */ LSRlookaside = RLSRdlookaside.LSRpool + RLSRilookaside.LSRpool LSRtotIO = LSRlookaside + RLSRdbufferread.LSRpool , + RLSRibufferread.LSRpool If LSRtotIO < TLSRlowusagepool Then Return /* Data */ LSRdlookaside = RLSRdlookaside.LSRpool LSRdIO = LSRdlookaside + RLSRdbufferread.LSRpool LSRratiod = (Max(LSRdlookaside,1)*100)/Max(LSRdIO,1) LSRratiod = Format(LSRratiod,3,0) If LSRratiod < TLSRdbuffer Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'data hit ratio' , Format(LSRratiod,3,0)'%' , 'is < recommended' TLSRdbuffer||'%, Read EXCPs' , Forbig(RLSRdbufferread.LSRpool) End /* Index */ LSRilookaside = RLSRilookaside.LSRpool LSRiIO = LSRilookaside + RLSRibufferread.LSRpool LSRratioi = (Max(LSRilookaside,1)*100)/Max(LSRiIO,1) LSRratioi = Format(LSRratioi,3,0) If LSRratioi < TLSRibuffer Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'index hit ratio' , Format(LSRratioi,3,0)'%' , 'is < recommended' TLSRibuffer||'%, Read EXCPs' , Forbig(RLSRibufferread.LSRpool) End Return LSRuserwrite: Trace Off Parse Var Rec.I ':' Num1 . ':' Num2 . RLSRduserwrite.LSRpool = Bignum(Num1) RLSRiuserwrite.LSRpool = Bignum(Num2) Total_LSRPOOL_BufferRW = Total_LSRPOOL_BufferRW + Bignum(Num1) + Bignum(Num2) Total_LSRPOOL_BufferW = Total_LSRPOOL_BufferW + Bignum(Num1) + Bignum(Num2) This_LSRPOOL_BufferRW = This_LSRPOOL_BufferRW + Bignum(Num1) + Bignum(Num2) LSRdread = RLSRdlookaside.LSRpool + RLSRdbufferread.LSRpool LSRdwrite = RLSRduserwrite.LSRpool+0 LSRtotdIO = LSRdread + LSRdwrite If LSRtotdIO < TLSRtotdio Then Return If LSRPOOLexclude.RApplid.LSRpool = 1 Then Return /* Ignore LSR write:read ratio LSRratiowr = (Max(LSRdwrite,1)*100)/Max(LSRdread,1) LSRratiowr = Format(LSRratiowr,,0) If LSRratiowr > TLSRratiowr Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'write:read ratio is', Right(LSRratiowr'%',8)', write I/O='Forbig(LSRdwrite)|| , ', read I/O='Forbig(LSRdread) End */ Return LSRnuserwrite: Trace Off Parse Var Rec.I ':' Num1 . ':' Num2 . RLSRdnuserwrite.LSRpool = Bignum(Num1) RLSRinuserwrite.LSRpool = Bignum(Num2) Total_LSRPOOL_BufferRW = Total_LSRPOOL_BufferRW + Bignum(Num1) + Bignum(Num2) Total_LSRPOOL_BufferW = Total_LSRPOOL_BufferW + Bignum(Num1) + Bignum(Num2) This_LSRPOOL_BufferRW = This_LSRPOOL_BufferRW + Bignum(Num1) + Bignum(Num2) /* Save total EXCPs for the LSR pool */ LSR_total_EXCPS.LSRpool = This_LSRPOOL_BufferRW If LSRPOOLexclude.RApplid.LSRpool = 1 Then Return If RLSRdnuserwrite.LSRpool > TLSRdnuserwrite Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'had' , Forbig(RLSRdnuserwrite.LSRpool) , 'non-user data buffer WRITE requests' End If RLSRinuserwrite.LSRpool > TLSRinuserwrite Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'had' , Forbig(RLSRinuserwrite.LSRpool) , 'non-user index buffer WRITE requests' End Return /* This subroutines parses the whole of the LSR bufferpool Statistics. */ LSRBufferstats: Trace Off Indatabuffers = 1 /* Check lookaside and read with the pool-level values */ Pool_lookaside = 0 Total_EXCP_savings = 0 I = I + 1 Do I = I to Rec.0 by 1 If Substr(Rec.I,1,1) = 'C0'x Then Parse Var Rec.I 2 Rec.I If Substr(Rec.I,1,1) = '1' | , Substr(Rec.I,1,1) = '-' | , Substr(Rec.I,1,1) = '0' | , Substr(Rec.I,1,1) = '+' Then Rec.I = ' '||Substr(Rec.I,2) Upper Rec.I Current_rec = Rec.I If Pos('LSR POOLS',Rec.I) > 0 Then Leave I If Pos('LOOK',Rec.I) > 0 Then Iterate If Pos('SIZE',Rec.I) > 0 Then Iterate If Pos('APPLID',Rec.I) > 0 Then Iterate If Pos('_',Rec.I) > 0 Then Iterate If Rec.I = ' ' Then Iterate If Pos('INDEX BUFFER STATISTICS',Rec.I) > 0 Then Do Indatabuffers = 0 If Total_EXCP_savings > 0 Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'data ' , 'EXCP saving at' TLSRdbuffer'%', Forbig(Total_EXCP_savings) End Total_EXCP_savings = 0 Iterate End If Pos('FILES',Rec.I) > 0 Then Do I = I - 1 Leave I End Parse Upper Var Rec.I +2 CISZ Bufs Lookaside Read UWrite Write . CISZ = Strip(CISZ) CISZ = Right(CISZ,5,'0') Bufs = Bignum(Bufs) Lookaside = Bignum(Lookaside) Read = Bignum(Read) UWrite = Bignum(Uwrite) Write = Bignum(Write) If Datatype(CISZ,'W') = 0 Then Call Execfail 'Counter parsing error 01 in LSRbufferstats' , 'Rec.'I Rec.I If Datatype(Bufs,'W') = 0 Then Call Execfail 'Counter parsing error 02 in LSRbufferstats' , 'Rec.'I Rec.I If Datatype(Lookaside,'W') = 0 Then Call Execfail 'Counter parsing error 03 in LSRbufferstats' , 'Rec.'I Rec.I If Datatype(Read,'W') = 0 Then Call Execfail 'Counter parsing error 04 in LSRbufferstats' , 'Rec.'I Rec.I If Datatype(UWrite,'W') = 0 Then Call Execfail 'Counter parsing error 05 in LSRbufferstats' , 'Rec.'I Rec.I If Datatype(Write,'W') = 0 Then Call Execfail 'Counter parsing error 06 in LSRbufferstats' , 'Rec.'I Rec.I Pool_lookaside = Pool_lookaside + Lookaside TotIO = Lookaside + Read + UWrite + Write If LSRPOOLexclude.RApplid.LSRpool = 1 Then Iterate /* Check LSR number of buffers are not excessive */ If Bufs > TLSRbufferlim Then Do Call BP_Analysis 'LSRPOOL' Format(LSRpool,2,0) , 'CISZ' Right(Strip(CISZ,'L','0'),5,' ') , 'number of buffers is high' Forbig(Bufs) End If TotIO < 1 & CISZ <> 32768 Then Do If Indatabuffers Then Do Call BP_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'data CI size' , CISZ 'has no I/O activity, consider setting zero buffers' Iterate End Else Do Call BP_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'index CI size' , CISZ 'has no I/O activity, consider setting zero buffers' Iterate End End /* Don't bother with low usage LSR data */ If TotIO < TLSRlowusageCISZ Then Iterate If Lookaside+Read > 0 Then Do /* Calculate LSR hit % */ LSRratio = Format((Lookaside*100)/(Lookaside+Read),3,0) /* Are we in Data (and Index) Buffers or in Index Buffers? */ If Indatabuffers Then Do If LSRratio < TLSRdbuffer Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'data ' , 'CI size' CISZ 'hit ratio' Format(LSRratio,3,0)'%' , 'EXCP saving at' TLSRdbuffer'%', Psaving(Lookaside,Read,TLSRdbuffer)||, ', consider increasing number of data buffers' , Format(Bufs,5,0) 'if the saving is worthwhile' Total_EXCP_savings = Total_EXCP_savings , + Psaving(Lookaside,Read,TLSRdbuffer) End End Else Do If LSRratio < TLSRibuffer Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'index' , 'CI size' CISZ 'hit ratio' Format(LSRratio,3,0)'%' , 'EXCP saving at' TLSRibuffer'%', Psaving(Lookaside,Read,TLSRibuffer)||, ', consider increasing number of index buffers' , Format(Bufs,5,0) 'if the saving is worthwhile' Total_EXCP_savings = Total_EXCP_savings , + Psaving(Lookaside,Read,TLSRibuffer) End End End End I If Indatabuffers = 0 /* We had Index buffers */ Then Do If Total_EXCP_savings > 0 Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'index' , 'EXCP saving at' TLSRibuffer'%', Forbig(Total_EXCP_savings) End End Else Do /* Catch Index and Data Buffers we did not report on as we won't have got the "Index Buffers" trigger to do it. Total_EXCP_savings = 0 either says we reported or there is nothing to report. */ If Total_EXCP_savings > 0 Then Do Call TH_Analysis 'LSRPOOL' Format(LSRpool,2,0) 'data ' , 'EXCP saving at' TLSRdbuffer'%', Forbig(Total_EXCP_savings) End End /* Sanity check as the total LSR pool lookaside can be truncated */ If Pool_lookaside <> (RLSRdlookaside.LSRpool + RLSRilookaside.LSRpool) Then Do BadLSRmsg = 'The summary data for Pool Number :' LSRpool , 'may have been truncated,' , 'Summary Lookaside =' RLSRdlookaside.LSRpool + RLSRilookaside.LSRpool , 'Sum of Buffer-level Lookaside =' Pool_lookaside Call EM_Analysis BadLSRmsg /*Say BadLSRmsg*/ End Return /* Calculate potential savings is LSR EXCPs had the lookaside threshold been achieved. Args: #lookasides #EXCPs Required_Lookaside Returns the number of EXCPs. */ Psaving: Procedure Trace Off Arg Plookaside , PEXCPs , Prequired , Pactual . Trequests = Plookaside + PEXCPs PrequiredEXCPs = Format(((100 - Prequired) * Trequests)/100,,0) PsavedEXCPs = PEXCPs - PrequiredEXCPs Return Forbig(PsavedEXCPs) /* This subroutines parses the whole of the File Statistics. */ FILEstatistics: Trace Off Do I = I to Rec.0 by 1 If Substr(Rec.I,1,1) = 'C0'x Then Parse Var Rec.I 2 Rec.I If Substr(Rec.I,1,1) = '1' | , Substr(Rec.I,1,1) = '-' | , Substr(Rec.I,1,1) = '0' | , Substr(Rec.I,1,1) = '+' Then Rec.I = ' '||Substr(Rec.I,2) Upper Rec.I Current_rec = Rec.I If Pos('TOTALS',Rec.I) > 0 Then Leave I If Pos('APPLID',Rec.I) > 0 Then Iterate If Pos('FILENAME',Rec.I) > 0 Then Iterate If Pos('ACCESS',Rec.I) > 0 Then Iterate If Pos('_',Rec.I) > 0 Then Iterate If Rec.I = ' ' Then Iterate /* We may have a print control character as the first byte */ If Substr(Rec.I,1,1) == ' ' Then Do Parse Var Rec.I Name AMethod Type LSRpool 32 . End Else Do Parse Var Rec.I . Name AMethod Type LSRpool 32 . End /* Ignore BDAM files */ If Type = 'BDAM' Then Iterate Name = Left(Name,7) AMethod = Substr(AMethod,1,1) If Datatype(Type,'W') = 1 Then Do LSRpool = Type Type = ' ' End Type = Left(Type,4) If Datatype(Lsrpool,'W') = 1 Then Do LSRpool = Right(Strip(LSRpool),2,'0') End Else Do LSRpool = Copies('0',2) End Parse Upper Var Rec.I . 31 Strmax Strwait Read Getupdate , Browse Add Update Delete Dexcps Iexcps . Strmax = Bignum(Strmax) Strwait = Bignum(Strwait) Read = Bignum(Read) Getupdate = Bignum(Getupdate) Browse = Bignum(Browse) Add = Bignum(Add) Update = Bignum(Update) Delete = Bignum(Delete) Dexcps = Bignum(Dexcps) Iexcps = Bignum(Iexcps) If Datatype(Strmax,'W') = 0 Then Call Execfail 'Counter parsing error 01 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Strwait,'W') = 0 Then Call Execfail 'Counter parsing error 02 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Read,'W') = 0 Then Call Execfail 'Counter parsing error 03 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Getupdate,'W') = 0 Then Call Execfail 'Counter parsing error 04 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Browse,'W') = 0 Then Call Execfail 'Counter parsing error 05 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Add,'W') = 0 Then Call Execfail 'Counter parsing error 06 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Update,'W') = 0 Then Call Execfail 'Counter parsing error 07 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Delete,'W') = 0 Then Call Execfail 'Counter parsing error 08 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Dexcps,'W') = 0 Then Call Execfail 'Counter parsing error 09 in Filestatistics' , 'Rec.'I Rec.I If Datatype(Iexcps,'W') = 0 Then Call Execfail 'Counter parsing error 19 in Filestatistics' , 'Rec.'I Rec.I TotLIO = Read + Getupdate + Browse + Add + Update + Delete TotPIO = Dexcps + Iexcps TotRead = Read + Getupdate + Browse TotWrite = Add + Update + Delete /* Sum total EXCPs for files */ Total_FILES_EXCPs = Total_FILES_EXCPs + TotPIO /* Report local files with zero requests but non-zero EXCPs If Amethod <> 'R' & TotPIO > 0 & Totlio = 0 Then Do Call EM_Analysis 'FILE' Left(Name,7) 'has zero requests,' , 'but the EXCP count is' Forbig(TotPIO)||',' , 'please investigate' End */ /* Ignore file with no activity now */ If TotLIO = 0 & TotPIO = 0 Then Iterate /* Avoid divide exception */ If TotLIO = 0 Then TotLIO = 1 /* Set LSRPOOL/NSR message insert and total NSR EXCPS */ If LSRpool <> 0 Then Do LSR_NSR = 'LSRPOOL' Format(LSRpool,2,0) End Else Do LSR_NSR = 'NSR ' Total_FILES_EXCPs_NSR = Total_FILES_EXCPs_NSR + TotPIO End /* Report local files with zero EXCPs deleted 14.03.2013 If Amethod <> 'R' & TotPIO = 0 Then Do Call EM_Analysis 'FILE' Left(Name,7) 'has zero EXCPs,' , 'but the request count is' Forbig(TotLIO)||',' , 'please investigate' End */ FILEname.0 = FILEname.0 + 1 X = FILEname.0 FILEname.X = Name FILEamethod.0 = FILEamethod.0 + 1 X = FILEamethod.0 FILEamethod.X = AMethod FILEtype.0 = FILEtype.0 + 1 X = FILEtype.0 FILEtype.X = Type FILELSRpool.0 = FILELSRpool.0 + 1 X = FILELSRpool.0 FILELSRpool.X = LSRpool FILEstrmax.0 = FILEstrmax.0 + 1 X = FILEstrmax.0 FILEstrmax.X = Bignum(Strmax) FILEstrwait.0 = FILEstrwait.0 + 1 X = FILEstrwait.0 FILEstrwait.X = Bignum(Strwait) FILEread.0 = FILEread.0 + 1 X = FILEread.0 FILEread.X = Bignum(Read) FILEgetupdate.0 = FILEgetupdate.0 + 1 X = FILEgetupdate.0 FILEgetupdate.X = Bignum(Getupdate) FILEbrowse.0 = FILEbrowse.0 + 1 X = FILEbrowse.0 FILEbrowse.X = Bignum(Browse) FILEadd.0 = FILEadd.0 + 1 X = FILEadd.0 FILEadd.X = Bignum(Add) FILEupdate.0 = FILEupdate.0 + 1 X = FILEupdate.0 FILEupdate.X = Bignum(Update) FILEdelete.0 = FILEdelete.0 + 1 X = FILEdelete.0 FILEdelete.X = Bignum(Delete) FILEdexcps.0 = FILEdexcps.0 + 1 X = FILEdexcps.0 FILEdexcps.X = Bignum(Dexcps) FILEiexcps.0 = FILEiexcps.0 + 1 X = FILEiexcps.0 FILEiexcps.X = Bignum(Iexcps) /*****************************************************/ /* Avoid any of the below analysis if the file is in */ /* FILE EXCLUDE */ /*****************************************************/ If Fexclude.Rapplid.Name = 1 Then Do Iterate End /*****************************************************/ /* Strmax is the peak string wait number. Strwait is the number of string waits */ If Strwait = 999 Then Plus = '+' Else Plus = ' ' If Strmax > LFILEstrmax | Strwait > LFILEstrwait Then Do Call LI_Analysis 'FILE' Left(Name,7) 'peak concurrent string waits', Forbig(Strmax)||', total string waits' Forbig(Strwait)||Plus, 'consider increasing the FILE definition STRINGS by a value up to' , Right(Min(Format(Rmxt*0.20,,0),Strmax+1),3) '(max. strings 255)' /* Extra msg. if max. string wait > MXT*20% or ULFILEstrmax whichever is smaller. */ If Strmax > Min(ULFILEstrmax,Format(Rmxt*0.20,,0)) Then Do Call LI_Analysis 'FILE' Left(Name,7) 'peak string waits', 'is high, please check the file and overall VSAM performance' End End /* Report on busy ESDS files that ony had add requests against them */ ESDSaddonly=0 If Type ='ESDS' & TotLIO = Add & TotLIO > TFILEactiveESDS Then Do ESDSaddonly=1 If LSR_NSR <> 'NSR' Then Do Call BP_Analysis 'ESDS' Name 'only has add requests reported,' , 'use STRINGS=1 on the CEDA FILE definition' , 'if that is how it is always used' End Else Do Call BP_Analysis 'ESDS' Name 'only has add requests reported,' , 'use LRSPOOL=NONE and STRINGS=1 on the CEDA FILE definition' , 'if that is how it is always used' End End /* Report on active NSR files */ If LSRpool = '00' & AMethod <> 'R' & TotLIO > TFILEactiveNSR , & ESDSaddonly=0 Then Do Call BP_Analysis 'FILE' Name 'is using NSR buffering, this is not' , 'normally recommended unless it is SHR(4) or add-only ESDS' End /* SQLGLOB */ If Name = 'SQLGLOB' Then Do Call BP_Analysis 'FILE' Name 'is best defined as a CICS Data Table' , 'if it has more than a small number of requests' End /* Report on active REMOTE files */ If AMethod = 'R' Then Do If TotLIO >= TFILEactiveREM Then Do Call TH_Analysis 'FILE' Name 'REMOTE requests' , Forbig(TotLIO) 'exceeds the threshold' Forbig(TFILEactiveREM)|| , ', function shipping is a big overhead' End End /* Get LSR file EXCP% of total LSR pool */ LSR_Text = '' /* 12.12.2013 This only works if no reset has occurred If LSR_NSR <> 'NSR' & AMethod <> 'R' Then Do LSRP = LSRPool+0 If LSR_total_EXCPS.LSRP > 0 Then Do File_pool_pcnt = (TotPIO*100/LSR_total_EXCPS.LSRP) LSR_Text = Format(File_pool_pcnt,5,2)||'% of the LSR pool EXCPs' End End */ /* The following are only for heavily used files */ If TotPIO > TFILEPIO & Type <> 'ESDS' & AMethod <> 'R' Then Do /* Handle unusual EXCPs per Request */ If TotPIO/TotLIO > 99.99 Then Do EXCPsperRequest = 99.99 End Else Do EXCPsperRequest = Format(TotPIO/TotLIO,2,2) End Select When Iexcps = 0 Then Do IDRatio = ' N/A' End When Iexcps/Dexcps > 99.99 Then Do IDRatio = 99.99 End Otherwise Do IDRatio = Format(Iexcps/Dexcps,2,2) End End Select When TotWrite = 0 Then Do RWRatio = 9999999.99 End When TotRead/TotWrite > 9999999.99 Then Do RWRatio = 9999999.99 End Otherwise Do RWRatio = Format(TotRead/TotWrite,7,2) End End Call PM_Analysis 'EXCPs' Forbig(TotPIO), LSR_NSR Type Name , 'Index/Data EXCP ratio' IDRatio , 'EXCPs/Request' EXCPsperRequest , 'File requests' Forbig(TotLIO), 'Read/Write ratio' RWRatio , 'Read' Format(((Read+Getupdate)*100)/Totlio,4,2)||'%' , 'Browse' Format((Browse*100)/Totlio,4,2)||'%' , 'Update' Format((Update*100)/Totlio,4,2)||'%' , 'Add' Format((Add*100)/Totlio,4,2)||'%', 'Delete' Format((Delete*100)/Totlio,4,2)||'%' , LSR_text Read = Bignum(Read) Getupdate = Bignum(Getupdate) Browse = Bignum(Browse) Add = Bignum(Add) Update = Bignum(Update) Delete = Bignum(Delete) Realname = Left(Name,7) /* No Data Table check 14.03.2013 If ((Read+Browse)*100)/TotLIO > TFILEDTratio , & Type = 'KSDS' & DTexclude.Rapplid.Realname = 0 Then Do Call PM_Analysis LSR_NSR 'file' Name , 'may be a Data Table candidate if it is a KSDS base cluster' , 'and it meets other Data Table selection criteria' End */ /* Omit EXCP:requests check PIOratio = Format((TotPIO*100)/TotLIO,,0) If PIOratio > 999999 Then Do PIOratio = 999999 End If (PIOratio > TFILEPIOratio) Then Do Call PM_Analysis LSR_NSR 'file' Name , 'high EXCP:requests ratio' Right(PIOratio||'%,',8), 'data EXCPs' Forbig(Dexcps)|| , ', index EXCPs' Forbig(Iexcps)|| , ', the number of buffers may need to be increased' End */ If Iexcps > Dexcps Then Do Call EM_Analysis LSR_NSR 'file' Name 'index EXCPs' , Forbig(Iexcps) 'is > data EXCPs' Forbig(Dexcps)||',' , 'this is not normal except for SHR(4)' End Readreq = Read + Getupdate + Browse Writereq = Add + Update + Delete Totalreq = Readreq + Writereq /* If Totalreq > 0 Then Do Writepcnt = Format((Writereq*100)/Totalreq,,0) If Writepcnt > PFILEWritepcnt Then Do Call PM_Analysis LSR_NSR 'file' Name , 'high write request ratio' Right(Writepcnt||'%,',8), 'writes' Forbig(Writereq)|| , ', total' Forbig(Totalreq) End End */ End /* If TotLIO > PIOthresh */ End I /* End of Files section processing */ If Total_FILES_EXCPs > 0 & Proftrans > 0 Then Do Call PM_Analysis 'FILES EXCPs per transaction is' , Format(Total_FILES_EXCPs/Proftrans,5,2) End If I > Rec.0 Then Call Execfail 'Filestatistics did not complete correctly' Return /* This subroutines parses the whole of the Data Tables Requests. */ DatatableIO: Trace Off Do I = I to Rec.0 by 1 If Substr(Rec.I,1,1) = 'C0'x Then Parse Var Rec.I 2 Rec.I If Substr(Rec.I,1,1) = '1' | , Substr(Rec.I,1,1) = '-' | , Substr(Rec.I,1,1) = '0' | , Substr(Rec.I,1,1) = '+' Then Rec.I = ' '||Substr(Rec.I,2) Upper Rec.I Current_rec = Rec.I If Pos('DATA TABLES - STORAGE',Rec.I) > 0 Then Leave I If Pos('APPLID',Rec.I) > 0 Then Iterate If Pos('FILENAME',Rec.I) > 0 Then Iterate If Pos('DATA',Rec.I) > 0 Then Iterate If Pos('_',Rec.I) > 0 Then Iterate If Rec.I = ' ' Then Iterate /* We may have a print control character as the first byte */ If Substr(Rec.I,1,1) == ' ' Then Do Parse Var Rec.I Name Type 25 Maxnumrec Read Nrf Addread , Addapi Addrej Rewrite Delete Retry . End Else Do Parse Var Rec.I . Name Type 25 Maxnumrec Read Nrf Addread , Addapi Addrej Rewrite Delete Retry . End Name = Left(Name,7) Type = Left(Strip(Type),4) Maxnumrec = Bignum(Maxnumrec) Read = Bignum(Read) Nrf = Bignum(Nrf) Addread = Bignum(Addread) Addapi = Bignum(Addapi) Addrej = Bignum(Addrej) Rewrite = Bignum(Rewrite) Delete = Bignum(Delete) Retry = Bignum(Retry) If Datatype(Maxnumrec,'W') = 0 Then Call Execfail 'Counter parsing error 01 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Read,'W') = 0 Then Call Execfail 'Counter parsing error 02 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Nrf,'W') = 0 Then Call Execfail 'Counter parsing error 03 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Addread,'W') = 0 Then Call Execfail 'Counter parsing error 04 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Addapi,'W') = 0 Then Call Execfail 'Counter parsing error 05 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Addrej,'W') = 0 Then Call Execfail 'Counter parsing error 06 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Rewrite,'W') = 0 Then Call Execfail 'Counter parsing error 07 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Delete,'W') = 0 Then Call Execfail 'Counter parsing error 08 in DatatableIO' , 'Rec.'I Rec.I If Datatype(Retry,'W') = 0 Then Call Execfail 'Counter parsing error 09 in DatatableIO' , 'Rec.'I Rec.I RDTname.0 = RDTname.0 + 1 X = RDTname.0 RDTname.X = Name /* Type is CICS, USER or REM */ RDTtype.0 = RDTtype.0 + 1 X = RDTtype.0 RDTtype.X = Type RDTmaxnumrec.0 = RDTmaxnumrec.0 + 1 X = RDTmaxnumrec.0 RDTmaxnumrec.X = Maxnumrec RDTread.0 = RDTread.0 + 1 X = RDTread.0 RDTread.X = Read RDTnrf.0 = RDTnrf.0 + 1 X = RDTnrf.0 RDTnrf.X = Nrf RDTaddread.0 = RDTaddread.0 + 1 X = RDTaddread.0 RDTaddread.X = Addread RDTaddapi.0 = RDTaddapi.0 + 1 X = RDTaddapi.0 RDTaddapi.X = Addapi RDTaddrej.0 = RDTaddrej.0 + 1 X = RDTaddrej.0 RDTaddrej.X = Addrej RDTrewrite.0 = RDTrewrite.0 + 1 X = RDTrewrite.0 RDTrewrite.X = Rewrite RDTdelete.0 = RDTdelete.0 + 1 X = RDTdelete.0 RDTdelete.X = Delete RDTretry.0 = RDTretry.0 + 1 X = RDTretry.0 RDTretry.X = Retry /* Set limits based on remote/local */ If Type <> 'REM' Then Do /* Local CICS/USER */ TDTrequests = TLDTrequests TDThitratio = TLDThitratio End Else Do /* Remote */ TDTrequests = TRDTrequests TDThitratio = TRDThitratio End /* Check for reasonable usage as a Data table */ If Read < TDTrequests Then Do Call TH_Analysis 'DATATABLE' Name 'may be a bad choice as a' , 'Data Table, the number of read hits is' Forbig(Read) , 'and the threshold is' Forbig(TDTrequests) End /* Check hit ratio */ If Read > 0 Then Do Totalreq = Read + Nrf + Addapi + Rewrite + Delete + Addrej DThitratio = Format((Read*100)/Totalreq,,0) If DThitratio < TDThitratio Then Do Call TH_Analysis 'DATATABLE' Name 'hit ratio' , Format(DThitratio,3,0)'%' , 'is low, hits' Forbig(Read)||', requests' Forbig(Totalreq) End End /* Check records loaded/maxnumrec ratio for a datatable that has loading data. */ If Addread > 0 & Maxnumrec > 0 Then Do DTUseratio = Format(((Addread+Addapi)*100)/(Maxnumrec),,0) If DTUseratio < TDTuseratiomin Then Do Call TH_Analysis 'DATATABLE' Name 'occupancy is' , Format(DTUseratio,3,0)'%, consider decreasing the' , 'CEDA FILE definition Maxnumrecs' End If DTUseratio > TDTuseratiomax Then Do Call TH_Analysis 'DATATABLE' Name 'occupancy is' , Format(DTUseratio,3,0)'%, consider increasing the' , 'CEDA FILE definition Maxnumrecs' End End /* Check for adds rejected */ If Addrej > TDTAddrej Then Do Call TH_Analysis 'DATATABLE' Name 'had' Forbig(Addrej) , 'adds rejected, the file definition MAXNUMRECS may have' , 'been exceeded' End End I If I > Rec.0 Then Call Execfail 'DatatableIO did not complete correctly' Return /* Profile LSR pools. */ LSRPROF: Trace Off TotLSRrequests = 0 TotLSREXCPs = 0 Do I = 1 to 15 TotLSRrequests = TotLSRrequests + RLSRdlookaside.I + RLSRdbufferread.I TotLSRrequests = TotLSRrequests + RLSRilookaside.I + RLSRibufferread.I TotLSREXCPs = TotLSREXCPs + RLSRdbufferread.I TotLSREXCPs = TotLSREXCPs + RLSRibufferread.I End I If TotLSRrequests <= 0 | TotLSREXCPs <= 0 Then Return Do I = 1 to 15 LSRpcnt1 = ((RLSRdlookaside.I + RLSRdbufferread.I , + RLSRilookaside.I + RLSRibufferread.I) * 100) / TotLSRrequests If LSRpcnt1 <= 0 Then Iterate LSRpcnt2 = ((RLSRdbufferread.I + RLSRibufferread.I) * 100) / TotLSREXCPs If LSRpcnt2 <= 0 Then Iterate Call PM_Analysis 'LSRPOOL '||Format(I,2,0) , 'is responsible for' Format(LSRpcnt2,5,2)||'% of all LSR Read EXCPs', 'and' Format(LSRpcnt1,5,2)||'% of all LSR activity' End I Return /* Profile EXCP split */ EXCPSplit: Trace Off Total_LSR_NSR_EXCPs = TotLSREXCPs + Total_FILES_EXCPs_NSR If Total_LSR_NSR_EXCPs < 1 Then Return Call PM_Analysis 'EXCPS for LSR' Forbig(TotLSREXCPs) 'is' , Format((TotLSREXCPs*100)/Total_LSR_NSR_EXCPs,3,2)|| , '% of total EXCPS reported' Call PM_Analysis 'EXCPS for NSR' Forbig(Total_FILES_EXCPs_NSR) 'is' , Format((Total_FILES_EXCPs_NSR*100)/Total_LSR_NSR_EXCPs,3,2)|| , '% of total EXCPS reported' Return /* Big numbers. Scale can be tweaked as required. */ Bignum: Trace Off Arg Val . /* Get rid of commas */ Nval = '' Do Sub = 1 to Length(Val) If Substr(Val,Sub,1) = ',' Then Iterate Nval=Nval||Substr(Val,Sub,1) End Sub /* Handle edited numbers like >999 */ Nval = Strip(Nval,'L','>') Select When Datatype(Nval,'N') = 0 Then Do Say 'A bad numeric value of' Val 'has been passed to Bignum,' , 'it will be changed to +1, some results may be incorrect' Say Current_rec Nval = 1 End When Nval < 0 Then Do Say 'A negative value of' Val 'has been passed to Bignum,' , 'it will be changed to +1, some results may be incorrect' Say Current_rec Nval = 1 End Otherwise Nop End Return Right(Nval,10,'0') /* Mid numbers. Scale can be tweaked as required. */ Midnum: Procedure Trace Off Arg Val . /* Get rid of commas */ Nval = '' Do I = 1 to Length(Val) If Substr(Val,I,1) = ',' Then Iterate Nval=Nval||Substr(Val,I,1) End I If Nval < 0 Then Do Say 'A negative value of' Val 'has been passed to Midnum,' , 'it will be changed to +1, some results may be incorrect' Nval = 1 End Return Right(Nval,7,'0') /* Tiny numbers. Scale can be tweaked as required. */ Tinynum: Procedure Trace Off Arg Val . /* Get rid of commas */ Nval = '' Do I = 1 to Length(Val) If Substr(Val,I,1) = ',' Then Iterate Nval=Nval||Substr(Val,I,1) End I If Nval < 0 Then Do Say 'A negative value of' Val 'has been passed to Tinynum,' , 'it will be changed to +1, some results may be incorrect' Nval = 1 End Return Right(Nval,3,'0') /* Big seconds. Scale can be tweaked as required. */ Bigsecs: Procedure Trace Off Arg Time . Parse Var Time hh ':' mm ':' ss . Secs = (hh * 3600) + (mm * 60) + ss Secs = Format(Secs,7,3) Return Right(Strip(Secs),11,'0') /* Format a big number */ Forbig: Procedure Trace Off Arg Bnum . Bnum = Format(Bnum,10,0) Return Bnum /* Format a number of seconds */ Forsecs: Procedure Trace Off Arg Secs . Secs = Format(Secs,7,3) Return Secs /* Format a storage value of K */ Forstor: Procedure Trace Off Arg Stor . If Stor < 0 Then Stor = 0 Stor = Format(Stor,7,0)||'K' Return Stor /* Milliseconds. Scale can be tweaked as required. */ Msecs: Procedure Trace Off Arg Time . Time = Strip(Time,'T','S') Time = Strip(Time,'T','M') Return Bignum(Time) /* Cache analysis entry. */ Analysis: Procedure Expose Analysis. RApplid Rdate Rtime String Trace Off Parse Arg Type ',' String If String = '' Then Do Say 'Invalid call to Analysis, Type ='Type',String is null' Exit 999 End Analysis.0 = Analysis.0 + 1 E = Analysis.0 Analysis.E = Left(RApplid,8) Rdate Left(Type,13) String Return /* Front-end Analysis for message type */ BP_Analysis: Trace Off If NOBP Then Return Parse Arg String Call Analysis 'Best Practice ,'String Return IN_Analysis: Trace Off If NOINF Then Return Parse Arg String Call Analysis 'Information ,'String Return LI_Analysis: Trace Off If NOLIM Then Return Parse Arg String Call Analysis 'Limit ,'String Return PM_Analysis: Trace Off If NOPROF Then Return Parse Arg String Call Analysis 'Profile ,'String Return TH_Analysis: Trace Off If NOTHR Then Return Parse Arg String Call Analysis 'Threshold ,'String Return EM_Analysis: Trace Off If NOEXC Then Return Parse Arg String Call Analysis 'Exception ,'String Return /* Write analysis entries. */ LogAnalysis: Trace Off If VM_env = True Then Do 'PIPE STATE ANALYSIS TXT A' If RC = 0 Then 'COPYFILE ANALYSIS TXT A = BACKUP = (REP OLDD PACK' /* Create Rapplid Rdate report, append to ANALYSIS TXT */ If NOINDV = False Then Do 'PIPE STEM ANALYSIS. | SORT 1-8 19-* | > ' Rapplid Rdate 'A' End 'PIPE STEM ANALYSIS. | >> ANALYSIS TXT A' /* De-duplicate ANALYSIS TXT */ 'PIPE FILEFAST ANALYSIS TXT A | SORT | UNIQUE' , '| SORT 1-8 19-*' , '| > ANALYSIS TXT A', '| SORT 1-8 19-55 10-17', '| > ANALYSIS TXTDATE A' If RC > 0 Then Do Say 'RC='RC 'in LogAnalysis creating de-duplicated ANALYSIS ACCUM' Exit 16 End End Else Do Oldrec. = '' Oldrec.0 = 0 'EXECIO * DISKR REPIN (FINIS STEM Oldrec. BLKSIZE' Dasd_BLKSIZE , 'RECFORM VARBLK' Do J = 1 to Analysis.0 Oldrec.0 = Oldrec.0 + 1 X = Oldrec.0 Oldrec.X = Analysis.J End Call De_dup_data 1 150 FC = Sortstem('Newrec.') If FC <> 0 Then Do Say 'RC='FC 'from Sortstem in LogAnalysis' Exit 999 End 'EXECIO' Newrec.0 'DISKW REPOUT (FINIS STEM Newrec. BLKSIZE' , Dasd_BLKSIZE 'RECFORM VARBLK' If RC <> 0 Then Do Say 'RC='RC 'in LogAnalysis writing data to REPOUT' Exit 16 End End Return /* Oh dear, it has all gone pear-shaped */ Execfail: Trace Off Arg Msg Say Msg Say 'Processing will now end' Exit 999 /* It is bad code I am afraid! */ Runtime_error: Trace Off Say 'Run-time' Condition('C') 'error raised' Say 'REXX error' rc 'in line' sigl ':' ERRORTEXT(rc) Say Sourceline(SIGL) Say 'Processing will now end' Exit 999