Chapter 5: Open Transactions

This chapter describes VERSANT support of open transactions and VERSANT support of the X/Open model of open transactions.

 

Open Transaction Concepts and Usage

 

Overview

An open transaction is a transaction controlled by an external process, called a Transaction Manager.

In a VERSANT open transaction, each phase of a commit or rollback to a VERSANT database is controlled explicitly by a non-VERSANT Transaction Manager.

VERSANT system supports a number of different transaction protocol standards, including X/Open and its subset XA, with numerous C/VERSANT functions.

 

VERSANT Transaction Model

The default VERSANT transaction model performs commits using a strict two phase commit protocol. This protocol uses:

•    a transaction manager — a process running on the machine containing the session database,

•    a coordinator transaction log — a log containing coordinator transaction entries which is maintained by the session database,

•    participant transaction logs — a log containing participant transaction entries, which is maintained by each participant database.

Commit and Rollback

The procedures for commits and rollbacks are similar:

1.  The transaction manager sends create, update, and delete information and an "are you ready?" message to the session database and to each connected database. This state is called "Phase 1".

2.  When every database responds that it is ready, the transaction manager sends a "commit" message to all databases and writes to its coordinator transaction log. This is state is called "Phase 2".

3.  Each database performs its part of the commit or rollback, writes to its participant transaction log, and sends a success or failure message to the transaction manager.

4.  If the transaction manger receives a success message from each database, it deletes the transaction entry from its log and sends a message to each participating database to delete its transaction entry.

Recovery

If any database involved in a transaction crashes during a commit or rollback, the transaction entry will remain in the coordinator transaction log. When the crashed database restarts, the following will happen as part of the startup procedure.

1.  The database will ask that the coordinator transaction log be examined.

2.  For each Phase 2 entry in the transaction log, the transaction manager will attempt to finish the commit or rollback.

3.  For each Phase 1 entry, the transaction manager will declare that the transaction involved is a "zombie".

 

Open Transaction Concepts

An open transaction is a transaction controlled by an external process, called a Transaction Manager. In an open transaction, each phase of a commit or rollback to a VERSANT database can be controlled explicitly by a non-VERSANT application.

VERSANT system supports a number of different transaction protocol standards, including X/Open and its subset XA, with numerous C/VERSANT functions.

The flow of control in a generic transaction protocol system is something like the following (details differ from one protocol standard to another).

1.  A Begin_Work() function starts the transaction. It registers the transaction with a Transaction Manager and creates a unique transaction identification number.

2.  The application now invokes Resource Managers, reading and writing from the client machine or from databases, and sending requests to local and remote services.

3.  When the Resource Managers get their first requests from a Transaction Manager, they join the associated transaction, telling the Transaction Manager that they wants to participate.

4.  After the system answers all requests, the transaction calls a Commit_Work() function. This causes the Transaction Manager to begin a two-phase commit protocol. In Phase 1, the Transaction Manager asks all of the Resource Managers that have joined the transaction if they think the transaction is consistent and complete.

5.  If all the Resource Managers respond "yes," the transaction is a correct transformation. The Resource Managers record this fact in their individual transaction logs. The Resource Managers then release the locks on the messages, finish any other necessary functioning, and the transaction is complete.

6.  If any Resource Manager votes "no" the commit fails, causing the Transaction Manager to orchestrate a rollback. The Transaction Manager reads the transaction's log, and for each log record, calls the Resource Manager that wrote the record, asking the Resource Manager to undo the transformation. Once all the undos are finished, the Transaction Manager calls all the Resource Managers that had joined the transaction to tell them that the transaction was aborted.

7.  The Transaction Manager also handles transaction recoveries if a site or node fails. If a site fails, the transaction protocol system restarts all the resource managers. As part of the Transaction Managers' restart code, the Transaction Manager tells Resource Managers the outcome of all transactions that were in progress at the time of the failure. The Resource Manager updates the logs and reconstructs its state.

