Previous | Contents | Index |
Read operations can transfer varying amounts of data. The system variable RECOUNT contains the number of characters (bytes) read after each read operation.
After a read operation from your terminal, RECOUNT contains the number of characters transferred, including the line terminator. After accessing a record, RECOUNT contains the number of characters in the record.
RECOUNT is reset by every read operation on any channel, including the controlling terminal. Therefore, if you need to use the value of RECOUNT, copy it to another variable before executing another read operation. RECOUNT is undefined if an error occurs during a read operation.
RECOUNT is often used as the argument to the COUNT clause in the UPDATE or PUT statement for variable-length files. The following sequence of statements ensures that the output record on channel #5 is the same length as the input record on channel #4:
GET #4% bytes_read% = RECOUNT . . . PUT #5%, COUNT bytes_read% |
The STATUS function accesses the status longword that contains characteristics of the last opened file. If an error occurs during an input operation, the value of STATUS is undefined. If an error does not occur, the six low-order bits of the returned value contain information about the type of device accessed by the last input operation. These bits correspond to the following devices:
Both the VMSSTATUS and RMSSTATUS functions are used to determine which
non BASIC error caused a resulting BASIC error. In particular,
VMSSTATUS can be used for any non BASIC errors, while RMSSTATUS is used
specifically for RMS errors. For more information about these
functions, see Chapter 16 and the Compaq BASIC for OpenVMS Alpha and VAX Systems Reference Manual.
14.8 OPEN Statement Options
This section explains the OPEN statement keywords that enable you to control how a file is created or opened. These keywords are as follows:
BUCKETSIZE
BUFFER
CONNECT
CONTIGUOUS
DEFAULTNAME
EXTENDSIZE
FILESIZE
NOSPAN
RECORDTYPE
TEMPORARY
USEROPEN
WINDOWSIZE
The BUCKETSIZE clause applies only to relative and indexed files. A bucket is a logical storage structure that RMS uses to build and maintain relative and indexed files on disk devices. A bucket consists of one or more disk blocks. The default bucket size is the record size rounded up to a block boundary. Although RMS defines the bucket size in terms of disk blocks, the BUCKETSIZE clause specifies the number of records a bucket contains. For example:
OPEN "STOCK_DATA.DAT" FOR OUTPUT AS FILE #1%, & ORGANIZATION RELATIVE FIXED, BUCKETSIZE 12% |
This example specifies a bucket containing approximately 12 records. RMS reads in entire buckets into the I/O buffer at once, and a GET statement transfers one record from the I/O buffer to your program's record buffer.
When you open an existing relative or indexed file and specify a bucket size other than that originally assigned to the file, BASIC signals the error, "File attributes not matched" (ERR=160).
Records cannot span bucket boundaries. Therefore, when you specify a bucket size in your program, you must consider the size of the largest record in the file. Note that a bucket must contain at least one record. Buckets in both relative and indexed files contain information in addition to the records stored in the bucket. You should take this into consideration.
There are two ways to establish the number of blocks in a bucket. The first is to use the default. The second is to specify the approximate number of records you want in each bucket. A bucket size based on that number is then calculated.
The default bucket size assigned to relative and indexed files is as small as possible. A small bucket size, however, is rarely desirable.
A default bucket size is selected depending on:
If you do not define the BUCKETSIZE clause in the OPEN statement, BASIC does the following:
Note that when you specify a bucket size for files in your program, you must keep in mind the space versus speed tradeoffs. A large bucket size increases file processing speed because a greater amount of data is available in memory at one time; however, it also increases the memory space needed for buffer allocation and the processing time required to search the bucket. Conversely, a small bucket size minimizes buffer requirements, but increases the number of accesses to the storage device, thereby decreasing the speed of operations.
It is recommended that you use the DCL command EDIT/FDL to design files
used in production applications where performance is a concern.
14.8.2 BUFFER Clause
The BUFFER clause applies to disk files of any organization. In the case of sequential files, the BUFFER clause sets the number of blocks read in on each disk access. For relative and indexed files, the BUFFER clause determines the number of I/O buffers that are allocated. In general, the OpenVMS operating system supplies adequate defaults for all file types; therefore, the BUFFER clause is rarely necessary.
You can specify up to 127 buffers as either a positive or a negative number:
The CONNECT clause can be used only on indexed files. CONNECT lets you process different groups of records on different indexed keys or on the same key without incurring all of the RMS overhead of opening the same file more than once. For example, a program can read records in an indexed file sequentially by one key and randomly by another. Each stream is an independent, active series of record operations.
MAP (Indmap) WORD Emp_num, & STRING Emp_last_name = 20, & SINGLE Salary, & STRING Wage_code = 2 OPEN "IND.DAT" FOR INPUT AS FILE #1%, & ORGANIZATION INDEXED, & MAP Indmap, & PRIMARY KEY Emp_num, & ALTERNATE KEY Emp_last_name . . . OPEN "IND.DAT" FOR INPUT AS FILE #2% & ORGANIZATION INDEXED, & MAP Indmap, & CONNECT 1 |
The channel on which you open the file for the first time is called the parent. The CONNECT clause specifies another channel on which you access the same file; connected channels are called children. More than one OPEN statement can connect to the parent channel; however, you cannot connect to a channel that has already been connected to another channel.
Do not use the CONNECT clause when accessing files on remote DECnet
nodes.
14.8.4 CONTIGUOUS Clause
A contiguous file with physically adjoining blocks minimizes disk searching and decreases file access time. Once the system knows where a contiguous file starts on the disk, it does not need to use as many retrieval pointers to locate the pieces of that file. Rather, it can access data by calculating the distance from the beginning of the file to the desired data. If there is not enough contiguous disk space, BASIC allocates as much contiguous space as possible. (For truly contiguous records, you must use the USEROPEN clause and set the CTG bit in the FAB FOP field---see the OpenVMS Record Management Services Reference Manual.)
Opening a file with both the FILESIZE and CONTIGUOUS clauses
pre-extends the file contiguously or in as few disk extents as possible.
14.8.5 DEFAULTNAME Clause
The DEFAULTNAME clause in the OPEN statement lets you specify a default file specification for the file to be opened. It is valid with all file organizations. BASIC uses the DEFAULTNAME clause for any part of the file specification that is not explicitly supplied.
LINPUT "Next data file";Fil$ OPEN Fil$ FOR INPUT AS FILE #5%, & ORGANIZATION SEQUENTIAL, & DEFAULTNAME "USER$DEVICE:.DAT" |
The DEFAULTNAME clause supplies default values for the device, directory, and file type portions of the file specification. Typing ABC in response to the Next data file? prompt causes BASIC to try to open USER$DEVICE:ABC.DAT.
BASIC uses the DEFAULTNAME values only if you do not supply those parts
of the file specification appearing in the DEFAULTNAME clause. For
example, if you type SYS$DEVICE:ABC in response to the prompt, BASIC
tries to open SYS$DEVICE:ABC.DAT. In this case, SYS$DEVICE: overrides
the device default in the DEFAULTNAME clause. Any part of the file
specification still missing is filled in from the current default
device and directory of the process.
14.8.6 EXTENDSIZE Clause
The EXTENDSIZE attribute determines how many disk blocks RMS adds to the file when the current allocation is exhausted. The EXTENDSIZE clause only has an effect when creating a file. You specify EXTENDSIZE as a number of blocks. For example:
OPEN "TSK.ORN" FOR OUTPUT AS FILE #2%, & ORGANIZATION RELATIVE, EXTENDSIZE 128% |
The EXTENDSIZE clause causes RMS to add 128 disk blocks whenever the current space allocation is exhausted and the file must be extended.
The value you specify must conform to the following requirements:
If you specify zero, the extension size equals the RMS default value.
The EXTENDSIZE value can be overridden for single OPEN operations.
14.8.7 FILESIZE Clause
With the FILESIZE attribute, you can allocate disk space for a file when you create it. The following statement allocates 50 blocks of disk space for the file "VALUES.DAT":
OPEN "VALUES.DAT" FOR OUTPUT AS FILE #3%, FILESIZE 50% |
Pre-extending a file has several advantages:
Note that pre-extension can be a disadvantage if it allocates disk
space needed by other users. The FILESIZE clause is ignored when
BASIC opens an existing file.
14.8.8 NOSPAN Clause
By default, sequential files allow records to cross or span block boundaries. If records cross block boundaries, RMS packs records into the file end-to-end throughout the file, leaving space for control information and padding.
The NOSPAN clause overrides this default, forcing records to fit into
individual blocks (with space provided for control information and
padding). When block boundaries restrict records, fixed-length records
must be less than 512 bytes, and variable-length records less than 510
bytes. This can waste extra bytes at the end of each block. However,
when records span block boundaries, RMS writes records end-to-end
without regard for block boundaries. For example, if you specify
NOSPAN, only four 120-byte records fit into a disk block. If you do not
specify NOSPAN, BASIC begins writing the fifth record in the block, and
continues writing that record in the next block. This minimizes wasted
disk space and improves the file's capacity, at the minimal expense of
increased processing overhead.
14.8.9 RECORDTYPE Clause
The RECORDTYPE clause lets you specify record formats that are compatible with files created by other language processors. You can choose one of four qualifiers: LIST, FORTRAN, ANY, and NONE. The default for BASIC is LIST, which specifies carriage return format. This is standard for ASCII text files and means that carriage control is performed by RMS when writing the file to a unit-record device.
If your program accesses a file created with a Fortran language processor, use the FORTRAN qualifier. In the following example, the FORTRAN qualifier sets the FORTRAN carriage control attribute in the RAT field in the FAB. For more information about the FAB control structure, see Section 14.8.11. The first byte of the record is assumed to be the carriage control information. For example:
OPEN "FIL.DAT" FOR INPUT AS FILE #1%, & ORGANIZATION SEQUENTIAL, RECORDTYPE FORTRAN |
If your program accesses a file created by an unknown language processor or by DCL, use the ANY qualifier; this qualifier causes BASIC to handle any record attribute type. If you create a file with the ANY qualifier, BASIC uses the default of LIST. For example:
OPEN "FIL.DAT" FOR INPUT AS FILE #1%, & ORGANIZATION INDEXED, RECORDTYPE ANY |
If you specify the TEMPORARY clause in the OPEN statement, BASIC deletes that file in any one of the following cases:
No entry for this file is made in any directory.
14.8.11 USEROPEN Clause
The USEROPEN clause specifies an external long function that BASIC executes when you open or create a file. (You do not need to declare the USEROPEN routine with an EXTERNAL FUNCTION statement.) This procedure can then specify additional OPEN parameters for the file. For example:
OPEN "FILE.DAT" FOR INPUT AS FILE #2%, & ORGANIZATION INDEXED, USEROPEN Myopen, MAP ABC |
The code in Myopen determines how the file FILE.DAT is opened. The Run-Time Library sets up six RMS control structures before calling the USEROPEN procedure. Table 14-4 defines these structures and their meanings.
Structure | Definition |
---|---|
FAB | File Access Block |
RAB | Record Access Block |
NAM | Name Block |
XAB | FHC Extended Attributes Block |
ESA | Expanded Name String |
RSA | Resultant Name String |
A USEROPEN procedure should not alter the allocation of these structures, although it can modify the contents of many of the fields. You should not modify fields set by other OPEN statement keywords. For example, you should use the RECORDSIZE clause, not a USEROPEN routine, to set the record length.
The allocation of the RMS control structures (except for the RAB) lasts only for the duration of the OPEN statement. Therefore, your USEROPEN can retain only the RAB address for use after the OPEN operation is complete. Note that any additional structures that you allocate and link into the RMS structures must be unlinked before exiting the USEROPEN.
Future releases of the OpenVMS Run-Time Library might alter the use of some RMS fields. Therefore, you might have to alter your USEROPEN procedures accordingly. |
The following steps describe the execution of the USEROPEN routine:
Example 14-1 shows how to create a USEROPEN routine to obtain a RAB address.
Example 14-1 Creating a USEROPEN Routine |
---|
%TITLE "Example USEROPEN" %SBTTL "Useropen Routine to obtain RAB address" %IDENT "Version 1.1" FUNCTION LONG Get_rab_address ( Fabdef User_fab, Rabdef User_rab, LONG Channel ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Save the address of the RMS Record Access Block allocated by the caller ! in a global symbol. Open the file and return the status from RMS. ! ! FORMAL PARAMETERS (Standard for all BASIC USEROPEN procedures) ! ! User_fab Address of RMS File Access Block ! User_rab Address of RMS Record Access Block ! Channel Logical Unit assigned to file by caller. ! ! RETURN VALUE: RMS Status value ! ! GLOBAL COMMON USAGE ! ! RAB_ptr Single longword PSECT used to pass RAB address to caller. ! !-- OPTION INACTIVE = SETUP, & CONSTANT TYPE = INTEGER, & TYPE = EXPLICIT %NOLIST %INCLUDE "$FABDEF" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET" %INCLUDE "$RABDEF" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET" %INCLUDE "$RMSDEF" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET" %INCLUDE "STARLET" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET" %LIST !+ ! Common area used to pass RAB address to caller. !- COMMON (RAB_ptr) LONG rab_address DECLARE LONG Rms_status !+ ! Save RAB address in global symbol known to caller. ! Perform standard RMS open sequence !- Rab_address = LOC(User_rab::rab$b_bid) Rms_status = Sys$open( User_fab ) IF Rms_status AND Rms$_normal THEN Rms_status = Sys$connect( User_rab ) END IF END FUNCTION Rms_status |
You cannot use a USEROPEN routine to fill the RBF, UBF, BKS, or CTX fields in the RAB. These fields are filled in after the USEROPEN routine returns; any values placed there by the USEROPEN routine are overwritten. Also, you must not set RMS Locate mode when using a USEROPEN routine on sequential files. |
The WINDOWSIZE clause specifies the number of block retrieval pointers in memory for the file. WINDOWSIZE is not a file attribute, and therefore can be changed any time you open a file.
Retrieval pointers are associated with the file header and point to contiguous blocks on disk. By keeping retrieval pointers in memory, you can reduce the I/O associated with locating a record because the operating system does not have to access the file header for pointers as frequently. The number of retrieval pointers in memory at any one time is determined by the system default or by the value you supply in the WINDOWSIZE clause. The usual default number of retrieval pointers is 7.
A value of zero specifies the default number of retrieval pointers. A value of -1 specifies mapping the entire file, if possible. Values from -128 to -2 are reserved.
Previous | Next | Contents | Index |