VSAM and IDCAMS
In the indexed-files module you used ORGANIZATION IS INDEXED and
GnuCOBOL built the file for you. On z/OS a COBOL program can't create a
VSAM file. Someone first defines it with the utility IDCAMS
(Access Method Services), and only then can a program open it.
The four VSAM types
| Type | Records are | COBOL ORGANIZATION |
Typical use |
|---|---|---|---|
| KSDS | in key order, with an index | INDEXED |
customer, account, policy masters |
| ESDS | in the order written | SEQUENTIAL |
logs, audit trails |
| RRDS | in numbered slots | RELATIVE |
direct lookup by number |
| LDS | a byte stream, no records | not used from COBOL | Db2 table spaces |
A KSDS is a cluster of two components: the data component holding the records in control intervals (CIs, blocks of typically 4 KB), grouped into control areas (CAs), and the index component. When a record is inserted into a full CI, VSAM performs a CI split, moving half the records to a free CI. Lots of splits make a file slow, which is why shops reorganise busy KSDSs regularly (unload, delete, define, reload).
Defining a cluster
//DEFCUST EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE BANK.CUSTOMER.MASTER CLUSTER PURGE
SET MAXCC = 0
DEFINE CLUSTER (NAME(BANK.CUSTOMER.MASTER) -
INDEXED -
KEYS(6 0) -
RECORDSIZE(26 26) -
FREESPACE(20 10) -
CYLINDERS(5 1) -
SHAREOPTIONS(2 3)) -
DATA (NAME(BANK.CUSTOMER.MASTER.DATA)) -
INDEX (NAME(BANK.CUSTOMER.MASTER.INDEX))
/*
INDEXEDmakes a KSDS (NONINDEXED= ESDS,NUMBERED= RRDS).KEYS(6 0): key length 6, starting at offset 0.RECORDSIZE(avg max)in bytes. It must match the copybook.FREESPACE(20 10): leave 20% of each CI and 10% of CAs empty for inserts, to delay splits.DELETE ... PURGEthenSET MAXCC = 0is the standard "delete if it exists" idiom: the delete fails harmlessly on the first run.
Loading and inspecting
//LOAD EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//INFILE DD DSN=BANK.CUSTOMER.SORTED,DISP=SHR
//SYSIN DD *
REPRO INFILE(INFILE) OUTDATASET(BANK.CUSTOMER.MASTER)
LISTCAT ENTRIES(BANK.CUSTOMER.MASTER) ALL
PRINT INDATASET(BANK.CUSTOMER.MASTER) CHARACTER COUNT(5)
/*
REPRO copies records (sequential to VSAM, VSAM to sequential for a
backup, VSAM to VSAM). LISTCAT ALL shows the definition and statistics
such as record count and CI splits. PRINT dumps records in CHARACTER,
HEX or DUMP format.
A sequential load must be in ascending key order, whether it's
REPRO or your own program. GnuCOBOL enforces the same rule. Run this:
IDENTIFICATION DIVISION.
PROGRAM-ID. KSDSLOAD.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CUST-FILE ASSIGN TO CUSTMAST
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS CUST-ID
FILE STATUS IS WS-FS.
DATA DIVISION.
FILE SECTION.
FD CUST-FILE.
01 CUST-REC.
05 CUST-ID PIC X(6).
05 CUST-NAME PIC X(20).
WORKING-STORAGE SECTION.
01 WS-FS PIC XX.
PROCEDURE DIVISION.
OPEN OUTPUT CUST-FILE
MOVE "C00001ADA LOVELACE" TO CUST-REC
WRITE CUST-REC
MOVE "C00007GRACE HOPPER" TO CUST-REC
WRITE CUST-REC
DISPLAY "C00007, STATUS " WS-FS
MOVE "C00003ALAN TURING" TO CUST-REC
WRITE CUST-REC
DISPLAY "C00003 AFTER C00007, STATUS " WS-FS
CLOSE CUST-FILE
OPEN INPUT CUST-FILE
READ CUST-FILE
DISPLAY "FIRST RECORD, STATUS " WS-FS ": " CUST-NAME
CLOSE CUST-FILE
STOP RUN.
C00007, STATUS 00
C00003 AFTER C00007, STATUS 21
FIRST RECORD, STATUS 00: ADA LOVELACE
Status 21 is a sequence error, the same one VSAM returns.
In the program's JCL a VSAM file needs only its name:
//CUSTMAST DD DSN=BANK.CUSTOMER.MASTER,DISP=SHR. Record size, key and
space all live in the catalog.
Not in the simulator
This course's job simulator doesn't include IDCAMS, so the JCL above is for reading only. The COBOL side is identical, which is why the indexed-file programs you wrote earlier would run against a real KSDS unchanged.
On the job
Before you touch a VSAM file, run LISTCAT ALL on it. Record size,
key position and the number of records answer half of the questions
you'll have, and support teams expect you to check them first.