Typically, each site has its own Transaction Manager. This allows each site to operate independently from each other. If the transaction deals with remote sites during its execution, remote Transaction Managers handle their own part of the process.

VERSANT provides the following functions that support open transactions.

o_beginxact() Start a transaction and assign a transaction identifier.
o_commitp1() Commit phase 1.
o_commitp2() Commit phase 2.
o_deleteZombieList() Delete list of zombie transactions.
o_flush() Flush specified objects.
o_getparticipants() Get databases participating in transaction.
o_getxid() Get transaction identifier.
o_getZombieCount() Get zombie count.
o_getZombieIndex() Get zombie index.
o_getZombieList() Get zombie list.
o_incZombieIndex() Increment zombie index.
o_recover() Get list of zombie transactions.
o_rollback() Rollback transaction.
o_setflushobjects() Set flush options.
o_setxid() Set transaction identifier.
o_setZombieCount() Set zombie count.
o_setZombieIndex() Set zombie index.
o_unsetxid() Remove transaction identifier.
o_xastatetransition() Is XA call consistent.
 

 

VERSANT Support of X/Open

 

X/Open Distributed Transaction Processing Model

The X/Open organization is standards group that has developed a standard dealing with portability, called X/Open Distributed Transaction Processing (X/OpenDTP). This standard defines the concept of Resource Managers and Transaction Managers. Part of this definition is an interface for transaction management and resource management communications. This interface is called XA, and is a library of subroutines that allow Resource Managers to register with local Transaction Managers, Transaction Mangers to invoke Resource Managers at restart, and for transactions to begin, commit and abort.

The X/Open DTP Model as shown in the XA Specification looks something like this:

Please refer to the XA Specification and the X/Open Guide for more information.

The key concept is that the XA and X/Open transaction models open up the two-phase commit process so that each phase can be controlled explicitly by an external Transaction Manager.

 

VERSANT X/Open Support

To allow VERSANT databases to function as a Resource Manager in compliance with the XA Specification, new interface routines have been created. Following are general comments on VERSANT support of X/Open and XA.

Resource Manager Identifier

The Resource Manager Identifier is an integer assigned by the Transaction Manager to uniquely identify the called Resource Manager instance within the thread of control. The Transaction Manager passes the Resource Manager Identifier on calls to XA routines to identify the Resource Manager. This identifier remains constant until the Transaction Manager in this thread closes the Resource Manager.

Transaction Identifier

Since XA allows multiple processes within a server group to share the same transaction, VERSANT provides routines that can associate a Transaction Identifier (XID) to a process. The Transaction Identifier is used to define the scope of the transaction for commits and rollbacks, and to aid record keeping in the event of a recovery operation.

The Resource Manager must be able to map the Transaction Identifier to the recoverable work it did for the corresponding branch. The Resource Manager may perform bitwise comparisons on the data components of an Transaction Identifier for the lengths specified in the Transaction Identifier structure. Most XA routines pass a pointer to the Transaction Identifier. These pointers are valid only for the duration of the call. If the Resource Manager needs to refer to the Transaction Identifier after it returns from the call, it must make a local copy before returning.

The xa.h header defines a public structure called a Transaction Identifier, xid_t, to identify a transaction branch. Resource Managers and Transaction Managers both use the Transaction Identifier structure.

Resource Manager Switch

The Transaction Manager administrator can add or remove a Resource Manager from the Distributed Transaction Processing system by controlling the set of Resource Managers linked to executable modules.

Each Resource Manager must provide a switch that gives the Transaction Manager access to the Resource Manager's XA routines. This lets the administrator change the set of Resource Managers linked with an executable module without having to recompile the application.

A different set of Resource Managers and their switches may be linked into each separate application executable module in the Distributed Transaction Processing system. Several instances of a Resource Manager can share the Resource Manager's switch structure.

A Resource Manager's switch is defined as a structure called xa_switch_t.

Resource Manager Identifier and VERSANT Sessions

There is a one-to-one mapping between Resource Manager Identifiers and VERSANT database sessions. The following shows how to translate a Resource Manager Identifier into a VERSANT session name.

