Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

Guide to OpenVMS File Applications


Previous Contents Index

7.2.2 Record-Locking Options

Record-locking options can be divided into three groups:

All record-locking options are specified by RAB input to the accessing service. All record-locking options apply to the Get service and the Find service, and most record-locking options apply to the Put service. You can specify a different set of record-locking options each time the record stream accesses a record.

This section describe the types of record access allowed by each record locking option. It also provides some examples of when an application program might select a particular record-locking option. The following four record-locking options control record access by other record streams:

To update or delete a record, a record stream must have an exclusive lock or a write lock on the record.

7.2.2.1 Exclusive Locking

By default, RMS performs exclusive locking. With exclusive locking, only the initial record stream is permitted to access the record for reading or writing until the lock is released. Any other record stream that tries to read or write the record by applying a lock is denied access. When a record stream is denied access because of a locked record, the requesting service returns a locked-record status (RMS$_RLK).

A record stream can read an exclusively locked record only with the read-regardless option (see Section 7.2.3.3).

Most application programs use exclusive locking because it requires minimal programming and provides maximum protection when modifying and reading records. Note, however, that contention is apt to be greatest when a record stream uses the exclusive-locking option.

See Section 7.2.1 for an example of how RMS uses exclusive locking for an application program that is modifying a record.

7.2.2.2 Write Locking

The write-locking option allows the record stream that locks a record to modify the record. This option prohibits other record streams from having write-lock access or exclusive lock access, both of which imply an intent to modify the record. The write-locking option also denies read-lock access to other record streams because a read-lock access is incompatible with a record stream that is modifying the record.

Contending record streams can read the record using the no-locking option, or the read-regardless option (see Section 7.2.3.3). When a contending record stream reads a write-locked record using the no-locking option, the accessing service returns a success status.

Typically, an application program uses the write-locking option when it wants the record to remain in a consistent state while the application program is modifying the record.

7.2.2.3 Read Locking

The read-locking option permits other record streams to access the record for reading but denies access to any record stream that attempts to access the record for making modifications.

No record stream is allowed to access a read-locked record for making modifications to the record until all record streams that have a read lock release the record. Any record stream that attempts to access a read-locked record using either the exclusive-locking option or the write-locking option are denied access. The requesting service returns a completion status record to the application program indicating that the record was locked (RMS$_RLK) and the requesting record stream was denied access.

Contending record streams can read the record using the read-locking option, the no-locking option or the read-regardless option (see Section 7.2.3.3). When a contending record stream accesses a read-locked record using the read-locking option or the no-locking option, the accessing service returns a success status.

Typically, an application program uses the read-locking option when it wants the record to remain in a consistent state while reading the record but does not intend to modify the record.

7.2.2.4 No Locking

The no-locking option specifies that the requesting record stream does not want to lock the record. This is the most compatible locking option because it permits the requesting record stream to have access to all locked records except for records that are locked for exclusive access. It also permits other record streams to apply any type of lock to the record. Using this option minimizes contention and may improve application program performance.

By implication, a record stream that uses the no-locking option can only access the record for reading. When a record stream uses the no-locking option to access a record, the invoked service returns with the record unlocked.

Note that when a record stream selects the no-locking option, RMS momentarily locks the record to determine whether or not the record is already locked by another record stream. This is required in order to determine if access is allowed. If the record is not locked, the requesting service returns a completion status indicating a successful access. If the record has an exclusive lock, the access is denied and the requesting service returns a completion status indicating the record is locked (RMS$_RLK). If the record has a write lock, the requesting service reads the record and returns a completion status indicating that the record was locked but a read was permitted (RMS$_OK_RLK).

If you specify the no-locking option together with the manual-unlocking option, the no-locking option takes precedence. That is, if you specify both options to the service that accesses the record, the service returns control to the application program with the record unlocked. See Section 7.2.4.1 for a description of the manual-unlocking option.

7.2.2.5 Put Service Considerations

Because the Put service adds a new record, the application program does not have to access an existing record. However, because adding a record is a multistep process, the record that is being added must be locked until the entire process is finished.

The scenario for adding a record to a file begins with the application program moving a record into its buffer. Next, the application program calls the Put service, which locks the record while it moves it from the application program buffer to the file. When the record is in the file, the Put service unlocks the record, making it available to other record streams. The locking process is transparent at the program level unless the application program selects the manual-unlocking option.

If a record stream tries to add a record using the no-locking option, the Put service ignores the option and adds the record.

7.2.2.6 Summary

