HP OpenVMS Systems Documentation

Content starts here

OpenVMS I/O User's Reference Manual


Previous Contents Index

6.6.1 Design Overview

The design approach writes the log record in a main loop thathibernates when it has no work to do. The loop uses ASTs to readkeystrokes from the terminal, write to the pseudoterminal, and writedata to the terminal. When a block of characters is written to theterminal, that block is placed into a queue of blocks to be written tothe log file, and a wake request is issued. Logging is stopped if youlog out of the subprocess, if you enter the stop logging characterCtrl\, or if a severe error occurs during data processing. When any ofthese events occur, all outstanding log records are written before theprogram exits.

One major design consideration is how flow control should behandled---either by attempting to enforce flow control, or by lettingthe terminal and terminal driver handle it. In this example, theterminal and terminal driver handle flow control; the driver sends XON,XOFF, or BELL characters to the terminal as necessary.

One of the six I/O buffers is permanently reserved as the terminal read buffer. This buffer is passed directly to the terminal read $QIO. This eliminates having to move data that is read from the terminal into the read buffer. The other five buffers are placed in a queue and are allocated and deallocated as needed. This pool of buffers reserves the first two longwords to be used as queue headers and traditional IOSBs. The third longword and the I/O status longwords are used by the pseudoterminal driver.

Example 6-1 Sample Pseudocode for Pseudoterminal Driver Program