sprintf(sessionName, "XA.Resource Manager Identifier:%0d", rmid);

Based on the assumption that Resource Manager Identifiers are unique, the session names should be unique also.

In the multi-process model, there is not much advantage to have this Resource Manager Identifier to VERSANT session binding. It may be useful, however, in the multi-thread model.

Transaction Identifiers and VERSANT Transactions

Internal transactions are created whenever a new external transaction is initiated, except for the first external transaction, which will attach to the transaction started when you begin a session.

When an external transaction terminates, all transaction states will be removed from the client even if there are objects in the cache. With this change, you must still be in a database session to be in a transaction, but you can now be in a session but not in a transaction. In the standard VERSANT transaction model, once a session started, you were always in a transaction.

To allow you to associate an external transaction with a VERSANT transaction, use the set transaction function, o_setxid(). Once the association is done, the VERSANT transaction will be considered an external transaction, and it will give up its role as a coordinator on deciding how to terminate the transaction. In other words, it will become passive and wait for an external request before recovering zombie transactions.

Only one VERSANT transaction is allowed to associate with an external transaction. If the server find that the external transaction with the given Transaction Identifier is already associated with a VERSANT transaction, the VERSANT server will return the VERSANT transaction to the client. This allows an external transaction to attach to a VERSANT transaction multiple times providing that they are serialized (i.e., no more than one attachment at any instance).

To avoid inconsistencies, every external transaction will be allowed to use only one front end cache at all times.

Recovery

If there is an external Transaction Manager, the VERSANT transaction manager will not terminate a transaction from a coordinator transaction entry when it is in the zombie state. Instead, it will rely on the external Transaction Manager's decision. There is be no change in any other states.

 

Structures and Functions that Support X/Open

The following VERSANT structures and functions directly support X/Open transaction. They are available when you include the header file xa.h.

Data Structures

 

vsnt_xa_switch_t An instance of xa_switch_t that maps XA functions to VERSANT functions.
xa_switch_t Information about function mapping.
xid_t Information about a transaction.
   

Functions

 

vsnt_xa_close() Close a Resource Manager.
vsnt_xa_commit() Commit a transaction.
vsnt_xa_complete() Complete asynchronous operation.
vsnt_xa_end() Notify when a thread of control ends.
vsnt_xa_forget() Remove external transaction entry.
vsnt_xa_open() Open a Resource Manager.
vsnt_xa_prepare() Prepare for a commit.
vsnt_xa_recover() Get list of prepared transactions.
vsnt_xa_rollback() Rollback transactoin.
vsnt_xa_start() Notify when application is ready.
   

XA/VERSANT mapping

 

vsnt_xa_open xa_open()
vsnt_xa_close xa_close()
vsnt_xa_start xa_start()
vsnt_xa_end xa_end()
vsnt_xa_rollback xa_rollback()
vsnt_xa_prepare xa_prepare()
vsnt_xa_commit xa_commit()
vsnt_xa_recover xa_recover()
vsnt_xa_forget xa_forget()
vsnt_xa_complete xa_complete()
   
 
NOTE — The VERSANT routines that support the X/Open Distributed Transaction Process (DTP) Model should not be used in conjunction with the standard VERSANT commit routines, such as o_xact() and o_xactwithvstr(). In other words, the XA open transaction model is incompatible with the VERSANT standard transaction model

 

Reference to VERSANT Open Transaction Functions

 

Functions

Following are C/VERSANT functions that support open transactions in general.

 

o_beginxact()

o_err o_beginxact(

o_xidhandle   xid,
o_xacthandle* xact,
o_u4b         flags);

Start a VERSANT transaction, associate the external transaction identified in the xid parameter with it, and set xact to the handle representing the VERSANT transaction.

Parameters:

xid

A pointer to the external Transaction Identifier.

xact

A pointer to the VERSANT transaction.

flags

Reserved for future use.

 

o_commitp1()

o_err o_commitp1(o_xidhandle xid, o_u4b flags);

