Document revision date: 30 March 2001

## Guide to OpenVMS File Applications

Previous | Contents | Index

### 8.2.3 Updating Records

The Update service modifies an existing record in a file. Your program must first locate the appropriate record and optionally retrieve the record itself, by calling either the Find service or the Get service. As with the Put service, your program must provide a buffer within the data portion of the program to hold the record that is to be updated.

When calling RMS directly, the program must also supply the length of each record to be written. This is a constant value when updating fixed-length records but varies from record to record when updating variable-length records or VFC records. Note that some high-level language compilers may automatically handle record buffer allocation and size specification or may supply a means to simplify its specification.

Your program must establish the current-record position before it updates a record. If the file is shared, the service that establishes the record position should also lock the record.

When you update indexed file records, take care not to alter the value of any key field that has been specified as unchangeable, for example, the primary key. To change the value of a record's primary key, you must replace the existing record with a new record having the desired primary key value. You can do this using the Put and Delete services respectively, or, where applicable, you may use the Put service with the update-if (RAB$L_ROP RAB$V_UIF) option.

When updating indexed file records, you do not have to specify the key of reference.

For more information about the Update service and record-processing options, refer to the OpenVMS Record Management Services Reference Manual.

### 8.2.4 Deleting Records

The Delete service removes a record from the file. You cannot delete individual records from sequential files, but you can truncate sequential files using the Truncate service. As with the Update service, the Delete service must be preceded by a Find or Get service to establish the current-record position.

When deleting records from an indexed file with alternate indexes, you can specify the fast-delete option to reduce the amount of time needed to delete a record. When you invoke the Delete service and specify the fast-delete option, RMS does not attempt to remove any of the pointers from alternative indexes to the deleted record.

You improve performance by postponing the processing needed to eliminate the pointers from alternative indexes to the record. However, there are disadvantages to using the fast-delete option:

- The unused pointers from the alternate indexes result in a corresponding waste of space.
- If the program later tries to access the deleted record from an alternate index, RMS must traverse the pointer linkage, find that the record no longer exists, and then perform the processing that was avoided originally with the Delete service.

Use the fast-delete option only if the immediate improvement in performance is worth the added space and overhead. Typically, you use the fast-delete option for indexed files that implement alternate keys and require frequent maintenance.

Conversely, avoid the fast-delete option for most read-only indexed files and for indexed files that are infrequently updated.

For more information about the Delete service, refer to the OpenVMS Record Management Services Reference Manual.

## 8.3 Secondary Services

This section provides very brief descriptions of the secondary services. Note that each of the services performs a specialized function with few options.

Connect | Allows you to connect to a single record stream or to multiple record streams.
Disconnect | Allows you to disconnect a record stream. This is done implicitly when a file is closed, but when using multiple record streams, you may want to disconnect one record stream but not others.
Flush | Writes modified I/O buffers and file attribute information maintained in memory to the file.
Free | Releases all record locks established by the current record stream.
Next Volume | Continues the next volume of a magnetic tape volume set. This service applies only to sequential files.
Release | Releases the record lock on the current record.
Rewind | Positions the record stream context to the first record of the file.
Truncate | Truncates a file beginning with the current record, effectively deleting it and all remaining records. This service applies only to sequential files.
Wait | Awaits the completion of an asynchronous record operation (or Connect service).

In addition to the record-processing services, a variety of file-processing services are also available. For more information about both types of processing services and the options that apply to each, see the OpenVMS Record Management Services Reference Manual.

## 8.4 Record Access for the Various File Organizations

To retrieve or insert a file record for a particular record stream, your program must specify either sequential or random access.

Sequential access can be used with all file organizations. For sequential files, sequential access implies that records are accessed according to their physical position in the file. For relative files, sequential access implies that records are accessed according to the ascending order of relative record numbers. In indexed files, sequential access implies that records are accessed according to a specified ordering of values for a particular key or keys.

Random access is defined as one of the following:

- Random access by key for indexed files implies that RMS uses the specified key value (contained within the record itself) to locate the desired record.
- Random access by relative record number for relative files and for sequential files having fixed-length records implies that the specified relative record number is used to locate the desired record. The relative record number does not necessarily reside in the record.
- Random access by RFA implies that the specified RFA is used to locate the desired record. This access mode is supported for all three file organizations and is normally available only to programs written in VAX MACRO or similar low-level languages.

Record access is specified using language statements or by establishing the appropriate control block field values (not offset values) in the RAB.

Note No FDL attributes are provided for specifying record access.

The appropriate RAB values in the access mode specification field, identified by the symbolic offset RAB$B_RAC, are as follows:

- You specify sequential access by inserting the value RAB$C_SEQ in the RAB$B_RAC field.
- You specify either random access by key or random access by relative record number by inserting the value RAB$C_KEY in the RAB$B_RAC field. This access mode is used to randomly access records in indexed files using a specified key value. It is also used to randomly access records by record number in relative files and in sequential files having fixed-length records.
- You specify random access by RFA for all file organizations by inserting the value RAB$C_RFA in the RAB$B_RAC field.

Your program may also need to specify the key or other record identifier needed to access the records. For indexed files, there are additional key-related options.

The record access mode can be changed without reopening the file or reconnecting the record stream. For example, you can use random access by key to establish the current-record position in an indexed file and then retrieve records sequentially by a specified sort order. Note, however, that changing modes in this manner requires program access to the RAB$B_RAC control block field at run time.

The record access mode, in conjunction with the file organization, is what determines the manner in which a record is selected. In the following sections, the sequential and random access modes are discussed in the context of the applicable file organizations. Random access by RFA is discussed separately because it applies to disk files, regardless of file organization.

The following discussion of record access modes is directed primarily toward services that insert records and services that retrieve records. For additional details about these services, see the OpenVMS Record Management Services Reference Manual.

### 8.4.1 Processing Sequential Files

A program can read sequential files on both tape and disk devices using the sequential record access mode. If the file resides on disk, the random access by RFA mode can be used to read records, and if the file uses the fixed-length record format, the random access by relative record number mode is permitted.

You can add records only to the end of a sequential file.

All record access modes permit you to establish a new current-record position in a sequential file using the Find service. With sequential access, the Find service permits you to skip over records. With either random access by relative record number or random access by RFA, the Find service establishes a starting point for sequential Get services.

You cannot randomly delete records from a sequential file. However, you can randomly update records in a sequential file if the file is on disk and if the update does not change the record size.

The following sections discuss the use of sequential and random access modes with sequential files.

#### 8.4.1.1 Sequential Access

The sequential access mode is supported for sequential files on all devices. It is the only record access mode that is supported for nondisk devices, such as terminals, mailboxes, and magnetic tapes.

With sequential access, RMS returns records from sequential files in the order in which they were stored. When a program has retrieved all of the records from a sequential file, any further attempt to sequentially access records in the file causes RMS to return an end-of-file (no more data) condition code.

In sequential access mode, you can add records only to the end of a sequential file, that is, the file location immediately following the current-record position.

#### 8.4.1.2 Random Access

You can use the relative record number to randomly retrieve and insert records in sequential files having fixed-length records. Records are numbered in ascending order, starting with number 1.

In a sequential file, records are usually inserted at the end of the file. To insert records randomly within the current boundaries of the file at a relative record number less than or equal to the highest record number, set the update-if option (FDL attribute CONNECT UPDATE_IF; RAB$L_ROP bit RAB$V_UIF) to overwrite existing records.

When accessing a sequential file randomly by relative record number, your program must provide the record number at symbolic offset RAB$L_KBF and must specify a key length of 4 at symbolic offset RAB$B_KSZ, in the RAB.

### 8.4.2 Processing Relative Files

The relative file organization permits greater program flexibility in performing record operations than the sequential organization. A program can read existing records from the file using sequential, random access by relative record number mode or random access by RFA mode. You can write new records either sequentially or randomly, as long as the intended record location (cell) does not already contain a record. You can also delete records.