/*** Main Routine**** Function: Intitializes the environment and then hibernates, waiting** to be awakened.  When awakened, the program checks to see whether it** is exiting, or whether more log data is available.  If more data is** available, the data is appended to the current log record and checked** to see whether a log record should be written.  A log record is written** either when maxbuf characters are in the log buffer,** or when it finds a <CR><LF> character pair.  The algorithm** allows an unlimited number of <NULL> fill characters to occur** between the <CR> and the <LF>. If the program is** exiting, it closes the log file,  deletes the pseudoterminal, resets the** terminal, and exits.*/Initialize environments (This includes creating pseudoterminal, the log file                         and starting up the subprocess.)If (Initialization OK) Then   Do      while (I/O buffer to log)         Data size = number of bytes in I/O buff         For all data in I/O buffer            If (cr_seen) Then               If (current char == <LF>) Then                  write current log buffer                  reset cr_seen                  point to start of log buffer               Else if (current char != <NULL>) Then                  insert <CR> and current char into log buffer                  move log buffer ptr over 2 characters                  reset cr_seen               Endif            Else if (current character != <CR>) Then               insert character into log buffer               move log buffer ptr over 1 character            Else               set cr_seen            Endif            If (log buffer ptr >= IOC$GW_MAX-48) Then               write log buffer               reset log buffer pointer               reset cr_seen            Endif         Endloop         Free I/O buffer call free_io_buffers      Endwhile      If (not exiting) Then         Wait for more to do call SYS$HIBER      Endif   Until ((exiting) and (no I/O buffers to log))   close log file   If ((close failed) and (exit reason is SS$_NORMAL)) Then      set exit to status to failure reason   Endif   If (subprocess still running) Then      call SYS$FORCEX to run down the subprocess   Endif   call PTD$CANCEL to flush all pending pseudoterminal read requests   call SYS$CANCEL to flush all terminal requests   call PTD$DELETE to delete the pseudoterminal   If ((delete failed) and (exit reason is SS$_NORMAL)) Then      set exit to status to failure reason   Endif   reset terminal to startup condition using SYS$QIOW   If ((terminal reset failed) and (exit reason is SS$_NORMAL)) Then      exit to status to failure reason   EndifEndifcall LIB$SIGNAL and report exit reasonExit/***** Initialization Code**** Function: This routine sets the terminal characteristics, creates the** pseudoterminal, starts up the subprocess, and opens the log file.  If** any of these steps fail, the program undoes any steps already done and** returns to the  main routine.***/read the maximum buffer size from IOC$GW_MAXBUFAssign a channel to SYS$INPUTIf (assign ok) Then   Read the terminal characteristics from the terminal   If (read of terminal characteristics ok) Then      Open log file with maximum record size of IOC$GW_MAXBUF      If (open ok) Then         Create the pseudoterminal with characteristics of terminal         If (create ok) then            Place 4 of the buffers on the queue of free I/O buffers            Copy terminal characteristics and modify them to NOECHO and PASTHRU            Set the terminal characteristics use modified value            If (set ok) Then               Get device name of pseudoterminal use SYS$GETDVI               If (get ok) Then                  Create subprocess                  If (create ok) Then                     Enable XON, XOFF, BELL, SET_LINE event notification ASTs                     If (AST setup OK) Then                        Call PTD$READ to start reading from the pseudoterminal                                      ASTADR = ft_read_ast                                      ASTPRM = buffer address                                      READBUF = I/O buffer + 8                                      READBUF_LEN = 500                        If (read ok) Then                           Call SYS$QIO and read a single character from the                                        keyboard ASTADR = kbd_read_ast                           If (read failed) Then                              Call PTD$CANCEL to flush queued pseudoterminal read                              Call PTD$DELETE to delete pseudoterminal                              Reset terminal to original state                              Close log file and delete it                           Endif                        Else                           Call PTD$DELETE to delete pseudoterminal                           Reset terminal to original state                           Close log file and delete it                        Endif                     Else                        Call PTD$DELETE to delete pseudoterminal                        Reset terminal to original state                        Close log file and delete it                     Endif                  Else                     Call PTD$DELETE to delete pseudoterminal                     Reset terminal to original state                     Close log file and delete it                  Endif               Else                  Call PTD$DELETE to delete pseudoterminal                  Reset terminal to original state                  Close log file and delete it               Endif            Else               Call PTD$DELETE to delete pseudoterminal               Close log file and delete it            Endif         Else            Close log file and delete it         Endif      Endif   EndifEndif/*** kbd_read_ast**** Function: This routine is called every time data is read from the terminal.** If the program is exiting, then the routine exits without restarting the** read.   The character read is checked to see if the terminate processing** character Ctrl\ was entered.  If the terminate processing character was** entered, the exiting state is set and a SYS$WAKE is issued to start the** main routine.  Now an attempt is made to obtain an I/O buffer in which** to store echoed output.  If an I/O buffer is unavailable, a simple** PTD$WRITE is issued; a PTD$WRITE with echo is issued if a buffer is** available.  If the write completes successfully, another read is issued** to the keyboard.***/If (not exiting) Then   If (read ok) Then      Search input data for Ctrl\      Allocate a read buffer call allocate_io_buffer      If (got a buffer) Then         Call PTD$WRITE to write characters to pseudoterminal                        ASTADR = ft_echo_ast                        ASTPRM = allocated I/O buffer                        WRTBUF = read I/O buffer                        WRTBUF_LEN = number of characters read                        ECHOBUF = allocated I/O buffer                        ECHOBUF_LEN = 500      Else         Call PTD$WRITE to write characters to pseudoterminal                        WRTBUF = read I/O buffer                        WRTBUF_LEN = number of characters read      Endif      If (write setup ok)         If ((write status is ok) or (write status is SS$_DATALOST))            Issue another single character read to terminal with                     ASTADR = kbd_read_ast, with data going to read I/O buffer            If (read setup failed) Then               Set exit flag               Set exiting reason to SS$_NORMAL            Endif         Else            Set exit flag            Set exiting reason to SS$_NORMAL         Endif      Else         Set exit flag         Set exiting reason to SS$_NORMAL      Endif   Else      Set exit flag      Set exiting reason to read failure status   Endif   If (exiting) Then      Wake the mainline call SYS$WAKE   EndifEndif/*** terminal_output_ast**** Function: This routine is called every time an I/O buffer is written** to the terminal.  If the terminal write request completes successfully,** it inserts the I/O buffer into the queue of I/O buffers to be logged.** If the I/O buffer is the only entry on the queue, it issues a SYS$WAKE** to start the main routine. To prevent spurious wake requests,** SYS$WAKE is not issued if multiple entries are already on** the queue.  If a terminal write error occurs, the routine sets the** exit flag and wakes the main routine.***/If (terminal write completed ok) Then   insert I/O buffer onto logging queue   If (this is only entry on queue) Then      wake the mainline call SYS$WAKE   EndifElse   set exit flag   set exiting reason to terminal write error reason   wake the mainline call SYS$WAKEEndif/***** ft_read_ast**** Function: This routine is called when a pseudoterminal read request** completes.  It writes the buffer to the terminal and attempts to start** another read from the pseudoterminal.  If the program is not exiting,** this routine writes the buffer to the terminal and does not start another** pseudoterminal read.***/If (not exiting)   If (Pseudoterminal read ok) Then      write buffer to the terminal ASTADR = terminal_output_ast      If (write setup ok) Then         Allocate another read buffer call allocate_io_buffer         If (got a buffer) Then            Call PTD$READ to restart reads from the pseudoterminal.                      ASTADR = ft_read_ast                      ASTPRM = buffer address                      READBUF = I/O buffer + 8                      READBUF_LEN = 500            If (read setup failed) Then               Set exit flag               Set exiting reason to read failure reason               Wake the mainline call SYS$WAKE            Endif         Else            Set read stopped flag         Endif      Else         Set exit flag         Set exiting reason to terminal write failure reason         Wake the mainline call SYS$WAKE      Endif   Else      Set exit flag      Set exiting reason to terminal read failure reason      Wake the mainline call SYS$WAKE   EndifEndif/***** ft_echo_ast**** Function: This routine is called if a write to the pseudoterminal used** an ECHO buffer.  If any data was echoed, the output is written to the** terminal.  If no data was echoed, the I/O buffer is freed so it can be** used later. If the program is exiting, this routine exits.***/If (not exiting) Then   If (ECHO buffer has data) Then      Write the buffer to the terminal with ASTADR = terminal_output_ast      If (error setting up write) Then         Set exit flag         Set exiting reason to write failure reason         Wake mainline call SYS$WAKE      Endif   Else      Free I/O buffer call free_io_buffers   EndifEndif/*** free_io_buffers**** Function: This routine places a free I/O buffer on the queue of available** I/O buffers. It also restarts any stopped read operations from the** pseudoterminals.  This routine disables AST delivery while it is running** in order to synchronize reading and resetting the read stopped flag.***/If (not exiting) Then   Disable AST deliver using SYS$SETAST   If (Pseudoterminal reads not stopped) Then      Insert I/O buffer on the interlocked queue of free I/O buffers   Else      Call PTD$READ to restart reads from the pseudoterminal.                   ASTADR = ft_read_ast                   ASTPRM = buffer address                   READBUF = I/O buffer + 8                   READBUF_LEN = 500      If (no error starting read) Then         Clear read stopped flag      Else         Set exit flag         Set exit reason to read setup reason      Endif  Endif  Enable AST delivery using SYS$SETASTEndif/***** allocate_io_buffer**** Function: This routine obtains a free I/O buffer from the queue of** available I/O buffers.  If the program is exiting, this routine** returns an SS$_FORCEDEXIT error.***/If (not exiting) Then   remove a I/O buffer from the interlocked queue of I/O buffers   If (queue empty) Then      exit with reason LIB$_QUEWASEMPelse   exit with reason SS$_FORCEDEXITEndif/*** subprocess_exit**** Function: This routine is called when the subprocess has completed** and exited.  This routine checks whether the program is already exiting.** If not, then the routine indicates that the program is exiting and wakes** up the main program.***/If (not exiting) Then   indicate subprocess no longer running   set exit status to SS$_NORMAL   indicate exiting   call SYS$WAKE to start up main loopEndif/*** xon_ast**** Function: This routine is called for the pseudoterminal driver to signal** that it is ready to accept keyboard input. The routine attempts to send** an XON character to the terminal by sending XON DC1 using SYS$QIO.** If the attempt fails, it is not retried.***/If (not exiting) Then   call SYS$QIO to send a <DC1> character to the terminalEndif/*** bell_ast**** Function: This routine is called when the pseudoterminal driver wants** to warn the user to stop sending keyboard data.  The routine attempts** to ring the terminal bell by sending the BELL character to the terminal** using SYS$QIO.  If the attempt fails, it is not retried.***/If (not exiting) Then   call SYS$QIO to send a <BELL> character to the terminalEndif/*** xoff_ast**** Function: This routine is called when the pseudoterminal driver wants to** signal that it will stop accepting  keyboard input. The routine attempts** to send an XOFF character to the terminal by sending XOFF DC3 to the** terminal using SYS$QIO.  If the attempt fails, it is not retried.***/If (not exiting) Then   call SYS$QIO to send a <DC3> character to the terminalEndif/*** set_line_ast**** Function: This routine is called when the pseudoterminal device** characteristics  change.  The routine reads the current pseudoterminal** characteristics, changes the characteristics to set PASTHRU and NOECHO,** and applies the characteristics to the input terminal.  If the attempt** to alter the terminal characteristics fails, it is not retried.***/If (not exiting) Then   call SYS$QIOW to read the pseudoterminals characteristics   If (not error) Then      Set the alter the just read characteristics to have PASTHRU and NOECHO      attributes      call SYS$QIO to set the terminal characteristics.   EndifEndif