Perform a Phase 1 commit on the current VERSANT transaction.

If o_commitp1() is called without first calling o_flush(), all dirty objects in the entire cache will be flushed. However, if o_commitp1() is called from a different process, you will be responsible for flushing the objects from the other caches.

Parameters:

xid

A pointer to the Transaction Identifier.

flags

Reserved for future use.

 

o_commitp2()

o_err o_commitp2(o_xidhandle xid, o_u4b flags);

Perform a Phase 2 commit on the current VERSANT transaction.

Parameters:

xid

A pointer to the Transaction Identifier.

flags

Options.

In this release, the only valid flag is:

O_COMMIT_ONE_PHASE

If O_COMMIT_ONE_PHASE is passed to o_commitp2() without calling o_flush(), all dirty objects in the entire cache will be flushed.

However, if this function is called with O_COMMIT_ONE_PHASE by a different process, you will be responsible for flushing the objects from the other caches.

 

o_deleteZombieList()

o_err o_deleteZombieList();

Delete the vstr of zombie transaction identifiers and clear all counts and indexes associated with it.

 

o_flush()

o_err o_flush(o_vstr *failed_objects);

Flush specified dirty objects to their database(s).

•    This function should always be used in conjunction with the o_getflushobjects() function.

Parameters:

failed_objects

The argument failed_objects, returns the list of objects that fail. Currently, it is only used for optimistic locking sessions to return objects that fail the time stamp validation.

 

o_getparticipants()

o_err o_getparticipants(

o_xidhandle xid,
o_list*     participants,
o_u4b       options);

Get a list of all databases that are participating in the external transaction associated with the Transaction Identifier xid.

Parameters:

xid

A pointer to the external Transaction Identifier.

particpants

The returned list of databases involved in the transaction.

options

If set to O_GETPARTS_INITIALIZE, then this function will recalculate the participants list; otherwise it will reuse the participants list that was calculated in a previous call to this function.

 

o_getxid()

o_err o_getxid(o_xidhandle *xid, o_u4b flags)

This function is used exclusively by XA to get the Transaction Identifier of the current VERSANT transaction.

The association between the external and VERSANT transaction is established on the client as well as the server side.

Parameters:

xid

A pointer to the Transaction Identifier.

flags

A transaction option.

Valid flags are:

O_XID_COMPARE

If the Transaction Identifier passed in is not the same as the Transaction Identifier for the current transaction, error OM_TR_INVALID_XID is returned.

 O_XID_RETRIEVE

Retrieves the Transaction Identifier for the current transaction and places it in the xid parameter.

 

o_getZombieCount()

o_u4b o_getZombieCount();

Get the number of zombie transactions.

 

o_getZombieIndex()

o_u4b o_getZombieIndex();

Get the zombie index, which refers to the next xid in the vstr of zombie transactions that has not yet been returned to the user.

 

o_getZombieList()

o_vstr *o_getZombieList();

Get a vstr containing the Transaction Identifiers of all zombie transactions. This list is intialized by the o_recover() function.

See also o_recover().

 

o_incZombieIndex()

o_u4b o_incZombieIndex();

Increment the zombie index and return its new value.

 

o_recover()

o_err o_recover(o_vstr *xids);

Get a list of transactions that are currently in Phase 1 commit (zombie) state.

The transactions list will be returned to specified vstr of Transaction Identifiers. You are then responsible for releasing this vstr when you are done.

 

o_rollback()

o_err o_rollback(o_xidhandle xid, o_u4b flags);

Roll back the work performed in the current VERSANT transaction.

Parameters:

xid

A pointer to the Transaction Identifier.

flags

Reserved for future use.

 

o_setflushobjects()

o_err o_setflushobjects(o_vstr objects, o_u4b options);

Register the flush options.

•    This function should always be used in conjunction with the o_flush() function.

Parameters:

objects

Contains the dirty objects that are to be flushed. If it is NULL, all dirty objects in the cache will be flushed.

options