This section provides two tables to summarize the information described in Sections 7.2.2.1 through 7.2.2.5.

The record-locking options that control record access exhibit varying degrees of compatibility. Table 7-5 summarizes access control locking compatibility by comparing the type of access being requested by a record stream with the current lock held by another record stream. The table does not take into account miscellaneous record-locking options, notably the read-regardless option.

Table 7-5 Compatibility of Record-Locking Options
  Current Lock Held by Another Record Stream
Requested Access EXCLUSIVE WRITE READ None
EXCLUSIVE NO NO NO YES
WRITE NO NO NO YES
READ NO NO YES YES
NO LOCK NO YES 1 YES 1 YES


1RMS$_OK_RLK is returned.

The next table lists record-locking options that control record access and how you select each option through the FDL and RMS interfaces.
Option Interface How to Select
Exclusive locking FDL:
RMS:
This is the default when you do not select write locking, read locking, or no locking.
Write locking FDL:
RMS:
CONNECT LOCK_ON_WRITE
RAB$L_ROP RAB$V_RLK
Read locking FDL:
RMS:
CONNECT LOCK_ON_READ
RAB$L_ROP RAB$V_REA
No locking FDL:
RMS:
CONNECT NOLOCK
RAB$L_ROP RAB$V_NLK

7.2.3 Handling Record-Locking Conflicts

Application programs that use shared files must handle record locking conflicts that may occur when two or more record streams try to access the same record.

RMS provides three options for handling record locking conflicts:

The following table lists the options for having RMS handle record locking conflicts and how you select each option through the FDL and RMS interfaces.
Option Interface How to Select
Wait if locked FDL:
RMS:
CONNECT WAIT_FOR_RECORD
RAB$L_ROP RAB$V_WAT
Wait timeout
period
FDL:

RMS:
CONNECT TIMEOUT_ENABLE and
CONNECT TIMEOUT_PERIOD
RAB$L_ROP RAB$V_TMO and RAB$B_TMO
Read regardless FDL:
RMS:
CONNECT READ_REGARDLESS
RAB$L_ROP RAB$V_RRL

The following sections describe each of these options.

7.2.3.1 Handling the Record-Locked Error

When a service is denied record access because of a record conflict, it returns a record-locked error status (RMS$_RLK) that indicates the access attempt failed because the record was locked. One option is to have the application program pause briefly, and then try again to access the record.

Example 7-1 contains a program fragment written in VAX MACRO that demonstrates one method of implementing a short pause between attempts to access a locked record.

Example 7-1 Designing a Pause Between Attempts to Access a Record

   .
   .
   .
10$:    $GET    RAB=INRAB              ; Get the record 
        BLBS    R0,GOT_RECORD          ; Branch on success 
        CMPL    R0,#RMS$_RLK           ; Record-locked error? 
        BNEQ    ERROR                  ; Quit on other errors 
        PUSHAL  ONE_SECOND             ; Pause for 
        CALLS   #1, G^LIB$WAIT         ; One second 
        BLBC    R0,ERROR               ; Quit on error 
        BRB     10$                    ; Try again for record 
   .
   .
   .

For more information about process control techniques, see the OpenVMS System Services Reference Manual.

7.2.3.2 Waiting for Locked Records

Another option for handling record-locking conflicts is to use the wait-if-locked option to wait for the locked record to be released. When you take this option, the accessing service does not return until the record is released or until a specified wait period expires.

The optional wait period is established using the wait-timeout-period option in conjunction with the wait-if-locked option. If the specified wait period expires before the requesting service obtains access to the locked record, the requesting service discards the request. The requesting service returns a completion status indicating that it waited for the locked record but was not granted access within the specified time period (RMS$_TMO).

If you select the wait-if-locked option and the requesting service must wait to access the record, it returns an alternate success status that indicates that it had to wait (RMS$_OK_WAT).

7.2.3.3 Reading Regardless of Lock

The third choice available to you for handling record-locking conflicts involves using the read-regardless (of lock) option. This option allows the accessing service to ignore a lock that prohibits read access. If a lock is granted under the specified record-locking option, access is granted and the service returns with the specified lock. If the lock is denied, the read-regardless option allows the accessing service, Get or Find, to read the record, regardless of the lock. The service returns without a lock for all three file organizations, but the returned status depends on the file organization:

An application program might use the read-regardless option to avoid record locking conflicts when a coordinated view of a record is not necessary. This option can also be used to continue sequential reads through a locked record.

