[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Programming Concepts Manual


Previous Contents Index

30.7.1.2 Locking Between Processes

A transaction may access an RM from more than one process. The XA Veneer creates a separate branch of the transaction for each process. This requests the RM to treat each process as a loosely coupled thread as defined by the XA specification. The RM takes locks to isolate access to a resource in one process from access in another process. Consequently, the processes may deadlock against each other if they attempt to access the same resource within a single transaction.

30.7.1.3 Binding to the XA Interface

Before a resource manager can take part in transaction processing, it must be bound to the XA interface. The XA interface requires the following:

  • The address of the XA Switch data structure for the resource manager. See the resource manager documentation for the symbolic name of this switch.
  • The xa_info text strings for xa_open() and xa_close(). See the resource manager documentation for the specification of these strings.
  • An optional name for the resource manager instance. (See Section 30.7.1.3.3.) The maximum length of the name is 24 characters, excluding the null terminator.

DECdtm supports the following methods of binding:

  • Static binding is the method implied by the XA standard. The address of the XA Switch and the xa_info text strings are determined at link time.
  • Dynamic binding requires a run-time call to a nonstandard function. This method gives the application control over the time at which binding and recovery is performed.

You can find definitions of the data structures and constants required to use the XA interface in SYS$LIBRARY:XA.H. This is the "xa.h" as listed in the XA specification. Additional nonstandard functions and flags are defined in SYS$LIBRARY:DDTM_XA.H.

To use an XA compliant RM, you must link the application with the following:

  • The RM's shareable image or object files.
  • SYS$LIBRARY:DDTM$XA_RM.OBJ. This object module contains a table of well-known resource managers and initialization code to load the XA Veneer.
  • SYS$LIBRARY:DDTM$XA.EXE. This shareable image implements the XA Veneer.

You can also link an application against SYS$LIBRARY:DDTM$TX.OBJ to use the TX transaction demarcation interface instead of DECdtm system service calls.

You must install the privileged shareable image SYS$LIBRARY:DDTM$XA_SS.EXE. It provides system services for internal use by the XA interface.

30.7.1.3.1 Static Binding

You bind resource managers by creating and linking a small object module. The object module places references to the XA Switch and xa_info string in the predefined PSECT DDTM$AX_RM. Consider the following HP C sample:


  /* TODO: define or reference your RM switch */
    extern struct xa_switch_t   SampleSwitch;

    /* TODO: define the info strings for xa_open() and xa_close() */
    static char RmInfoOpen[] = "SampleInfoOpen";
    static char RmInfoClose[] = "SampleInfoClose";

    /* TODO: define the RM instance name */
    static char RmName[] = "SampleName";

    /* put the switch and info addresses in the DDTM$AX_RM psect */
    #pragma extern_model strict_refdef "DDTM$AX_RM" pic, shr

    void* RmDefSample[] = {&RmSwitchSample,
                           RmInfoOpen, RmInfoClose, RmName};

To bind the resource manager, make the following changes to the sample file:

  1. Change "SampleSwitch" to the symbolic name of the XA switch structure as given in the documentation for your RM.
  2. Change "SampleInfoOpen" and "SampleInfoClose" to xa_info strings as given in the documentation for your RM. Typically, the xa_open string will specify a database name and access information, and the xa_close string may be null.
  3. Change "SampleName" to a resource manager instance name that you choose, as described in Section 30.7.1.3.3.

If you prefer to code the RM definition in another language, such as VAX MACRO, note the full attributes of the PSECT as follows:


    .PSECT DDTM$AX_RM,CON,GBL,SHR,NOEXE,WRT,NOCOM,4

To make the xa_info strings configurable, the XA Veneer attempts to translate the strings in the SYS$DECDTM_XA_RM logical name table. If the strings cannot be translated, they are passed unchanged to the resource manager.

When you use static binding, the XA Veneer calls xa_recover() either when tx_open() is called or at the start of the first transaction in the image lifetime.

You can use ax_close_decdtm() to close statically bound resource managers.

30.7.1.3.2 Dynamic Binding

An application program can bind additional RMs to the XA Veneer by calling ax_bind_decdtm_2(). Dynamic binding requests the XA Veneer to call xa_recover(), which allows recovery to be initiated earlier than with static binding.

Note that ax_open_decdtm() and ax_close_decdtm() have no effect on dynamically bound resource managers.

30.7.1.3.3 Resource Manager Instances

You must specify the resource manager instance name if the resource manager implements multiple instances (or databases) that may be recovered independently. You cannot bind a resource manager into a single process multiple times, unless each binding is for a different named instance.

You must also specify a resource manager instance name if the resource manager instance name in the XA Switch structure is longer than 24 characters. Otherwise, if the resource manager does not support multiple instances, the instance name may be set null, and DECdtm uses the resource manager name in the XA Switch structure as the instance name.

The definition of resource manager instances controls the following features of the XA Veneer:

  • When DECdtm calls xa_recover(), it expects that the resource manager instance returns the complete list of prepared transaction branches for the instance. DECdtm will forget any transactions for the instance that are not returned by xa_recover().
  • If a process or OpenVMS Cluster node using the XA Veneer fails, DECdtm initiates recovery in any one of the surviving processes in the cluster that are bound to the resource manager instance.

When you choose the instance name, you must set it identically in all processes. It has a maximum size of 24 characters (excluding the null terminator). HP recommends that the first part of the name is the same as the resource manager name in the XA Switch structure, provided that this is possible within the overall limit of 24 characters.

You can bind a maximum of 1024 resource manager instances in a process.

In this manual, the term "resource manager instance" is used in the same sense as "Oracle Instance" in the Oracle documentation. In the HP OpenVMS System Services Reference Manual, the DECdtm services descriptions use the same term in a different context and with a different meaning.

30.7.1.3.4 Hints

You may find the following hints to be of help:

  • Check any OpenVMS documentation for your resource manager as well as the generic documentation. For example, the generic documentation for Oracle suggests that you may need to specify an explicit shared library for the Oracle XA RM. However, on OpenVMS no specific action is needed; a reference to the Oracle XA switch structure is sufficient.
  • To use XA transactions with Oracle 8i on OpenVMS, you must install the Oracle DDBOPT product (Distributed Database Option), and you must enable the Distributed Database Option in the configuration options for the Oracle RDBMS product.

30.7.1.4 Implementation Characteristics

This section provides information for developers of XA-compliant RMs that are to be used with the DECdtm XA Veneer.

The DECdtm XA Veneer does not use some features of the XA interface that must normally be provided by resource managers. This information is provided for the convenience of RM developers, to help them decide if an existing implementation is likely to work with DECdtm. Future implementations of DECdtm XA may make use of these features.

This section also describes possible deviations from the XA standard or common interpretations of the standard.

30.7.1.4.1 Threads

DECdtm does not support DECthreads or POSIX p-threads. That is, the default transaction is managed per process, not per thread. When reading the XA specification, you must regard a thread as equivalent to a process.

The Veneer assumes there is a single default transaction per process and does not attempt to suspend or migrate the association of a transaction branch with a thread or process. Thus, it never sets the TMSUSPEND or TMMIGRATE flags on a call to xa_end(), and never sets TMRESUME on a call to xa_start().

The Veneer never sets the TMJOIN flag on a call to xa_start().

30.7.1.4.2 Heuristic Decision

DECdtm does not support heuristic decisions. If the RM reports a heuristic decision on xa_commit() or xa_rollback(), the Veneer records the decision in a log file. The xa_forget() function is called immediately and the transaction is treated as if it committed or aborted normally.

30.7.1.4.3 Resource Manager Synchronization

The XA Veneer always calls XA functions at non-AST level in user mode. The Veneer never interrupts an XA call with another XA call.

The Veneer may interrupt application processing to call the following functions:

  • xa_recover()
  • xa_commit() or xa_rollback() for a transaction listed by xa_recover()

However, such calls are not made while the process has an active transaction, that is, between xa_start() and xa_end(). Therefore, they cannot interrupt the RM while it is executing a call from the application.

TP frameworks, implemented using the earliest version of the DECdtm interface, may run application code in concurrent DECdtm unsynchronized branches. This is not recommended (see the OpenVMS DECdtm Services Reference Manual), partly because the Veneer cannot determine when branch processing ends, and may therefore make xa_end() and xa_rollback() calls asynchronously while an XA RM is processing a call from the application. This occurs only when a transaction is aborted by another DECdtm branch. This problem does not occur with ACMS, because ACMS executes branches serially, not concurrently.

If the version of the TP framework in use does not make a clear statement that synchronized branches are used, and transactions have multiple branches, HP recommends that applications protect XA RM calls against asynchronous events using the nonstandard functions ax_lock_decdtm() and ax_unlock_decdtm(). The Veneer may be locked at the start of branch processing and unlocked at the end, or individual RM calls may be protected by paired lock/unlock calls.

30.7.1.4.4 Asynchronous Operation

This implementation does not use asynchronous operations.

The RM Switch flag TMUSEASYNC is ignored. The TMASYNC flag is never set on calls to the resource manager. The xa_complete() function is never called.

30.7.1.4.5 Resource Manager Switch

An RM can ensure that a future version of the Veneer preserves restrictions and possible nonstandard behavior by setting the nonstandard flag TM_DDTM_V1 in the flags field of the XA Switch data structure.

30.7.1.4.6 Image Termination and Recovery

No XA functions are called directly when an image or process terminates.

The RM is dissociated from any active transaction, and the transaction is aborted.

After an image terminates, a process terminates, or a cluster node fails, DECdtm calls xa_recover() on any one of the surviving processes in the cluster that is bound to the same resource manager instance.

30.7.1.4.7 Transaction Branch Identification

In this implementation, formatID is set to 223585243, gtrid_length is 16 and bqual_length is 36. However, RMs should not make assumptions about the values of these fields.

30.7.1.4.8 Error Handling

In most cases, the return values XAER_INVAL and XAER_PROTO are treated as failures of the XA Veneer. An SS$_BUGCHECK exception is reported. See xa_close() and xa_open() in Section 30.7.1.4.9 for exceptions.

In most cases, XAER_RMERR and XAER_RMFAIL have a common interpretation by the Veneer. The current transaction is aborted, but the RM continues to participate in new transactions. The error return values differ only in that they cause different DECdtm reason codes to be returned to the application. See xa_commit() below for an exception.

30.7.1.4.9 XA Functions

ax_reg() A return value of TMER_INVAL indicates that either arguments are invalid or the TMREGISTER flag in the resource manager's xa_switch_t data structure was not set.

A successful call that returns a NULLXID blocks the AP from starting a new default transaction. Other RMs that register through the same thread also receive a success status with a NULLXID.

A call to ax_reg() made while registered fails with XAER_PROTO. TM_JOIN is never returned.

A return value of TMER_PROTO may also indicate that xa_reg() was called while there was a current transaction, but called too late to join it.

ax_unreg() There is no additional information for this function.
xa_close() This function is called for the following reasons:
  • For all statically bound resource managers, when ax_close_decdtm() is called.
  • For a dynamically bound resource manager, when ax_unbind_decdtm() is called.
  • In unusual error cases, typically after an unexpected status is returned by the RM.

This function is not called on image exit or process exit.

The return value XAER_INVAL is assumed to be an invalid rm_info string, not a Veneer failure.

xa_commit() DECdtm does not use the TMNOWAIT flag.

The return value XAER_RMERR is treated as a catastrophic failure of the resource manager. The error is logged and the Veneer fails with a SS$_BUGCHECK exception to prevent further processing.

The return value XAER_RMFAIL is treated as a less severe error. The error is logged. It is assumed that the resource manager will continue to fail all new transactions with XAER_RMFAIL, but that it may eventually be possible to commit the transaction on recovery.

The Veneer attempts to retry xa_commit() when XAER_RETRY is returned. It retries the operation at 10-second intervals for up to 2 minutes.

xa_complete() The Veneer never calls this function.
xa_end() DECdtm does not use the TMSUSPEND or TMMIGRATE flags.
xa_forget() DECdtm does not support heuristic decisions. It calls xa_forget() immediately after an RM reports a heuristic decision.

Error return values are recorded in the Veneer error log, but are otherwise ignored.

xa_open() Any error return leaves the RM unregistered. The error is recorded in the Veneer error log.

The return value XAER_INVAL is assumed to be an invalid rm_info string, not a Veneer failure.

xa_prepare() There is no additional information for this function.
xa_recover() DECdtm calls xa_recover() for the following reasons:
  • When it receives an ax_bind_decdtm_2() call with the DDTM_M_RECOVER flag set.
  • At the start of the first transaction in the image lifetime, if the resource manager is statically bound to DECdtm.
  • When an image that has performed a transaction using XA Veneer terminates, and other processes are still using the XA Veneer.
  • When the resource manager returns from an xa_recover() call with a value equal to count.

DECdtm never sets TMENDRSCAN. Thus, it always performs full scans for prepared transaction branches.

DECdtm expects that the RM returns the complete list of prepared transactions started on the current node of the OpenVMS Cluster for an RM instance. Any other transactions that the RM has forgotten will be forgotten by DECdtm. The RM may also return prepared transactions started on other nodes, and these will be resolved.

xa_rollback() There is no additional information for this function.
xa_start() DECdtm does not use the TMNOWAIT flag.

DECdtm does not use the TMJOIN or TMRESUME flags.

The return value XAER_DUPID is not expected, because DECdtm calls each resource manager once only for each transaction. It causes the Veneer to report an SS$_BUGCHECK exception.

The current DECdtm implementation is unable to return an error from $START_TRANS when the RM returns an error. Instead, the Veneer raises an SS$_ABORT exception, which the application may dismiss. The application should call $END_TRANS or $ABORT_TRANS. The transaction will be aborted in either case. $END_TRANS returns.

30.7.1.5 Recovery Processes

By default, the XA Veneer calls xa_recover in any process that has bound an RM instance. This is undesirable if the process called to perform recovery runs at low priority or executes an application that may be blocked for link periods with an active transaction. It is especially undesirable if the process uses a resource manager such as Oracle that waits during an active transaction if it finds data that needs recovery.

It is therefore preferable to create one or more processes that are available to perform recovery but which do not execute transactions. You can do this in the following way:

  1. Define the logical name SYS$DECDTM_XA_RECOVER as "FALSE" or "F" for all processes that may execute transactions. This will prevent xa_recover from being called in those processes. The logical name may be defined group or system wide.
  2. Create a recovery process that binds all XA RMs and has the logical name SYS$DECDTM_XA_RECOVER defined as "TRUE" or "T". This will prevent the process from joining active XA transactions.
  3. Ensure that one or more instances of the recovery process are started before starting any application processes.

The executable code of the process is provided by the module SYS$LIBRARY:DDTM$XA_RECOVERY.OBJ. Alternatively, you can create a custom process using the following code as a starting point:


    #define DESC_INIT_S(p1, p2, p3)       \
        (p1).dsc$w_length = p2,           \
        (p1).dsc$b_dtype = DSC$K_DTYPE_T, \
        (p1).dsc$b_class = DSC$K_CLASS_S, \
        (p1).dsc$a_pointer = (char *) (p3)
    main() {

        int             status;
        struct dsc$descriptor  dscName;
        struct dsc$descriptor  dscValue;

        /* enable recovery in this process */
        DESC_INIT_S(dscName, strlen("SYS$DECDTM_XA_RECOVER"),
                             "SYS$DECDTM_XA_RECOVER");
        DESC_INIT_S(dscValue, 1, "T");
        status = lib$set_logical(&dscName, &dscValue);
        if ((status & 1) != 1) {
            printf("Failed to define logical name, status %d\n", status);
            exit(EXIT_FAILURE);
        }

        /* open XA RMs */
        status = ax_open_decdtm();
        if (status != TX_OK) {
               printf("Error %d on ax_open_decdtm\n", status);
           exit(EXIT_FAILURE);
        }

        /* wait for recovery requests */
        while (1)
            sys$hiber();
    }

To link the process, include the following object modules and libraries:

  • SYS$LIBRARY:DDTM$XA_RECOVERY.OBJ, or the code shown previously.
  • An object module binding each RM to the XA Veneer, as described in Section 30.7.1.3.1.
  • Shareable images or object files for each XA RM.
  • SYS$LIBRARY:DDTM$XA_RM.OBJ.
  • SYS$LIBRARY:DDTM$XA.EXE / SHARABLE.

To restore the default behavior (process joins active transactions and may perform recovery) when SYS$DECDTM_XA_RECOVER has been defined as a group or systemwide logical, define SYS$DECDTM_XA_RECOVER as 0 (zero) for the process.

30.7.1.6 Error Logging

The DECdtm XA log file records heuristic decisions and other serious errors that may impact transaction consistency. Typically, these occur on xa_commit() or xa_rollback(), or during recovery. Less serious errors, such as on xa_prepare, are not logged.

To enable logging, define the logical name SYS$DECDTM_XA_LOG to specify a log file. You can define the logical name processwide, groupwide or systemwide. The log file is created automatically and is shared between processes.

Each record on the log file has the following format:


  tid, bid, time, error_name, rm_name, [reserved], additional_information

Error names are fixed-length 8-character strings with space padding as shown in Table 30-3.

Table 30-3 XA Veneer Error Names
Error Name Meaning
GETDTI DECdtm was unable to resolve the transaction state.
HEURCOM The transaction branch has been heuristically committed.
HEURHAZ The transaction branch may have been heuristically completed.
HEURMIX The transaction branch has been heuristically committed and rolled back.
HEURRB The transaction branch has been heuristically rolled back.
INVAL Invalid arguments were specified to xa_open. Probably the rm_info string is incorrect.
RMERR Catastrophic RM failure on xa_commit().
RMFAIL An error occurred that makes the resource manager unavailable.
UNKNOWN Unexpected return code from the RM.

30.7.1.7 Tracing

The XA Veneer includes a trace facility to help investigate problems of interaction between DECdtm and XA resource managers. The trace file shows the sequence of operations. It also shows more detailed error information than that revealed by XA return values.

To enable tracing, define the logical name SYS$DECDTM_XA_TRACE to specify a trace file. You can define the logical name processwide, groupwide or systemwide. The trace file is created automatically and is shared between processes.

The trace file records the following information:

  • All ax_ calls from the application and the resource managers.
  • All xa_ calls to the resource managers.
  • XA and OpenVMS error status results returned by the above functions. If no status return is included in the trace, success can be assumed.
  • DECdtm events and their corresponding acknowledgements.

Trace records have the following formats:

Record Type Format
Operation time csid pid operation [rmid]
Status time csid pid xa_status ["VMS" vms_status] [extra_info]


Previous Next Contents Index