Options.

Valid options are:

O_FLUSH_RETAIN_OBJECT
O_FLUSH_RETAIN_SCHEMA_OBJECT
O_FLUSH_CLEAN_CODS

The options will be stored in the per session per thread (seps) structure. The O_FLUSH_RETAIN_OBJECT and O_FLUSH_CLEAN_CODS options apply to the given objects if it is not NULL; otherwise, they apply to the entire cache.

When there are retained locks at the end of a VERSANT transaction, the next external transaction will also associate with this VERSANT transaction in order to inherit its locks. This support is limited to a single cache (process) model.

 

o_setxid()

o_err o_setxid(o_xidhandle xid, o_4b size, o_u4b flags)

This function is used exclusively by XA to set the Transaction Identifier to the current VERSANT transaction. The association between the external and VERSANT transaction is established on the client as well as the server side.

Parameter:

xid

A pointer to the Transaction Identifier.

size

The size of the structure pointed to by Transaction Identifier.

flags

Options.

Valid flags are:

O_XID_IGNORE_COUNT
O_EXTERNAL_FORGET_XACT
O_EXTERNAL_END_XACT

 

o_setZombieCount()

void o_setZombieCount();

Set the zombie count, an internal data variable, to the number of xids in the vstr of zombie transactions.

 

o_setZombieIndex()

void o_setZombieIndex(o_u4b count);

Set the zombie index, an internal data variable pointing to the next xid in the vstr of zombie transaction that has not yet been processed, to the value of count, where count is the number of zombie transactions.

See o_getZombieCount().

 

o_unsetxid()

o_err o_unsetxid(o_xidhandle xid, o_4b size, o_u4b flags)

This function is used exclusively by XA to remove the Transaction Identifier from the current VERSANT transaction. The association between the external and VERSANT transaction is established on the client as well as the server side.

xid

A pointer to the Transaction Identifier.

size

The size of the structure pointed to by the xid parameter.

flags

Options.

Valid flags are:

O_XID_IGNORE_COUNT
O_EXTERNAL_FORGET_XACT
O_EXTERNAL_END_XACT

 

Reference to VERSANT Structures and Functions that Support X/Open

 

Data Structures

 

vsnt_xa_switch_t

The VERSANT X/Open implementation creates and instance of the X/Open structure xa_switch_t named vsnt_xa_switch_t. This structure translates Transaction Manager calls to VERSANT interface functions.

struct xa_switch_t vsnt_xa_switch =
{

"VERSANT-ODBMS",
TMNOFLAGS,
0,
vsnt_xa_open,
vsnt_xa_close,
vsnt_xa_start,
vsnt_xa_end,
vsnt_xa_rollback,
vsnt_xa_prepare,
vsnt_xa_commit,
vsnt_xa_recover,
vsnt_xa_forget,
vsnt_xa_complete
};

Elements are:

VERSANT-ODBMS

Name of Resource Manager.

TMNOFLAGS

Flags for Resource Manager.

0

Version.

vsnt_xa_open

Map to xa_open()

vsnt_xa_close

Map to xa_close()

vsnt_xa_start

Map to xa_start()

vsnt_xa_end

Map to xa_end()

vsnt_xa_rollback

Map to xa_rollback()

vsnt_xa_prepare

Map to xa_prepare()

vsnt_xa_commit

Map to xa_commit()

vsnt_xa_recover

Map to xa_recover()

vsnt_xa_forget

Map to xa_forget()

vsnt_xa_complete

Map to xa_complete()

 

 

xa_switch_t

struct xa_switch_t
{
char    name[Resource ManagerNAMESZ];
long    flags;
long    version;
int     (*xa_open_entry)     (char*, int,  long);
int     (*xa_close_entry)    (char*, int,  long);
int     (*xa_start_entry)    (XID*,  int,  long);
int     (*xa_end_entry)      (XID*,  int,  long);
int     (*xa_rollback_entry) (XID*,  int,  long);
int     (*xa_prepare_entry)  (XID*,  int,  long);
int     (*xa_commit_entry)   (XID*,  int,  long);
int     (*xa_recover_entry)  (XID*,  long, int, long);
int     (*xa_forget_entry)   (XID*,  int,  long);
int     (*xa_complete_entry) (int*,  int*, int, long);
};