Chapter 7
Shadow-Set Virtual Unit Driver

This chapter provides an overview of Volume Shadowing for OpenVMS anddescribes the use of the shadow-set virtual unit driver (SHDRIVER).

7.1 Introduction

Volume Shadowing for OpenVMS ensures that data is available forapplications and end users by duplicating data on multiple disks.Because the same data is recorded on multiple disk volumes, if one diskfails, the remaining disk or disks can continue to service I/Orequests. This ability to shadow disk volumes is sometimes referred toas disk mirroring.

Volume shadowing supports the clusterwide shadowing of DIGITAL SCSI andDSA storage systems. Volume shadowing also supports shadowing of allmass storage control protocol (MSCP) served DSA disks and DIGITAL SCSIdisks. For more information about Volume Shadowing supported devices,refer to the Volume Shadowing for OpenVMS Software ProductDescription.

You can mount one, two or three compatible disk volumes, including thesystem disk, to form a shadow set. Each disk in theshadow set is known as a shadow set member. VolumeShadowing for OpenVMS logically binds the shadow set devices togetherand represents them as a single virtual device called a virtualunit. This means that multiple members of the shadow set,represented by the virtual unit, appear to applications and users as asingle, highly available disk.

Volume Shadowing features include:

  • Controller independence. Shadow set members can be located on any node in a VAXcluster system that has Volume Shadowing enabled.
  • Clusterwide, homogeneous shadow-set maintenance functions.
  • Ability to survive controller, disk, and media failures transparently.
  • Shadowing functions that do not affect application I/O.