All record access modes for relative files allow you to establish the current-record position using the Find or Get service. After finding the record, RMS permits you to delete the record from the relative file. After the record is deleted, the empty cell becomes available for a new record. In addition, your program can update records anywhere in the file. For variable-length records, the Update service can modify the record length up to the maximum size specified when the file was created.

When you insert a record into a relative file, the record is placed in a fixed cell within the file. A cell within a relative file can contain a record, can be vacant (never have contained a record), or can contain a deleted record.

The following sections discuss the sequential and random access modes for relative files.

#### 8.4.2.1 Sequential Access

For relative files, the sequential access mode can be used to retrieve successive records in ascending record number. Vacant cells and cells that contain deleted records are skipped over automatically.

#### 8.4.2.2 Random Access

You can directly read a record within a relative file by specifying the appropriate relative record number. If you attempt to read from a nonexistent cell---that is, a vacant cell or a cell containing a deleted record---RMS returns an error message.

To position the record stream at a particular cell, regardless of whether or not it contains a record, use the nonexistent-record option (FDL attribute CONNECT NONEXISTENT_RECORD), or set the RAB$V_NXR bit in the RAB$L_ROP field.

You can use the forward search key options (equal-or-next-key and next-key) to directly access records in relative files, but the reverse search key options are not supported for relative files.

The equal-or-next-key option (FDL attribute CONNECT KEY_GREATER_EQUAL) directs RMS to return a record having a record number equal to or greater than the specified record number. For example, when you specify record number 48, RMS returns record number 48. If RMS does not find record number 48, it returns the first record it encounters having a number greater than 48.

The next-key option (FDL attribute CONNECT KEY_GREATER_THAN) directs RMS to return the record that has the next greater record number. For example, when you specify record number 48, RMS returns record number 49, if record 49 exists.

You can also use random access mode to insert records into relative files. You can even overwrite cells that contain records by selecting the update-if option (FDL attribute CONNECT UPDATE_IF) or by directly setting the RAB$V_UIF bit in the RAB$L_ROP field.

To access a relative file randomly by record number, your program must contain the relative record number in the RAB at symbolic offset RAB$L_KBF and the key length value 4 at symbolic offset RAB$B_KSZ.

### 8.4.3 Processing Indexed Files

Indexed files provide the most record-processing flexibility. Your program can read existing records from the file in sequential, random access by RFA mode or random access by key mode. RMS also allows you to write any number of new records into an indexed file if you do not violate a specified key constraint, such as not allowing duplicate key values.

In random access by key mode, RMS provides two forward search key options for use with one of four match options (see Section 8.4.3.2). A reverse search key option permits reverse random access when used in combination with either of the two forward search key options.

The search key options are:

- The equal-or-next-key option (FDL attribute CONNECT KEY_GREATER_EQUAL) searches the file forward (toward the end of the file) to return the next record whose key value is equal to or greater than the current key of reference, according to sort order.
- The next-key option (FDL attribute CONNECT KEY_GREATER_THAN) searches the file forward (toward the end of the file) to return the record whose key value is greater than the current key of reference, according to sort order.
- The reverse search key option is used with either the equal-or-next-key option or the next-key option to access selected records in reverse order. (This option does not reverse the direction of sequential access operations, which are always done in the forward direction, according to sort order.)
  If the reverse search key option is used with the equal-or-next-key option, RMS searches the file backward (toward the beginning of the file) to return the previous record whose key value is equal to or less than the current key of reference, assuming according to sort order.
  If the reverse search key option is used with the next-key option, RMS searches the file backward (toward the beginning of the file) to return the previous record whose key value is less than the current key of reference, according to sort order.

Table 8-2 lists the search key types for each option combination. Note that three of the listed combinations are not supported (not allowed) and result in the return of an error message.

Table 8-2 Search Key Types
| Search Key Option Settings
--- | ---
Search Key Type | Reverse | Equal or Next | Next
Equal 1 | Off | Off | Off
Equal or greater than | Off | On | Off
Greater than | Off | Off | On
Not allowed | Off | On | On
Not allowed | On | Off | Off
Equal or less than 2 | On | On | Off
Less than (previous) | On | Off | On
Not allowed | On | On | On

1Default forward search key
2Default reverse search key