Resource Manager switch structure containing information about the Resource Manager.

Elements are:

name[Resource ManagerNAMESZ]

Name of the Resource Manager. The maximum size is 32 bytes.

flags

Options specific to the Resource Manager.

This flag indicates whether the Resource Manager uses dynamic registration, whether the Resource Manager operates asynchronously, and whether the Resource Manager supports the migration of associations. Only the migration of associations is currently be supported.

version

Version information, which must be specified as 0 in this release.

xa_open_entry
xa_close_entry
xa_start_entry
xa_end_entry
xa_rollback_entry
xa_prepare_entry
xa_commit_entry
xa_recover_entry
xa_forget_entry
xa_complete_entry

Non-null pointers to the Resource Manager entry points.

 

xid_t

struct xid_t
{
    long    formatID;
    long    gtrid_length;
    long    bqual_length;
    char    data[XIDDATASIZE];
};

An identifier containing a Global Transaction Identifier and a Branch Qualifier.

Elements are:

formatID

Format identifier.

If formatID is -1, the transaction identifier is NULL.

gtrid_length

The number of bytes that constitute the Global Transaction Identifier (gtrid), starting at the first byte of the data element (data[0]).

The maximum length is 64 bytes.

bqual_length

The number of bytes that constitute the branch qualifier, starting at the first byte after gtrid (data[gtrid_length]).

The maximum length is 64 bytes.

data[XIDDATASIZE]

The data field. The maximum length is 128 bytes.

Neither component in data[] is null terminated.

You do not need to initialize any unused bytes.

 

Functions

 

o_xastatetransition()

int o_xastatetransition(

o_xidhandle xid,
o_u4b       xaoperation,
o_u4b       flags,
int         xaer);

Check whether the execution of an XA call is consistent with the state of the Resource Manager and Transaction Branch associated with the transaction identified in the xid parameter.

If the XA function was called out of sequence or if the input flags are inconsistent, then this function will return XAER_RMFAIL.

Parameters:

xid

A pointer to the Transaction Identifier.

xaoperation

The type of XA operation that was performed.

flags

The same value as that of the XA function.

xaer

The result error code of the XA function.

 

vsnt_xa_close()

static int vsnt_xa_close(char *xa_info, int rmid, long flags);

VERSANT interprets the xa_close() call from the Transaction Manager as vsnt_xa_close(). A Transaction Manager calls xa_close() to close a currently open Resource Manager in the calling thread of control. Once closed, the resource manager cannot participate in global transactions on behalf of the calling thread until it is re-opened. Objects in the cache, if present, will not be flushed and will be lost.

It is an error, [XAER_PROTO], for a Transaction Manager to call xa_close() within a thread of control that is associated with a transaction branch (i.e., the Transaction Manager must call xa_end() before calling xa_close()).

Parameters:

xa_info

The argument xa_info points to a null-terminated character string that may contain instance-specific information for the Resource Manager. In the case of VERSANT, we require that it conform to the following format:

<database name>

The maximum length of the database name is 31 bytes.

rmid

This is the same integer that the Transaction Manager generated when calling xa_open() and identifies the Resource Manager called from the thread of control.

flags:

The function's last argument, flags must be set to TMNOFLAGS.

 

vsnt_xa_commit()

static int vsnt_xa_commit(XID *xid, int rmid, long flags);

VERSANT interprets the xa_commit() call from the Transaction Manager as vsnt_xa_commit().

A Transaction Manager calls xa_commit() to commit the work associated with *xid. Any changes made to resources held during the transaction branch are made permanent.

All associations for *xid must have been ended by using xa_end() with TMSUCCESS set in the flags parameter.

Parameters:

xid

