VisiTransact Guide : Pluggable Database Resource Module for VisiTransact

Pluggable Database Resource Module for VisiTransact
The pluggable database resource module, or Pluggable Resource Interface, is a component that implements a set of predefined interfaces to allow transactional applications to use databases as their persistent storage in transactions managed by VisiTransact.
The examples given in this document are for the Oracle9i database, but you can use the Pluggable Resource Interface to manage transactions with the database of your choice.
Concepts
What is the pluggable database resource module?
The pluggable database resource module is a component that implements a set of predefined interfaces to allow transactional applications to use databases as their persistent storage in transactions managed by VisiTransact.
Developers who want to use a specific type of database have to implement the module. After a module has been properly implemented and compiled, the Session Manager's Connection Manager will load the module into application.
The pluggable modules are provided in the form of shared libraries. Once the Session Manager's Connection Manager loads a module, it will interact with the module by the predefined interfaces. Those predefined interfaces enable the Session Manager's Connection Manager to carry out tasks necessary for a transaction, including: obtaining a physical connection from the supported database for the transactional application to manipulate data; informing the database of the association, dissociation, and the decision (commit or rollback) of a transaction; and disconnecting from the database when it is no longer needed.
The predefined interfaces are simple and standard-based, which support two kinds of transactions, that is, local transactions (Direct connections or DCs) and global transactions (XA connections). Direct connections are used when there is only one resource in a transaction. In that case it does not need to coordinate the commitment of multiple resources so VisiTransact will send commit or roll back directly to the database. XA connections are used when more than one databases are involved in a single global transaction. VisiTransact uses the XA interface defined in the X-Open specification to coordinate the databases to complete a global transaction.
Using the pluggable module technique of VisiTransact, a developer can easily integrate different databases into VisiTransact-managed transactional applications.
Structural descriptions
The following figure shows the basic model for the pluggable modules.
Figure 22
The transaction application is a program that usually initializes transactions to carry out safe business tasks. The session manager's connection manager sits between the transaction application and the pluggable modules to take care of the connection and association issues for the access to a database in transactions. The various pluggable modules are loaded by the application in time of need, through which all specific databases can be reached.
The session manager's connection manager also caches the live connections for reuse, thus improving the performance. It also communicates with VisiTransact to register resource objects.
For XA connections a separate component, resource director, is used.
Connection Management
When a transactional application for the first time starts a transaction and get a connection with a specified profile name, the session manager's connection manager will load the right pluggable module into the process according to the profile. The session manager's connection manager makes connection to the database through the module and wraps the physical link into a standard connection object, and then associates it with the transaction. After that, it returns the connection object to the application.
Once the connection object is got, the application is safe to use it to update transactional data in the database. When a part of work is finished, the application must release the connection. This allows the session manager's connection manager to either recollect the resources allocated to the connection object or make the current connection available to other tasks.
Each time a connection object is created, it is associated with a specific configure profile which contains information necessary for the Session Manager Connection Manager to make a physical connection to a database. The Session Manager Connection Manager also associates some attributes with the connection object, such as transaction context, internal connection states, and timeout.
A connection obtained from the Session Manager Connection Manager is valid until it is released, disconnected, or finished with the completion of the associated transaction.
When a pluggable connection object is released, it is pooled for reuse. However the pooling and reuse mechanism is different between the DC and XA connections.
For a DC connection, the following table gives the detail about how a connection is used, pooled and reused.
The commit() interface will be called.
For an XA connection, the following table shows the mechanism.
The xa_close_string() interface will be called for the string used to close the connection. Other necessary calls will be made through the xa switch.
One major difference between XA and DC connections are their thread models. For DC connections, once the application get a connection from a thread, it can pass the connection object to any thread in the process as long as the specific database allows it to do so; for XA connections, the Session Manager Connection Manager obtains connections for different threads and then associates each connection object, as well as the thread who requires the connection, with the global transaction managed by VisiTransact. Passing an XA connection object across threads may get unexpected results and therefore is strongly discouraged.
Writing a Pluggable Module
The connection profiles
Each connection that the pluggable modules provides is associated with a configure profile, which contains the necessary information for the Session Manager Connection Manager to get a connection. This information is given in the following table:
A string parameter the session manager passes to the getITSDataConnection() call in the pluggable module to get a new connection. This will give the module a way to customize different types of connections it can produce. (See the example included in the product for detail.)
When an application calls getConnection() interface (defined in VISSessionManager.idl), it must supply a configure profile name for the session manager connection manager to load the right module and make the connections. So before starting your application, the corresponding configure profiles must be created.
To create a profile, use the smconfigsetup tool included in the product.
To start the smconfigsetup tool, follow these steps:
1
Start osagent.
2
Start smconfig_server.
3
Start smconfigsetup.
After starting the smconfigsetup tool, it will give you a list of options that you can use to manage your profiles. Select option 7 to create a configure profile for the pluggable modules. Then you can follow the prompt to give all your information defined in the above table in order. The tool will save the profile in the specified location for session manager.
The Interface Definition
The interfaces that a pluggable module need to implement are defined in a single header file.
In this header file, a function that Session Manager Connection Manager used to get a connection object from and a connection class are defined. A pluggable module does not need to implement all the interfaces. Some of the interface are compulsory, some are optional, based on the type of connection the module is going to support.
The Single Function
Any pluggable module must implement this function.
The function GetITSDataConnection() is defined as follows:
extern "C"
ITSDataConnection* GetITSDataConnection(const char* param);
This function, when called by Session Manager Connection Manager, must return a new object that represents a new connection. If an existing connection is reused, the session manager connection manager never calls the function again for it. The function uses C calling convention.
This function takes a string as its only parameter. Users are free to specify this parameter in a configuration file to control the properties of the connections corresponding to the profile, if any. The Session Manager Connection Manager will get this parameter from the profile and passes it as the argument to this function.
The return value is a pointer to an object of type ITSDataConnection which contains the connection related interfaces that a pluggable module should implement.
This function can be taken as the entry point of a pluggable support module - the first call by the module loader (which is the Session Manager Connection Manager). The session manager connection manager relies on this function to get an object for connection management.
The ITSDataConnection class
This class is defined below.
class ITSDataConnection
{
public:
virtual void connect() = 0;
virtual void disconnect() = 0;
virtual void rollback() = 0;
virtual void commit() = 0;
virtual xa_switch_t* xa_switch() { return 0; }
virtual const char* xa_open_string() { return 0; }
virtual const char* xa_close_string() { return 0; }
virtual void* native_handle() { return 0; }
};
The methods in ITSDataConnection class can be divided into three groups:
1
2
3
Native handle acquisition interface
void* native_handle();
This function is used to get access to the native APIs for a database supported by the module. The return value is a void pointer, allowing the implementation to return anything necessary to manipulate data in the database. A transactional application can obtain this pointer through getNativeConnectionHandle(), in which the Session Manager Connection Manager will call the native_handle() and return the pointer back to the application.
Any pluggable module must implement this function.
Local transaction connection and completion interface
Pluggable modules that support the local transaction must implement these functions.
These four methods are used by Session Manager Connection Manager to inform the database of the start and completion of local transactions.
void connect();
When it is called, this method establishes the connection to the database and tells the database that a local transaction begins.
void disconnect();
When this method is called, it means the connection, if established, is no longer needed. So the connection can be closed.
void rollback();
This method tells the database to commit the transaction.
void commit();
This method tells the database to rollback the transaction.
Global transaction connection and completion interface
Pluggable modules that support global transactions must implement the functions.
The session manager uses X-open's XA interface to talk to a XA conformable database.
xa_switch_t* xa_switch();
All the Session Manager Connection Manager need from the pluggable module is a pointer to a xa_switch_t data structure which contains all the XA APIs as defined in the xa.h. The xa_switch() function is just for this purpose. Whenever being called, it must returns a valid pointer to this data.
Usually the specific database implements and exposes the xa_switch_t to its clients. The name of that data struct varies from database to database. For example, Oracle9i implements its xa_switch_t as a global variable named xaosw.
This function is also used by Session Manager Connection Manager to judge the type of a connection. If the function returns zero, the session manager will treat the connection as DC type, otherwise it takes the connection as XA type.
Pluggable modules that support global transactions must implement the function and must not return zero.
const char* xa_open_string();
When called, it returns a string used as argument to xa_open() call.
const char* xa_close_string();
When called, it returns a string used as argument to xa_close() call.
The two methods are called by the session manager to get database specific parameters to open or close a XA connection to a database. The returned string from the xa_open_string() call will be used in the call on xa_open() and the returned string from the xa_close_string() is used in xa_close().
Once called for an XA connection, the session manager will keep the returned values for later use. The implementation does not need to keep the validity of the returned pointer all the time.
Building and Running
1
Compiling the pluggable module doesn't need any VisiTransact specific libraries. However, you have to include the itsdataconnection.h in your source file. The xa.h is a standard XA header that needed to be in your include path. Usually databases which support the XA interface provide the xa.h in their installation directory.
2
No VisiTransact specific libraries are needed during the compile time. However, you may need the database specific libraries. For example if you want to support the oracle9i database in your pluggable module and use OCI, you have to put the oracle9i client library in your library path and link it with your code.
3
The pluggable modules must be in form of shared libraries. Different compilers have different flags that control the build target type. Please refer to our examples to see the flags needed to build a shared library.
Running Applications using the pluggable modules
A transactional application need not have the knowledge of the pluggable modules. However, it may need to know the interface of the native handle for accessing data in databases. Building the application does not need to link with any pluggable modules as those modules, when needed, will be dynamically loaded into the process in the run time. Therefore, before you start the application make sure that the pluggable modules are in the library path so that the Session Manager Connection Manager can successfully loaded them in.
Programming restrictions
When using the DirectConnect profile, the following operations should not be called in the application: “Connection Operation”, “Transaction Operations”, and “Implicit Operations”. Similarly, there is another set of programming restrictions when using the XA profile. See “Programming restrictions” and “Programming restrictions” for more information.
Known limitations
In any plug-in session manager, the VISSessionManager::Connnection::isSupported() API will have static return values. In the case of DC connection, isSupported(“hold”) will return true and isSupported("thread_portable") will return true. In the case of XA connection, isSupported("hold") will return false and isSupported("thread_portable") will return false.
In any plug-in session manager, the VISSessionManager::Connection::getInfo("version_rm") will now return NULL. As the information is not applicable in the case of a plug-in session manager.