Note that when you use the read-regardless option with the wait-if-locked option and a wait timeout period, RMS acts on the read-regardless option only after the wait timeout expires.

7.2.4 Miscellaneous Record-Locking Options

This section describes two miscellaneous record-locking options---the manual-unlocking option and the lock-nonexistent-record option in a relative file.

7.2.4.1 Manual-Unlocking Option

The manual-unlocking option gives the application program explicit control over releasing a record lock established by the Get service, the Find service, or the Put service as described in Section 7.2.1.

Even if you select the manual-unlocking option, RMS unlocks affected records when a record stream is disconnected (Disconnect service), or when a file is closed (Close service). Other record operations, including operations that result in errors, do not unlock the record.

To manually release record locks, the application program can invoke the Free service to unlock all record locks held by a record stream, or it can invoke the Release service to selectively release record locks, using the record's RFA.

Manual unlocking is useful when you have to modify multiple records as part of a single transaction. For example, assume the application program must modify two related but separate records. Assume, too, that the modified first record must not be accessed by another record stream until modifications to the second record are completed.

While the program modifies the first record, it uses the manual-unlocking option to hold the lock on the modified first record. It then proceeds to modify the second record while still maintaining a lock on the first record. By using manual unlocking, the application program can restore the original contents of the first record if the update to the second record fails, thereby maintaining data integrity.

7.2.4.2 Lock-Nonexistent-Record Option

The lock-nonexistent-record option applies only to random accessing of relative files. Relative files have a static physical structure made up of record cells in contrast to sequential files and indexed files, which have a dynamic structure. The record cells may or may not contain records. A record may have been deleted from a cell, or the cell may be empty (that is, it never contained a record). In either case, the record cells are accessible to the application program.

Typically, if a record stream tries to access and lock an empty cell in a relative file using random access, the accessing service returns a record-not-found error status (RMS$_RNF). However, if the lock-nonexistent-record option is selected, the accessing service returns an alternative success status (RMS$_OK_RNF) indicating that the record stream accessed a cell that never contained a record. If the cell contains a deleted record, RMS returns the deleted record with an alternate success status (RMS$_OK_DEL) to indicate that a deleted record was accessed.

The lock-nonexistent-record option prevents other record streams from putting a record into an empty cell until the locking record stream puts a record in it or releases the record lock. Any other record stream that tries to access the cell to put data into it receives a record-locked status (RMS$_RLK). If the record stream that has the lock puts a record into the cell, RMS returns an alternate success status (RMS$_OK_ALK) indicating that the cell was already locked. In general, the RMS$_OK_ALK status is returned when a service tries to lock a record that the current record stream has already locked. This also applies to the Put service, which locks and unlocks the record in one record operation.

The next table lists miscellaneous record-locking options and how you select each option through the FDL and RMS interfaces:
Option Interface How to Select
Manual unlocking FDL:
RMS:
CONNECT MANUAL_UNLOCKING
RAB$L_ROP RAB$V_ULK
Lock nonexistent record FDL:
RMS:
CONNECT NONEXISTENT_RECORD
RAB$L_ROP RAB$V_NXR

7.2.5 Record-Locking Deadlocks

A deadlock occurs when there is a set of processes and each process is waiting to access a record that is locked by another process in the set. The program stalls because none of the processes can acquire the record that it needs to complete its task and release its locks.

The lock manager resolves the deadlock by denying one of the lock requests. When this occurs with a record lock, RMS returns an RMS$_DEADLOCK status. The RMS$_DEADLOCK status is only returned if the wait-if-locked option is selected. If your application program does its own wait and retry handling, the deadlock will occur, but the lock manager will not detect it.

The amount of time that lapses before RMS takes action on the deadlock depends on the value specified in the DEADLOCK_WAIT system parameter. The default value for this system parameter is 10 seconds. For further details about how this parameter is set, see the OpenVMS System Manager's Manual.

For more information about the lock manager, see the OpenVMS System Services Reference Manual.

7.3 Local and Shared Buffering Techniques

One of the key performance factors is record buffering, that is, the transfer of records between a storage device and an area of memory accessible to the application program. Between the storage device and the record buffer in the appliction program, however, is an intermediate buffer area that RMS maintains. An intermediate buffer area is usually associated with each process; you can also specify a shared buffer area for a shared file.

7.3.1 Record Transfer Modes

For synchronous and asynchronous record operations, RMS provides two record transfer modes: move mode and locate mode.