Upon success, zero or more Transaction Identifiers will be placed into the space pointed to by xids. It is the Transaction Manager's responsibility to ignore Transaction Identifiers that do not belong to it.

rmid

This is the same integer that the Transaction Manager generated when calling xa_open(), This parameter identifies the resource manager called from the thread of control.

flags

Must be set to either TMNOFLAGS or TMONEPHASE.

The options TMNOWAIT and TMASYNC are not supported.

 

vsnt_xa_complete()

static int vsnt_xa_complete(

int *handle,
int *retval,
int rmid,
long flags)

VERSANT interprets the xa_complete() call from the Transaction Manager as vsnt_xa_complete().

This functions always returns XAER_PROTO, since no asynchronous operation is supported in this release.

 

vsnt_xa_end()

static int vsnt_xa_end(XID *xid, int rmid, long flags);

VERSANT interprets the xa_end() call from the Transaction Manager as vsnt_xa_end(). A Transaction Manager calls xa_end() when a thread of control finishes.

Parameters:

xid

A pointer to the Transaction Identifier. The argument xid must point to the same Transaction Identifier that was passed to the xa_start() call that established the thread's association; otherwise, an error, [XAER_NOTA], will be returned.

rmid

This is the same integer that the Transaction Manager generated when calling xa_open(), identifies the Resource Manager called from the thread of control.

flags

Must be set to TMSUCCESS or TMFAIL, TMSUSPEND, or TMMIGRATE. TMASYNC is not supported. In case the flag is set to TMSUSPEND, the front end cache will not be flushed, and we will not allow a different process to use the suspended external transaction.

 

vsnt_xa_forget()

static int vsnt_xa_forget(

Transaction Identifier* xid,
int                     rmid,
long                    flags);

VERSANT interprets the xa_forget() call from the Transaction Manager as vsnt_xa_forget().

A request will be sent from the client to the server asking it to remove the external transaction entry.

 

vsnt_xa_open()

static int vsnt_xa_open(char *xa_info, int rmid, long flags);

VERSANT interprets the xa_open() call from the Transaction Manager as vsnt_xa_open(). Transaction Manager calls xa_open to initialize a Resource Manager and prepare it for use in a distributed transaction processing environment. It must be called before any other resource manager (xa_) calls are made. If the Resource Manager supports multiple instances, the Transaction Manager can call xa_open() more than once for the same Resource Manager.

Parameters:

xa_info

The argument xa_info points to a null-terminated character string that may contain instance-specific information for the Resource Manager. In the case of VERSANT, we require that it conform to the following format:

<database name>

The maximum length of the database name is 31 bytes.

rmid

The argument rmid, an integer assigned by the Transaction Manager, uniquely identifies the called Resource Manager instance within the thread of control. The Resource Manager passes the rmid on subsequent calls to XA routines to identify the Resource Manager. This identifier remains constant until the Transaction Manager in this thread closes the Resource Manager.

flags

Must be set to TMNOFLAGS. The only other value, TMASYNC, is not supported.

 

vsnt_xa_prepare()

static int vsnt_xa_prepare(XID *xid, int rmid, long flags);

VERSANT interprets the xa_prepare() call from the Transaction Manager as vsnt_xa_prepare().

A Transaction Manager calls xa_prepare() to request a Resource Manager to prepare for commitment any work perform on behalf of xid. All associations for xid must have been ended by using xa_end() with TMSUCCESS set in flags.

Once this function successfully returns, the Resource Manager must guarantee that the transaction branch may be either committed or rolled back regardless of failures. A resource manager cannot erase it's knowledge of a branch until the Transaction Manager calls either xa_commit() or xa_rollback() to complete the branch.

Parameters:

xid

A pointer to the Transaction Identifier.

rmid

This is the same integer that the Transaction Manager generated when calling xa_open(), identifies the Resource Manager called from the thread of control.

flags

Must be set to TMNOFLAGS.

 

vsnt_xa_recover()

static int vsnt_xa_recover(

Transaction Identifier *xids,
long count,
int rmid,
long flags);

