Previous | Contents | Index |
PL/I uses the standard PL/I ON condition names to signal run-time errors that occur for file operations. The ON conditions and the circumstances under which they are signaled are as follows:
To handle any of these conditions in a PL/I procedure, you can establish an ON-unit to receive control if the specified condition is signaled. For example:
ON UNDEFINEDFILE (INFILE) OPEN FILE (INFILE) TITLE ('SYS$INPUT'); |
An ON-unit can be a generalized error-handling routine, written so that it responds to specific errors or prints an error message. Following are the PL/I built-in functions that provide meaningful information in an ON-unit to handle a file system error:
Whenever an error is signaled, the built-in function ONCODE makes available the condition value associated with the specific error. When a PL/I program is executing under control of the OpenVMS operating system, the value returned by the ONCODE built-in function is a unique 32-bit condition value that indicates the reason for the error. This value is from the system, from RMS, or from the PL/I run-time system.
The built-in function ONFILE returns a character string giving the name of the file constant on which the error occurred.
If the file was being accessed by key, the ONKEY built-in function
returns the key value that caused the error to be signaled.
4.3.2 Writing an Error Handler
You can write an ON-unit to detect and correct errors that occur during file operations. The following example shows an ON-unit that detects whether a record with a given key value was not found or whether an attempt was made to write a record whose key duplicates the value of an existing key.
ON KEY(STATE_FILE) BEGIN; %INCLUDE $RMSDEF; /* Check for a record not found */ IF ONCODE() = RMS$_RNF /* if record not found */ THEN DO; PUT SKIP EDIT(STATENAME,'Not found.') (A,X,A); STOP; END; /* Check for duplicate key */ ELSE IF ONCODE = RMS$_DUP THEN DO; PUT SKIP EDIT('Record already exists for', STATENAME) (A,X,A); STOP; END; END; |
In this example, the ON-unit declares symbolic names for two specific status values returned by ONCODE:
In an ON-unit for the KEY condition, ONCODE may also return the value associated with the status code RMS$_KEY. This code indicates that a key value is invalid; for example, it is an incorrect data type.
The symbolic names for RMS status codes are declared as %REPLACE
constants in module $RMSDEF of PLI$STARLET.
4.3.3 Default Error Handling for the File System
If a file system error occurs during the execution of a PL/I statement, the PL/I run-time system signals either the specific PL/I condition name or the ERROR condition. If no user-specified ON-units exist to handle either the specific PL/I condition or the ERROR condition, PL/I performs its default condition handling.
If any active procedure specified OPTIONS (MAIN), a default PL/I condition handler is present and executed. It prints a PL/I run-time error message. If there is no default PL/I handler, the error signal is passed to the default condition handler established by the OpenVMS system, which prints the message associated with the RMS error. If the error was a fatal error, the handler terminates the program; otherwise, the program continues.
The following example illustrates the type of message that the PL/I run-time system displays when an error occurs during an I/O operation:
%PLI-F-ERROR, PL/I ERROR condition. -PLI-I-IOERROR, I/O error on file 'STATE_FILE' -PLI-I-FILENAME, File name:'_DB7:[PROJECT]STDATA.DAT;' -PLI-I-NOTKEYD, Not a KEYED file. %TRACE-F-TRACEBACK, symbolic stack dump follows module name routine line relative PC absolute PC FLOWERS BEGIN%35 35 00000085 00000C88 FLOWERS BEGIN%29 29 000000BD 00000C02 FLOWERS FLOWERS 25 000000D3 00000B42 |
In this example, the error occurred because a keyed I/O statement was specified for a file lacking the KEYED attribute.
Stream I/O is one of the two general kinds of I/O performed by PL/I (the other is record I/O, described in Chapter 6). In stream I/O, more than one record or line can be processed by a single statement, and, conversely, multiple statements can process a single line or record. In record I/O, only one record of a file is processed by each READ or WRITE statement.
Stream input and output are performed by the statements GET and PUT, respectively. Both statements can perform either list-directed or edit-directed operations.
This chapter discusses the physical organization of stream files. See the Kednos PL/I for OpenVMS Systems Reference Manual for detailed information on the following topics:
A file has the STREAM attribute if one of the following conditions is met:
Files that are declared with the STREAM attribute have the following characteristics:
Stream files contain only ASCII data. The ASCII format used to represent program data in a stream output file differs depending on the attributes given to the file. For example, the representation of character strings differs depending on the presence or absence of the PRINT attribute in the file declaration.
An existing stream file can be reopened and accessed by the READ and WRITE statements. If READ and WRITE open a file implicitly, the attributes RECORD INPUT SEQUENTIAL and RECORD OUTPUT SEQUENTIAL are implied, respectively. These attributes are compatible with, for example, an existing disk file created with the STREAM and OUTPUT attributes.
The most straightforward way to retrieve an entire line (record) from an existing stream file is with a simple READ statement. The following sample program uses the READ statement to retrieve entire lines from a stream file (TEST.STR) that was created by a previous program; each record is then output to a record file (TEST.REC). Note that both files are declared with the RECORD attribute to be compatible with the READ and WRITE statements. TEST.STR is assumed to have 80-character lines, and these input records are assigned to a varying-length character variable.
FILES: PROCEDURE OPTIONS(MAIN); %REPLACE LENGTH BY 80; DCL INFILE RECORD INPUT; DCL OUTFILE RECORD OUTPUT; DCL INSTRING CHAR(LENGTH) VARYING; DCL EOF BIT(1) INITIAL('0'B); ON ENDFILE(INFILE) EOF='1'B; OPEN FILE(INFILE) TITLE('TEST.STR'); OPEN FILE(OUTFILE) TITLE('TEST.REC'); READ FILE(INFILE) INTO(INSTRING); DO WHILE(^EOF); WRITE FILE(OUTFILE) FROM(INSTRING); READ FILE(INFILE) INTO(INSTRING); END; END FILES; |
Record I/O is performed by the READ, WRITE, DELETE, and REWRITE statements; each statement processes an entire record. (In stream I/O, more than one line or record can be processed by a single statement.) In addition, some forms of record I/O allow you to access records in the file by record number or by a key field contained in the record.
This chapter includes the following topics:
For detailed description of record positional information and the READ,
WRITE, DELETE, and REWRITE statements, see the Kednos PL/I for OpenVMS Systems Reference Manual.
6.1 File Organizations
OpenVMS Record Management Services (RMS) supports the following three file organizations for record files:
The relative and indexed sequential file organizations are valid only for disk devices. To read or write files on tape or unit record devices, you must use sequential organization.
The type of organization you select for a file and the attributes of the file, that is, the record format and size, the file size, and so on, are set when you create a file and need not be specified again. When a program subsequently accesses an existing file, the file's organization and attributes are known to the file system. Table 6-1 shows the attributes and access modes for record files.
In a sequential file, records are ordered one after the other, in the order in which they are written. New records can be added only at the end of an existing file. Existing records can be updated or replaced only if the replacement record is exactly the same length as the original record. Sequential files are discussed in more detail in Section 6.5.
A relative file contains a specified number of fixed-length cells, numbered from 1 to n, where n is a user-specified maximum. Any record written to the file is written to a specific numbered cell; the cell number is also the relative record number of the record in the file.
Normally, the records in a relative file have an implied numeric data field, for example, an account number or employee number, which corresponds to the cell in which the record will be placed. When you read or write a record in a relatively organized file, you specify the record by its relative record number. Relative files are discussed in more detail in Section 6.6.
In an indexed sequential file, each record has one or more data keys that define a sort order for the file. The file system maintains an index for each key in the file and uses these indexes to locate a record when a program specifies the key of interest.
The records can be accessed either in the sort order defined by a key, or individually by key specification. Indexed sequential files are discussed in more detail in Section 6.7.
Table 6-1 shows the attributes and access modes for record files.
Attributes Specified |
Attributes Implied |
Valid Devices and File Organizations |
Usage |
---|---|---|---|
SEQUENTIAL
OUTPUT |
RECORD |
Any output
device or file except indexed |
Records can be added to the end of the file with WRITE statements. Each WRITE statement adds a single record to the file. |
SEQUENTIAL
INPUT |
RECORD |
Any input
device or file |
Records in the file are read with READ statements. Each statement reads a single record. |
SEQUENTIAL
UPDATE |
RECORD |
Relative,
indexed, sequential disk |
READ statements read a file's records in order. PL/I maintains the current record, which is the record just read. This record can be replaced in a REWRITE statement. 1 In a relative or indexed sequential file, the current record can also be deleted with a DELETE statement. Each statement processes a single record. |
DIRECT
OUTPUT |
KEYED
RECORD |
Relative,
indexed, sequential disk 2 |
WRITE statements insert records into the file at positions specified by keys. Each statement inserts a single record. |
DIRECT
INPUT |
KEYED
RECORD |
Relative,
indexed, sequential disk 2 |
READ statements specify records to be read randomly by key. Each statement reads a single record. |
DIRECT
UPDATE |
KEYED
RECORD |
Relative,
indexed, sequential disk 2 |
READ, WRITE and REWRITE statements specify records randomly by key. In a relative or indexed file, records can also be deleted by key. |
KEYED
SEQUENTIAL OUTPUT |
RECORD |
Relative,
indexed, sequential disk 2 |
WRITE statements insert records into the file at positions specified by keys. Each statement inserts a single record. This mode is identical to DIRECT OUTPUT. |
KEYED
SEQUENTIAL INPUT |
RECORD |
Relative,
indexed, sequential disk 2 |
READ statements access records in the file randomly by key or sequentially. |
KEYED
SEQUENTIAL UPDATE |
RECORD |
Relative,
indexed, sequential disk 1 |
Any record I/O operation is allowed except a WRITE statement that does not specify a key or a DELETE statement for a sequential disk file with fixed-length records. |
In standard PL/I, you can specify one of the following sets of attributes to define how a program accessesses the records in a file:
Two additional ways to access a file exist in PL/I. You specify an ENVIRONMENT option to indicate that you are going to process a file in either of these ways:
Although you cannot change the organization of the records in a file
after you have created the file, you can select a different type of
access mode for reading or processing the file. You can also access a
file using more than one access mode; for example, you can read a
record in an indexed file by specifying a key, and then read records
sequentially beginning at that position in the file.
6.2.1 Sequential Access
You can use sequential access with any type of file organization. When you access a file sequentially, each read or write operation reads or writes the next record in the file. As you process a file sequentially, PL/I keeps track of the current record (that is, the record just read or written) and the next record (the record that follows the record just read or written).
When you access a relative file sequentially, the records are read or written in order by relative record number. In a file in which not all cells contain records, sequential input operations involve only cells that contain data records.
When you access an indexed sequential file sequentially, you can
specify the number of the index on which to base the sequence. The next
record in the input operation is the next ordered record in the
specified index.
6.2.2 Random Access
When you access a file randomly by key, each I/O request must contain the KEY or KEYFROM option. The contents of the specified key depend on the file's organization, as follows:
By default, a READ statement accesses a record based on an exact match
of the
key specified. In PL/I you have the option of requesting that
the READ statement match any record with an equal or greater key value,
or any record with a greater key value.
6.2.3 Random and Sequential Access
When you access a file for random and sequential access, you can read
records sequentially or randomly. For example, you can use a keyed READ
statement to position the file at a specified record and then read or
process records sequentially from that position.
6.2.4 Block Input/Output
A block is a physical extent on a disk volume. You can elect to perform all of your I/O operations in terms of disk blocks: the file system transfers blocks of data at a time to your program. Your program is responsible for interpreting and deblocking the data in the blocks.
To perform block I/O, specify the BLOCK_IO option of the ENVIRONMENT attribute. This option is valid for disk files and for magnetic tape files. You can access a disk file for block I/O using either sequential or random access. If you are performing sequential block I/O, blocks are transferred to your program in sequential order. If you use keyed access, you must specify a virtual block number in the KEY or KEYFROM option. The first block in the file is number 1, the second block is number 2, and so on.
Block I/O to magnetic tape files can only be performed sequentially.
When a file is opened for block I/O, the SPACEBLOCK built-in subroutine
can be used to move the file forward or backward a given number of
blocks.
6.2.5 Access by Record Identification
You can access records in any type of disk file that is opened for any type of access using a record identification. You must do the following:
For example:
DECLARE LIBFILE FILE ENVIRONMENT(RECORD_ID_ACCESS), SAVED_ID(2) FIXED BINARY(31); OPEN FILE (LIBFILE) DIRECT; READ FILE (LIBFILE) KEY(MODULE_NAME) INTO (INREC) OPTIONS (RECORD_ID_TO(SAVED_ID)); |
Previous | Next | Contents | Index |