In move mode, RMS copies a record from an I/O buffer into a buffer that you specify. For input operations, data is first read into the I/O buffer from a peripheral device (such as a disk), then moved to your application program buffer for processing. For output operations, you first build the record in your application program buffer; then RMS moves the record to the I/O buffer that is used to transfer the record to disk.

In locate mode, RMS allows the application program to access records in an I/O buffer by providing the address of the returned record as the internal buffer location instead of an application program buffer location (field RAB$L_RBF). Usually, this reduces program overhead because records can be processed directly within the I/O buffer. Locate mode is only available for input operations. Because it may not always be possible to use locate mode, you must supply an application program buffer for cases in which move mode must be used, even though you specify locate mode (see the OpenVMS Record Management Services Reference Manual).

Other RMS facilities allow programs to control I/O buffer space allocation or to leave space management to RMS. The following sections describe buffering.

7.3.2 Understanding Buffering

Your program perceives RMS record processing as the movement of records between a file and the program itself. In fact, RMS uses internal memory areas called I/O buffers to read or write blocks or buckets of data. Transparent to your program, RMS transfers blocks or buckets of a file into or from an I/O buffer. Records within the I/O buffer are then made available to the program when RMS transfers the records between the I/O buffer and the application program's record buffer.

The unit of data transfer between a file and the I/O buffers depends on the file organization. For the sequential organization, RMS reads and writes a block or series of blocks. For relative and indexed organizations, RMS reads and writes buckets.

The relationship between the application program and the I/O buffers that RMS maintains is shown in Figure 7-2. As illustrated, the application program resides in the P0 region of process address space. The RMS-maintained buffer area, together with RMS-maintained control information, resides in the P1 region.

Note that RMS normally overflows into P0 space and that the linker provides options for controlling the overflow. Note, too, that linker options are available for allocating additional buffer space in the P0 region, if needed. See the OpenVMS Linker Utility Manual for details.

Figure 7-2 RMS Buffers and the Application Program


The specified record buffer contains the record to be read or written, and RMS maintains the rest of the block in application program process space in an RMS-controlled area of the program.

For optimum performance, consider the number of buffers carefully. The defaults calculated by RMS are few and may be adequate for access to small files. For example, it is not unusual to specify many buffers when processing a large indexed file, yet the default number of buffers RMS provides is only two.

The CONNECT secondary attribute MULTIBUFFER_COUNT establishes the number of local buffers, but the FILE secondary attribute GLOBAL_BUFFER_COUNT (FAB field FAB$W_GBC) specifies the number of global buffers as described in Section 7.3.6.

Often the best way to achieve optimum buffering for a particular application program is to use combinations of buffer sizes and numbers of buffers. One approach is to time each combination and measure the number of I/O operations. Then consider the amount of memory used before you choose the one that improved application program performance the most.

With buffering, the goal is to use a buffer size and number of buffers that improves application program performance without exhausting the virtual memory resources of your process or system. Keep in mind the trade-offs between file I/O performance and exhausting memory resources. The buffers used by a process are charged against the process's working set. You should avoid allocating so many buffers that the CPU spends excessive processing time paging and swapping. For performance-critical application programs, consider increasing the size of the process working set and adding additional memory.

The system manager should monitor the paging and swapping activity of the application program's process and selected other processes to avoid improving the performance of the target application program at the expense of other application programs. Have your system manager consult the Guide to OpenVMS Performance Management 1 for system tuning information. For information about the resources needed for file applications, refer to Section 1.8.

When records are accessed sequentially, a large buffer (or buffers) should be used. Contiguous records in a file are read into memory in one or more blocks for sequential files or in buckets (multiblock units) for relative and indexed files. After the blocks or buckets are read into the buffer area provided by RMS, later access to adjacent records would access records in the same block or bucket in the buffer. This eliminates additional I/O and improves performance. When a record is needed that is not in the current buffer cache, one of the buffers is replaced by the blocks or the bucket that contains the new record.

When records in the file are repeatedly accessed, using more than one buffer can hold the previously accessed records in memory longer and eliminate an I/O operation when the program accesses the records again.

The buffers that the application program requests RMS to allocate for its use are referred to as a buffer cache and can be thought of as a buffer pool for your process. RMS uses buffer caches to locate records first before attempting I/O to the target device. When many processes share a file, the program can use a shared global buffer cache. (See Section 7.3.6.)

Note

1 This manual has been archived but is available in PostScript and DECW$BOOK (Bookreader) formats on the OpenVMS Documentation CD-ROM. A printed book can be ordered through DECdirect (800-354-4825).


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
4506PRO_020.HTML