VERSANT interprets the xa_recover() call from the Transaction Manager as vsnt_xa_recover().

A Transaction Manager calls xa_recover() during recovery to obtain a list of transactions that are currently in a prepared state. The caller points xids to an array into which the resource manager places Transaction Identifiers for these transactions, and sets count to the maximum number of Transaction Identifiers that fit into that array.

So that all Transaction Identifiers may be returned irrespective of the size of the array xids, one or more xa_recover() calls may be used within a single recovery scan.

The start of a recovery scan moves a cursor to the start of a list of prepared transactions. Throughout the recovery scan the cursor marks the current position in that list. Each call advances the cursor past the set of Transaction Identifiers it returns.

Two consecutive complete recovery scans return the same list of transactions unless a Transaction Manager calls xa_commit(), xa_forget(), xa_prepare(), or xa_rollback() for that Resource Manager.

A Transaction Manager may call this function from any thread of control, but all calls in a given recovery scan must be made by the same thread.

Parameters:

flags

Defines when a recovery scan should start or end, or start and end.

xid

Upon success, xa_recover() places zero or more Transaction Identifiers in the space pointed to by xids. It is the Transaction Manager's responsibility to ignore Transaction Identifiers that do not belong to it.

count

The function returns the number of Transaction Identifiers it has placed there. If this value is less than count, there are no more Transaction Identifiers to recover and the current scan ends. (That is, the Transaction Manager need not call xa_recover() again with TMENDRSCAN set in flags.) Multiple invocations of xa_recover() retrieve all the prepared transactions.

rmid

The argument rmid, the same integer that the transaction manager generated when calling xa_open(), This parameter identifies the resource manager called from the thread of control.

flags

Following are valid settings for flags:

TMSTARTRSCAN

This flag indicates that xa_recover() should start a recovery scan for the thread of control and position the cursor to the start of the list. Transaction Identifiers are returned from that point. If a recovery scan is already open, the effect is as if the recovery scan were ended and then restarted.

TMENDRSCAN

This flag indicates that xa_recover() should end the recovery scan after returning the Transaction Identifiers. if this flag is used in conjunction with TMSTARTRSCAN, the single xa_recover() call starts and then ends a scan.

TMNOFLAGS

This flag must be used when no other flags are set in flags. A recovery scan must already be started. Transaction Identifiers are returned starting at the current cursor position.

 

vsnt_xa_rollback()

static int vsnt_xa_rollback(XID *xid, int rmid, long flags);

VERSANT interprets the xa_rollback() call from the Transaction Manager as vsnt_xa_rollback().

A Transaction Manager calls xa_rollback() to roll back the work performed at a Resource Manager on behalf of the transaction branch.

Parameters:

xid

A pointer to the Transaction Identifier.

rmid

This is the same integer that the Transaction Manager generated when calling xa_open(), identifies the Resource Manager called from the thread of control.

flags

Must be set to TMNOFLAGS.

 

vsnt_xa_start()

static int vsnt_xa_start(XID *xid, int rmid, long flags);

VERSANT interprets the xa_start() call from the Transaction Manager as vsnt_xa_start().

A Transaction Manager calls xa_start() to inform a Resource Manager that an application may do work on behalf of a transaction branch.

Parameters:

xid

A pointer to the Transaction Identifier that a Resource Manager must associate with the calling thread of control. There will be a table to map the *xid to a VERSANT transaction on the server side.

rmid

This is the same integer that the Transaction Manager generated when calling xa_open() and identifies the Resource Manager called from the thread of control.

flags

Must be set to TMNOFLAGS, TMJOIN, or TMRESUME, TMNOWAIT and TMASYNC are not supported. Only the process that suspended it can resume a suspended external transaction.

 

 

 


This online documentation is confidential and proprietary to Versant Corporation and is licensed to you, or to your organization, pursuant to the terms of an agreement between you and Versant that restricts the use of this documentation. Please refer to the agreement for more information or call Versant at 510-789-1500 with any questions.