Applications and users read and write data to and from a shadow setusing the same commands and program language syntax and semantics thatare used for nonshadowed I/O operations. Volume shadowed sets aremanaged and monitored using the same commands and utilities that areused for nonshadowed disks. The only difference is that access isthrough the virtual unit, not to individual devices.

SHDRIVER, the driver that controls the virtual unit functions, isdescribed in Section 7.3.

For more detailed information on Volume Shadowing for OpenVMS, refer tothe Volume Shadowing for OpenVMS manual.

7.2 Configurations

Volume Shadowing for OpenVMS does not depend on specific hardware inorder to operate. All shadowing functions can be performed on VAX andAlpha systems running the OpenVMS operating system. Shadow set membersmust have the same physical geometry (that is, the same number ofidentical logical blocks [LBNs]) and members can be located anywhere ina VAXcluster system.

7.2.1 Supported Hardware

Volume Shadowing for OpenVMS does not depend on specific hardware tooperate. All shadowing functions can be performed on any type of VAX orAlpha system using the OpenVMS operating system. Volume shadowingrequires a minimum of one VAX computer, one mass storage controller,and DSA (DIGITIAL Storage Architecture) or Small Computer SystemInterface (SCSI) disk drives.

Refer to the most recent Volume Shadowing for OpenVMS SoftwareProduct Descriptions (SPD 27.29.xx) for additionalinformation about hardware requirements.

