*> ============================================================ *> 23-select-condition : Customer Search (TELECOM BILLING) *> Input : CUSTOMER-FILE (INDEXED) *> Output: REPORT-FILE, TXN-LOG, AUDIT-FILE *> Coverage: DB-N001, DB-N002, DB-N006, DB-R001 *> ============================================================ IDENTIFICATION DIVISION. PROGRAM-ID. Main23SelectCond. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT CUSTOMER-FILE ASSIGN TO "customer.dat" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS CUST-KEY FILE STATUS IS CUST-STATUS. SELECT REPORT-FILE ASSIGN TO "select-report.txt" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS REPORT-STATUS. SELECT TXN-LOG ASSIGN TO "txn-log.txt" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS TXN-STATUS. SELECT AUDIT-FILE ASSIGN TO "audit-file.txt" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS AUDIT-STATUS. DATA DIVISION. FILE SECTION. FD CUSTOMER-FILE. 01 CUST-RECORD. 05 CUST-KEY PIC X(10). 05 CUST-NAME PIC X(20). 05 CUST-BALANCE PIC 9(10). FD REPORT-FILE. 01 REPORT-LINE PIC X(80). FD TXN-LOG. 01 TXN-RECORD PIC X(120). FD AUDIT-FILE. 01 AUDIT-RECORD PIC X(120). WORKING-STORAGE SECTION. 01 WS-TELECOM-REC. COPY "telecom/TEL-BILLING.cpy". *> ---------- FILE STATUS flags ---------- 01 CUST-STATUS PIC XX. 88 CUST-OK VALUE "00". 88 CUST-EOF VALUE "10". 88 CUST-NOTFOUND VALUE "23". 01 REPORT-STATUS PIC XX. 88 REPORT-OK VALUE "00". 01 TXN-STATUS PIC XX. 88 TXN-OK VALUE "00". 01 AUDIT-STATUS PIC XX. 88 AUDIT-OK VALUE "00". *> ---------- Timestamp ---------- 01 WS-DATE-SYS PIC 9(8). 01 WS-TIME-SYS PIC 9(8). 01 WS-TIMESTAMP-OUT PIC X(19). 01 WS-TS-DATE-FMT. 05 WS-TS-YEAR PIC X(4). 05 FILLER PIC X(1) VALUE "/". 05 WS-TS-MONTH PIC X(2). 05 FILLER PIC X(1) VALUE "/". 05 WS-TS-DAY PIC X(2). 01 WS-TS-TIME-FMT. 05 WS-TS-HOUR PIC X(2). 05 FILLER PIC X(1) VALUE ":". 05 WS-TS-MIN PIC X(2). 05 FILLER PIC X(1) VALUE ":". 05 WS-TS-SEC PIC X(2). *> ---------- Error message ---------- 01 WS-ERROR-MSG PIC X(60). *> ---------- Existing query fields ---------- 01 WS-CUST-COUNT PIC 9(02) VALUE 0. 01 WS-TEST-CASE PIC 9(02) VALUE 0. 01 WS-TOTAL-BALANCE PIC 9(10) VALUE 0. 01 WS-START-KEY PIC X(10). 01 WS-END-KEY PIC X(10). 01 WS-RANGE-LOW PIC X(10). 01 WS-RANGE-HIGH PIC X(10). 01 WS-HEADER1. 05 FILLER PIC X(20) VALUE "KEY NAME". 05 FILLER PIC X(20) VALUE " BALANCE". 01 WS-DETAIL-LINE. 05 DL-KEY PIC X(10). 05 FILLER PIC X(02) VALUE SPACES. 05 DL-NAME PIC X(20). 05 FILLER PIC X(02) VALUE SPACES. 05 DL-BALANCE PIC Z(9)9. *> ---------- Test data ---------- 01 CUST-DATA-AREA. 05 CUST-DATA OCCURS 6 TIMES. 10 CD-KEY PIC X(10). 10 CD-NAME PIC X(20). 10 CD-BALANCE PIC 9(10). 01 CUST-DATA-VALUES. 05 PIC X(40) VALUE "CUST000001ZHANG-SAN 0000001000". 05 PIC X(40) VALUE "CUST000002LI-SI 0000002000". 05 PIC X(40) VALUE "CUST000003WANG-WU 0000003000". 05 PIC X(40) VALUE "CUST000004ZHAO-QIAN 0000004000". 05 PIC X(40) VALUE "CUST000005SUN-LI 0000005000". 05 PIC X(40) VALUE "CUST000010ZHOU-WU 0000010000". 01 CUST-DATA-REDEF REDEFINES CUST-DATA-VALUES. 05 CUST-DATA-ENTRY OCCURS 6 TIMES. 10 CDE-KEY PIC X(10). 10 CDE-NAME PIC X(20). 10 CDE-BALANCE PIC 9(10). 01 IDX PIC 9(02). *> ===== NEW FIELDS ===== *> Operation type statistics 01 WS-OP-BY-KEY-COUNT PIC 9(02) VALUE 0. 01 WS-OP-RANGE-COUNT PIC 9(02) VALUE 0. 01 WS-OP-GREATER-COUNT PIC 9(02) VALUE 0. 01 WS-FOUND-BY-KEY PIC 9(02) VALUE 0. 01 WS-FOUND-RANGE PIC 9(02) VALUE 0. 01 WS-FOUND-GREATER PIC 9(02) VALUE 0. *> Search performance metrics 01 WS-PERF-READS PIC 9(02) VALUE 0. 01 WS-PERF-START-READS PIC 9(02) VALUE 0. 01 WS-PERF-RANGE-READS PIC 9(02) VALUE 0. 01 WS-PERF-GREATER-READS PIC 9(02) VALUE 0. *> Hash total for data integrity 01 WS-HASH-TOTAL PIC 9(12) VALUE 0. *> Batch control totals 01 WS-BC-TOTAL-REQUESTS PIC 9(02) VALUE 0. 01 WS-BC-TOTAL-FOUND PIC 9(02) VALUE 0. 01 WS-BC-TOTAL-NOTFOUND PIC 9(02) VALUE 0. *> Key validation flag 01 WS-KEY-VALID-FLAG PIC X(01). 88 WS-KEY-VALID-YES VALUE "Y". 88 WS-KEY-VALID-NO VALUE "N". *> Transaction log work area 01 WS-TXN-BUFFER PIC X(120). 01 WS-TXN-TYPE PIC X(15). 01 WS-TXN-DETAIL PIC X(88). PROCEDURE DIVISION. MAIN-PROCEDURE. PERFORM 1000-INIT THRU 1000-EXIT PERFORM 2000-OPEN-FILES THRU 2000-EXIT PERFORM 3000-READ-INPUT THRU 3000-EXIT PERFORM 4000-REPORT THRU 4000-EXIT PERFORM 5000-AUDIT THRU 5000-EXIT PERFORM 9000-EXIT-PGM THRU 9000-EXIT STOP RUN. *> ============================================================ *> 1000-INIT : Create INDEXED file, populate with test data *> ============================================================ 1000-INIT SECTION. 1000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 1000-INIT: Starting". OPEN OUTPUT CUSTOMER-FILE. IF NOT CUST-OK MOVE "1000: OPEN OUTPUT CUST FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. CLOSE CUSTOMER-FILE. IF NOT CUST-OK MOVE "1000: CLOSE CUST (post-OUTPUT) FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. OPEN I-O CUSTOMER-FILE. IF NOT CUST-OK MOVE "1000: OPEN I-O CUST FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > 6 MOVE CDE-KEY(IDX) TO CUST-KEY MOVE CDE-NAME(IDX) TO CUST-NAME MOVE CDE-BALANCE(IDX) TO CUST-BALANCE WRITE CUST-RECORD INVALID KEY DISPLAY "[" WS-TIMESTAMP-OUT "]" " INIT INSERT FAILED: " CUST-STATUS END-WRITE IF NOT CUST-OK DISPLAY "[" WS-TIMESTAMP-OUT "] INIT WRITE FAILED" " KEY=" CUST-KEY " STATUS=" CUST-STATUS END-IF END-PERFORM. CLOSE CUSTOMER-FILE. IF NOT CUST-OK MOVE "1000: CLOSE CUST (post-WRITE) FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. OPEN I-O CUSTOMER-FILE. IF NOT CUST-OK MOVE "1000: OPEN I-O (reopen) FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 1000-INIT: Complete". GO TO 1000-EXIT. 1000-EXIT. EXIT. *> ============================================================ *> 2000-OPEN-FILES : Open output files, write audit header *> ============================================================ 2000-OPEN-FILES SECTION. 2000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 2000-OPEN-FILES:" " Opening output files". OPEN OUTPUT REPORT-FILE. IF NOT REPORT-OK MOVE "2000: OPEN REPORT FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. OPEN OUTPUT TXN-LOG. IF NOT TXN-OK MOVE "2000: OPEN TXN-LOG FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. OPEN OUTPUT AUDIT-FILE. IF NOT AUDIT-OK MOVE "2000: OPEN AUDIT FAILED" TO WS-ERROR-MSG PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. PERFORM GET-TIMESTAMP. WRITE AUDIT-RECORD FROM SPACES. STRING "*** AUDIT START *** " WS-TIMESTAMP-OUT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. IF NOT AUDIT-OK DISPLAY "[" WS-TIMESTAMP-OUT "] AUDIT HEADER WRITE" " FAILED STATUS=" AUDIT-STATUS END-IF. DISPLAY "[" WS-TIMESTAMP-OUT "] 2000: All files opened". GO TO 2000-EXIT. 2000-EXIT. EXIT. *> ============================================================ *> 3000-READ-INPUT : Execute 4 test cases (by-key, range, *> zero-results, greater-than). Each includes key validation, *> search execution, statistics update, and TXN log entry. *> ============================================================ 3000-READ-INPUT SECTION. 3000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 3000-READ-INPUT:" " Starting test cases". *> Report header MOVE WS-HEADER1 TO REPORT-LINE. WRITE REPORT-LINE. IF NOT REPORT-OK DISPLAY "[" WS-TIMESTAMP-OUT "] REPORT HEADER WRITE" " FAILED STATUS=" REPORT-STATUS END-IF. *> === TEST 1 : WHERE key = 'CUST000003' === ADD 1 TO WS-TEST-CASE. ADD 1 TO WS-BC-TOTAL-REQUESTS. MOVE 0 TO WS-PERF-READS. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] === Test " WS-TEST-CASE ": WHERE key = 'CUST000003' ===". MOVE "CUST000003" TO WS-START-KEY. MOVE WS-START-KEY TO CUST-KEY. PERFORM 3100-VALIDATE-KEY THRU 3100-EXIT. PERFORM 3200-SELECT-BY-KEY. ADD WS-CUST-COUNT TO WS-BC-TOTAL-FOUND. ADD 1 TO WS-OP-BY-KEY-COUNT. ADD WS-PERF-READS TO WS-PERF-START-READS. MOVE "BY-KEY" TO WS-TXN-TYPE. STRING "KEY=" WS-START-KEY " FOUND=" WS-CUST-COUNT INTO WS-TXN-DETAIL END-STRING. PERFORM 5000-TXN-LOG. *> === TEST 2 : key >= 'CUST000002' AND <= 'CUST000005' === ADD 1 TO WS-TEST-CASE. ADD 1 TO WS-BC-TOTAL-REQUESTS. MOVE 0 TO WS-PERF-READS. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] === Test " WS-TEST-CASE ": WHERE key >= 'CUST000002'" " AND key <= 'CUST000005' ===". MOVE "CUST000002" TO WS-RANGE-LOW. MOVE "CUST000005" TO WS-RANGE-HIGH. MOVE WS-RANGE-LOW TO CUST-KEY. PERFORM 3100-VALIDATE-KEY THRU 3100-EXIT. MOVE WS-RANGE-HIGH TO CUST-KEY. PERFORM 3100-VALIDATE-KEY THRU 3100-EXIT. PERFORM 3200-SELECT-RANGE. ADD WS-CUST-COUNT TO WS-BC-TOTAL-FOUND. ADD 1 TO WS-OP-RANGE-COUNT. ADD WS-PERF-READS TO WS-PERF-RANGE-READS. MOVE "RANGE" TO WS-TXN-TYPE. STRING "LOW=" WS-RANGE-LOW " HIGH=" WS-RANGE-HIGH " FOUND=" WS-CUST-COUNT INTO WS-TXN-DETAIL END-STRING. PERFORM 5000-TXN-LOG. *> === TEST 3 : WHERE none match (key = 'ZZZZZZZZZZ') === ADD 1 TO WS-TEST-CASE. ADD 1 TO WS-BC-TOTAL-REQUESTS. MOVE 0 TO WS-PERF-READS. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] === Test " WS-TEST-CASE ": WHERE none match ===". MOVE "ZZZZZZZZZZ" TO WS-START-KEY. MOVE WS-START-KEY TO CUST-KEY. PERFORM 3100-VALIDATE-KEY THRU 3100-EXIT. PERFORM 3200-SELECT-BY-KEY. ADD WS-CUST-COUNT TO WS-BC-TOTAL-FOUND. IF WS-CUST-COUNT = 0 ADD 1 TO WS-BC-TOTAL-NOTFOUND END-IF. ADD WS-PERF-READS TO WS-PERF-START-READS. MOVE "BY-KEY" TO WS-TXN-TYPE. STRING "KEY=" WS-START-KEY " FOUND=" WS-CUST-COUNT INTO WS-TXN-DETAIL END-STRING. PERFORM 5000-TXN-LOG. *> === TEST 4 : WHERE key > 'CUST000003' === ADD 1 TO WS-TEST-CASE. ADD 1 TO WS-BC-TOTAL-REQUESTS. MOVE 0 TO WS-PERF-READS. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] === Test " WS-TEST-CASE ": WHERE key > 'CUST000003' ===". MOVE "CUST000003" TO WS-START-KEY. MOVE WS-START-KEY TO CUST-KEY. PERFORM 3100-VALIDATE-KEY THRU 3100-EXIT. PERFORM 3200-SELECT-GREATER-THAN. ADD WS-CUST-COUNT TO WS-BC-TOTAL-FOUND. ADD 1 TO WS-OP-GREATER-COUNT. ADD WS-PERF-READS TO WS-PERF-GREATER-READS. MOVE "GREATER-THAN" TO WS-TXN-TYPE. STRING "KEY>" WS-START-KEY " FOUND=" WS-CUST-COUNT INTO WS-TXN-DETAIL END-STRING. PERFORM 5000-TXN-LOG. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 3000: All test cases done". GO TO 3000-EXIT. 3000-EXIT. EXIT. *> ============================================================ *> 3100-VALIDATE-KEY : Validate key format "CUST" + 6 digits. *> Sets WS-KEY-VALID-FLAG to "Y"/"N". *> ============================================================ 3100-VALIDATE-KEY SECTION. 3100-START. MOVE "Y" TO WS-KEY-VALID-FLAG. IF CUST-KEY(1:4) NOT = "CUST" MOVE "N" TO WS-KEY-VALID-FLAG DISPLAY "[" WS-TIMESTAMP-OUT "] VALIDATE: key [" CUST-KEY "] prefix not 'CUST'" END-IF. *> Check that positions 5-10 are all numeric digits PERFORM VARYING IDX FROM 5 BY 1 UNTIL IDX > 10 IF CUST-KEY(IDX:1) < "0" OR CUST-KEY(IDX:1) > "9" MOVE "N" TO WS-KEY-VALID-FLAG END-IF END-PERFORM. IF WS-KEY-VALID-NO DISPLAY "[" WS-TIMESTAMP-OUT "] VALIDATE: key [" CUST-KEY "] INVALID FORMAT" END-IF. GO TO 3100-EXIT. 3100-EXIT. EXIT. *> ============================================================ *> 3200-PROCESS-RECORD : Populate detail line, accumulate hash *> total, display result, and write to report. *> ============================================================ 3200-PROCESS-RECORD SECTION. 3200-START. MOVE CUST-KEY TO DL-KEY. MOVE CUST-NAME TO DL-NAME. MOVE CUST-BALANCE TO DL-BALANCE. ADD CUST-BALANCE TO WS-HASH-TOTAL. DISPLAY " " WS-DETAIL-LINE. PERFORM 3300-WRITE-OUTPUT THRU 3300-EXIT. GO TO 3200-EXIT. 3200-EXIT. EXIT. *> ---- Single-record read by primary key ---- 3200-SELECT-BY-KEY. MOVE 0 TO WS-CUST-COUNT. MOVE WS-START-KEY TO CUST-KEY. READ CUSTOMER-FILE KEY IS CUST-KEY INVALID KEY PERFORM GET-TIMESTAMP DISPLAY "[" WS-TIMESTAMP-OUT "] KEY NOT FOUND: " WS-START-KEY DISPLAY "[" WS-TIMESTAMP-OUT "] ROW EXISTENCE" " CHECK: no record for key " WS-START-KEY " STATUS=" CUST-STATUS MOVE " KEY NOT FOUND" TO REPORT-LINE WRITE REPORT-LINE IF NOT REPORT-OK DISPLAY "[" WS-TIMESTAMP-OUT "] REPORT WRITE" " FAILED STATUS=" REPORT-STATUS END-IF NOT INVALID KEY ADD 1 TO WS-CUST-COUNT PERFORM 3200-PROCESS-RECORD THRU 3200-EXIT END-READ. IF NOT CUST-OK AND NOT CUST-NOTFOUND DISPLAY "[" WS-TIMESTAMP-OUT "] READ FAILED" " STATUS=" CUST-STATUS END-IF. ADD 1 TO WS-PERF-READS. *> ---- Range search via START / READ NEXT ---- 3200-SELECT-RANGE. MOVE 0 TO WS-CUST-COUNT. MOVE WS-RANGE-LOW TO CUST-KEY. START CUSTOMER-FILE KEY IS NOT LESS THAN CUST-KEY IF CUST-STATUS NOT = "00" DISPLAY "[" WS-TIMESTAMP-OUT "] RANGE START" " FAILED STATUS=" CUST-STATUS MOVE " RANGE START FAILED" TO REPORT-LINE WRITE REPORT-LINE ELSE PERFORM UNTIL CUST-EOF READ CUSTOMER-FILE NEXT RECORD AT END SET CUST-EOF TO TRUE NOT AT END IF CUST-KEY > WS-RANGE-HIGH SET CUST-EOF TO TRUE ELSE ADD 1 TO WS-CUST-COUNT PERFORM 3200-PROCESS-RECORD THRU 3200-EXIT END-IF END-READ IF CUST-OK ADD 1 TO WS-PERF-READS END-IF END-PERFORM END-IF. *> ---- Greater-than search via START / READ NEXT ---- 3200-SELECT-GREATER-THAN. MOVE 0 TO WS-CUST-COUNT. MOVE WS-START-KEY TO CUST-KEY. START CUSTOMER-FILE KEY IS GREATER THAN CUST-KEY IF CUST-STATUS NOT = "00" DISPLAY "[" WS-TIMESTAMP-OUT "] GREATER START" " FAILED STATUS=" CUST-STATUS ELSE PERFORM UNTIL CUST-EOF READ CUSTOMER-FILE NEXT RECORD AT END SET CUST-EOF TO TRUE NOT AT END ADD 1 TO WS-CUST-COUNT PERFORM 3200-PROCESS-RECORD THRU 3200-EXIT END-READ IF CUST-OK ADD 1 TO WS-PERF-READS END-IF END-PERFORM END-IF. *> ============================================================ *> 3300-WRITE-OUTPUT : Write a single detail line to report *> ============================================================ 3300-WRITE-OUTPUT SECTION. 3300-START. MOVE WS-DETAIL-LINE TO REPORT-LINE. WRITE REPORT-LINE. IF NOT REPORT-OK MOVE "3300: WRITE REPORT FAILED" TO WS-ERROR-MSG DISPLAY "[" WS-TIMESTAMP-OUT "] " WS-ERROR-MSG " STATUS=" REPORT-STATUS PERFORM 6000-ERROR-HANDLE THRU 6000-EXIT END-IF. GO TO 3300-EXIT. 3300-EXIT. EXIT. *> ============================================================ *> 4000-REPORT : Summary with batch totals, operation stats, *> hash totals, and performance metrics *> ============================================================ 4000-REPORT SECTION. 4000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 4000-REPORT:" " Generating summary". WRITE REPORT-LINE FROM SPACES. MOVE "=== BATCH CONTROL TOTALS ===" TO REPORT-LINE. WRITE REPORT-LINE. STRING "Total search requests : " WS-BC-TOTAL-REQUESTS INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. STRING "Total records found : " WS-BC-TOTAL-FOUND INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. STRING "Total records not found: " WS-BC-TOTAL-NOTFOUND INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. WRITE REPORT-LINE FROM SPACES. MOVE "=== OPERATION TYPE STATISTICS ===" TO REPORT-LINE. WRITE REPORT-LINE. STRING "By-key searches : " WS-OP-BY-KEY-COUNT INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. STRING "Range searches : " WS-OP-RANGE-COUNT INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. STRING "Greater searches : " WS-OP-GREATER-COUNT INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. WRITE REPORT-LINE FROM SPACES. MOVE "=== DATA INTEGRITY HASH TOTALS ===" TO REPORT-LINE. WRITE REPORT-LINE. STRING "Hash total (CUST-BALANCE sum): " WS-HASH-TOTAL INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. WRITE REPORT-LINE FROM SPACES. MOVE "=== SEARCH PERFORMANCE METRICS ===" TO REPORT-LINE. WRITE REPORT-LINE. STRING "Total READs (by-key) : " WS-PERF-START-READS INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. STRING "Total READs (range) : " WS-PERF-RANGE-READS INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. STRING "Total READs (greater-than): " WS-PERF-GREATER-READS INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. DISPLAY "[" WS-TIMESTAMP-OUT "] 4000: Report written". GO TO 4000-EXIT. 4000-EXIT. EXIT. *> ============================================================ *> 5000-AUDIT : Write operation summary to audit file with *> timestamps, statistics, hash totals, and performance data *> ============================================================ 5000-AUDIT SECTION. 5000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 5000-AUDIT:" " Writing audit records". WRITE AUDIT-RECORD FROM SPACES. MOVE "--- OPERATION SUMMARY ---" TO AUDIT-RECORD. WRITE AUDIT-RECORD. STRING " Program: Main23SelectCond Timestamp: " WS-TIMESTAMP-OUT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. STRING " Test cases: " WS-TEST-CASE INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. WRITE AUDIT-RECORD FROM SPACES. MOVE " Search type breakdown:" TO AUDIT-RECORD. WRITE AUDIT-RECORD. STRING " By-key : " WS-OP-BY-KEY-COUNT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. STRING " Range : " WS-OP-RANGE-COUNT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. STRING " Greater-than: " WS-OP-GREATER-COUNT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. WRITE AUDIT-RECORD FROM SPACES. MOVE " Batch control totals:" TO AUDIT-RECORD. WRITE AUDIT-RECORD. STRING " Requests: " WS-BC-TOTAL-REQUESTS " Found: " WS-BC-TOTAL-FOUND " NotFound: " WS-BC-TOTAL-NOTFOUND INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. WRITE AUDIT-RECORD FROM SPACES. MOVE " Data integrity:" TO AUDIT-RECORD. WRITE AUDIT-RECORD. STRING " Hash total (balance): " WS-HASH-TOTAL INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. WRITE AUDIT-RECORD FROM SPACES. MOVE " Performance metrics:" TO AUDIT-RECORD. WRITE AUDIT-RECORD. STRING " ByKey=" WS-PERF-START-READS " Range=" WS-PERF-RANGE-READS " Greater=" WS-PERF-GREATER-READS INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. WRITE AUDIT-RECORD FROM SPACES. PERFORM GET-TIMESTAMP. STRING "*** AUDIT END *** " WS-TIMESTAMP-OUT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. IF NOT AUDIT-OK DISPLAY "[" WS-TIMESTAMP-OUT "] AUDIT END WRITE" " FAILED STATUS=" AUDIT-STATUS END-IF. DISPLAY "[" WS-TIMESTAMP-OUT "] 5000: Audit written". GO TO 5000-EXIT. 5000-EXIT. EXIT. *> ---- Transaction log entry ---- 5000-TXN-LOG. PERFORM GET-TIMESTAMP. STRING WS-TXN-TYPE " | " WS-TXN-DETAIL " | " WS-TIMESTAMP-OUT INTO WS-TXN-BUFFER END-STRING. MOVE WS-TXN-BUFFER TO TXN-RECORD. WRITE TXN-RECORD. IF NOT TXN-OK DISPLAY "[" WS-TIMESTAMP-OUT "] TXN LOG WRITE" " FAILED STATUS=" TXN-STATUS END-IF. *> ============================================================ *> 6000-ERROR-HANDLE : Log errors to DISPLAY, audit, report, *> and transaction log *> ============================================================ 6000-ERROR-HANDLE SECTION. 6000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 6000-ERROR: " WS-ERROR-MSG. STRING "ERROR: " WS-ERROR-MSG " at " WS-TIMESTAMP-OUT INTO AUDIT-RECORD END-STRING. WRITE AUDIT-RECORD. STRING "ERROR: " WS-ERROR-MSG " at " WS-TIMESTAMP-OUT INTO REPORT-LINE END-STRING. WRITE REPORT-LINE. MOVE "ERROR" TO WS-TXN-TYPE. MOVE WS-ERROR-MSG TO WS-TXN-DETAIL. PERFORM 5000-TXN-LOG. GO TO 6000-EXIT. 6000-EXIT. EXIT. *> ============================================================ *> 9000-EXIT-PGM : Close all files, display final summary *> ============================================================ 9000-EXIT-PGM SECTION. 9000-START. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] 9000-EXIT: Closing files". CLOSE REPORT-FILE. IF NOT REPORT-OK DISPLAY "[" WS-TIMESTAMP-OUT "] CLOSE REPORT-FILE" " FAILED STATUS=" REPORT-STATUS END-IF. CLOSE CUSTOMER-FILE. IF NOT CUST-OK DISPLAY "[" WS-TIMESTAMP-OUT "] CLOSE CUSTOMER-FILE" " FAILED STATUS=" CUST-STATUS END-IF. CLOSE TXN-LOG. IF NOT TXN-OK DISPLAY "[" WS-TIMESTAMP-OUT "] CLOSE TXN-LOG" " FAILED STATUS=" TXN-STATUS END-IF. CLOSE AUDIT-FILE. IF NOT AUDIT-OK DISPLAY "[" WS-TIMESTAMP-OUT "] CLOSE AUDIT-FILE" " FAILED STATUS=" AUDIT-STATUS END-IF. PERFORM GET-TIMESTAMP. DISPLAY "[" WS-TIMESTAMP-OUT "] ====== Finished =====". DISPLAY "[" WS-TIMESTAMP-OUT "] Requests:" WS-BC-TOTAL-REQUESTS " Found:" WS-BC-TOTAL-FOUND " NotFound:" WS-BC-TOTAL-NOTFOUND. DISPLAY "[" WS-TIMESTAMP-OUT "] Hash total:" WS-HASH-TOTAL. DISPLAY "[" WS-TIMESTAMP-OUT "] Reads ByKey:" WS-PERF-START-READS " Range:" WS-PERF-RANGE-READS " Greater:" WS-PERF-GREATER-READS. GO TO 9000-EXIT. 9000-EXIT. EXIT. *> ============================================================ *> GET-TIMESTAMP : Build WS-TIMESTAMP-OUT = YYYY/MM/DD HH:MM:SS *> ============================================================ GET-TIMESTAMP. ACCEPT WS-DATE-SYS FROM DATE YYYYMMDD. ACCEPT WS-TIME-SYS FROM TIME. MOVE WS-DATE-SYS(1:4) TO WS-TS-YEAR. MOVE WS-DATE-SYS(5:2) TO WS-TS-MONTH. MOVE WS-DATE-SYS(7:2) TO WS-TS-DAY. MOVE WS-TIME-SYS(1:2) TO WS-TS-HOUR. MOVE WS-TIME-SYS(3:2) TO WS-TS-MIN. MOVE WS-TIME-SYS(5:2) TO WS-TS-SEC. STRING WS-TS-DATE-FMT " " WS-TS-TIME-FMT INTO WS-TIMESTAMP-OUT END-STRING.