If you use the reverse search key option with a set of records that has duplicate keys, only the first record in the set is returned. An application that needs to access all records having duplicate key values requires additional compiler or program logic.

On-disk data structures are designed to provide optimum performance for forward searches. Reverse search performance may be diminished, especially for applications that process long chains of deleted records. To take advantage of built-in caching that improves performance when retrieving successive previous records, specify full key sizes and select the next-key option.

The following C program demonstrates the use of the search key option. The program reads the last and the next-to-last records in a file.

    /*
       REVERSE-SEARCH

     The file is defined by the logical INFILE, and has record and
     key sizes defined below.
    */

    #include <rms>  /* defines rabs and fabs */
    #include <stdio>  /* defines printf  */
    #include <string> /* defines strlen  */
    #include <stdlib> /* defines exit   */
    #include <starlet>  /* defines sys$open, et al  */

    #define RECORD_SIZE 80
    #define KEY_SIZE 10

    char INPUT_NAME[] = "INFILE";

    struct FAB infab;
    struct RAB inrab;

    error_exit (code, value)
    long code;
    long value;
    {
     void lib$signal();
     lib$signal (code, value);
     exit (0);
    }

    main ()
    {
     char record [RECORD_SIZE + 1]; /* record buffer */
     char key [KEY_SIZE + 1];  /* key buffer */
     long status;

     /* Set up input fab */
     infab = cc$rms_fab;
     infab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL;
     infab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD
         | FAB$M_SHRDEL; /* read/write sharing */
     infab.fab$l_fna = INPUT_NAME; /* logical name INFILE */
     infab.fab$b_fns = sizeof INPUT_NAME - 1;

     /* Set up input rab */
     inrab = cc$rms_rab;
     inrab.rab$l_fab = &infab;
     inrab.rab$b_rac = RAB$C_KEY;  /* key access */
     inrab.rab$l_rop = RAB$M_REV | RAB$M_NXT;
          /* reverse-search, next */
     inrab.rab$b_krf = 0;   /* access by primary key */
     inrab.rab$l_ubf = record;  /* record buffer */
     inrab.rab$w_usz = RECORD_SIZE;  /* maximum record size */

     /* Open and connect */
     status = sys$open (&infab);
     if (! (status & 1))
      error_exit (status, infab.fab$l_stv);
     status = sys$connect (&inrab);
     if (! (status & 1))
      error_exit (status, inrab.rab$l_stv);

     /* Set key larger than the largest possible real key */
     strcpy (key, "~");
     inrab.rab$l_kbf = key;   /* key buffer */
     inrab.rab$b_ksz = 1;   /* set key length */

     /* Get and display the last record */
     status = sys$get (&inrab);
     if (! (status & 1))
      error_exit (status, inrab.rab$l_stv);
     record[inrab.rab$w_rsz] = '\0';
     printf ("Record: {%s}\n", record);

     /* Set key to the (just-read) largest key */
     inrab.rab$l_kbf = record;  /* key buffer */
     inrab.rab$b_ksz = KEY_SIZE;  /* set key length */

     /* Get and display the next-to-last record */
     status = sys$get (&inrab);
     if (! (status & 1))
      error_exit (status, inrab.rab$l_stv);
     record[inrab.rab$w_rsz] = '\0';
     printf ("Record: {%s}\n", record);

     /* Close file */
     status = sys$close (&infab);
     if (! (status & 1))
      error_exit (status, infab.fab$l_stv);
    }

You can use the Find service (similar to the Get service), in sequential access mode, random access by RFA mode, or random access by key access mode. When finding records in random access by key access mode, your program can specify any one of the four types of key matches (exact, generic, approximate, generic/approximate) described in Section 2.1.1.2 and Section 8.4.3.2.

In addition to reading, writing, and finding a record, your program can delete or update any record in an indexed file if the operation does not violate specified key characteristics. For example, if the program specifies that key values cannot be changed, any update that attempts to change a key value is rejected.

The next section describes how indexed files are used with the sequential and random access by key modes.

Previous | Next | Contents | Index

| privacy and legal statement |
4506PRO_023.HTML