7.2.2 Compatible Disk Drives and Volumes

Volume shadowing requires compatibility among the physical units (diskdrives and volumes) that form a shadow set. For example:

  • Units must have the same geometry, including the same number of sectors per track, the same number of tracks per cylinder, and the same number of cylinders per volume.
  • Units must be Files-11 On-Disk Structure Level 2 (ODS-2) data disks.
  • Units and controllers must conform to DSA and OpenVMS MSCP, or must be SCSI compliant.
  • Units should not have hardware write protection enabled. Hardware writeprotection stops the volume shadowing software from maintainingidentical volumes. However, the shadow set virtual unit may be mountedsoftware write-locked with the /NOWRITE qualifier to MOUNT.

7.3 Driver Functions

This section describes the major virtual unit functions supported bySHDRIVER. In addition to the virtual unit functions described in thissection, SHDRIVER supports all OpenVMS disk functions. SHDRIVERreceives QIO operations from application programs and is a client ofthe disk class drivers DUDRIVER. Applications access the shadow set asthey would access a standard OpenVMS disk.

Table 7-1 summarizes the major SHDRIVER functions.

Important Note

The MOUNTSHAD, ADDSHADMBR, COPYSHAD, and REMSHADMBR functions arereserved for Compaq internal use. Use of these functions by customer orthird-party provided software may cause unpredictable results includingsystem crashes and data corruption.

Table 7-1 Functions of the Shadow Set Virtual Unit Driver
Function Description
MOUNTSHAD Creates a virtual unit
ADDSHAD Evaluates a physical member and adds members
COPYSHAD Triggers and controls copy operations
REMSHAD Removes a physical member
AVAILABLE Virtual unit dissolution
SENSECHAR Verifies shadow set status
READ Directs I/O to a physical member
WRITE Propagates a write operation to all physical members

7.3.1 Read and Write Functions

With minor changes, the read and write functions for SHDRIVER operatethe same as for the disk class driver (see Sections 2.4.1 and2.4.2).

During an SHDRIVER read operation, the host directs the read to themember volume with the shortest path.

During a write operation, SHDRIVER directs the write to each member volume. The write operations for each member volume usually proceed in parallel; the virtual unit write operation terminates when all writes have completed. The write function for SHDRIVER takes the IO$M_VUEX_FC function modifier; this modifier should not be used by application programs.

The read and write SHDRIVER functions, as well as all user functions, are issued by user programs. All other SHDRIVER functions are invoked by MOUNT and DISMOUNT commands, or the $MOUNT and $DISMOUNT system services.

Remember that volume shadowing provides data availability by protecting against hardware problems or communication path problems that might cause a disk volume to be a single point of failure. If a write request is made to a shadow set, but the system fails before a completion status is returned from all of the shadow set members, it is possible that:

  • All members might contain the new data.
  • All members might contain the old data.
  • Some members might contain new data and others might contain old data.

When the system recovers, volume shadowing performs a merge or copy operation to ensure that the corresponding blocks on each shadow set member contain the same data (right or wrong). Therefore, the goal here is not one of data correctness but of data availability. Volume shadowing is designed to make the data on all disks identical, then, if necessary, incorrect data can be reconciled either by the user reentering the data or by an application automatically employing database or journaling techniques.

For example, when used with volume shadowing, OpenVMS RMS journaling allows you to develop applications that can automatically recover from failures such as:

  • Permanent loss of the path between a CPU data buffer containing the data being written and the disk being written to during a multiple block I/O operation. Communication path loss can occur due to node failure or a failure of node-to-node communications.
  • Failure of a CPU (such as a system crash, halt, power failure, or system shutdown) during a multiple block write I/O operation.
  • Mistaken deletion of a file.
  • Corruption of file system pointers.
  • OpenVMS RMS file corruption due to a software error or incomplete bucket write operation to an indexed file.
  • Cancellation of an in-progress multiple block write operation.

Refer to the Volume Shadowing for OpenVMS manual for more information about shadowingmerge and copy operations.


Previous Next Contents Index