Application Development |
Once a transaction manager command is invoked, the transaction manager generates a series of events.
This chapter describes:
Generating Transaction Manager Events |
When a transaction manager command is called, the transaction manager processes the command as a series of events, using information entered in the application screen, as well as information defined in screen properties, and in table view and link widget properties. The control flow of events within the transaction manager (on a three-tier application server or on a two-tier client) is illustrated in Figure 35-1.
Figure 35-1 The transaction manager processes a command as a series of events.
As shown in Figure 35-1, the events are characterized as either request events or slice events. When the transaction manager is called, a command interpreter generates a set of request events for the specified command. For several of the more important requests, a sequence of more specialized events, referred to as slices, are generated by the transaction model and/or event functions. Table 35-1 describes this processing sequence for events, requests and slices.
For example, consider the VIEW
command which fetches database information, the command interpreter generates the following request events for the command:
TM_PRE_VIEW
TM_VIEW
TM_POST_VIEW
Each request event, for example, TM_PRE_VIEW
, is sent to the traversal controller, where the request is mapped over the table views for the current screen. When the traversal controller completes the processing for one request, the next request is sent.
Refer to page 9-3 in the Programming Guide for a list of the request and slice events for all transaction manager commands.
Traversing the Table Views |
After the command interpreter generates the request events, the next step is to traverse the transaction tree, applying those requests to the database tables that are a part of the screen.
To support automatic database access, Panther needs to know which widgets are associated with which database tables, and how the tables are related. Database table information is stored in a table view widget. Text widgets derived from the database table's columns are members of the table view.
The database table's relationship information is stored in link widgets; they define the relationship between two table views. Based on these relationships, a transaction tree can be generated. The DB Interactions window, shown in Figure 35-2, illustrates a sample transaction tree for event processing.
Figure 35-2 The DB Interactions window shows the link relationships between table views on a screen.
Generating Events in the Transaction Model |
As the transaction manager traverses the table views, it needs to determine what processing to perform for each event. The processing is defined in event functions and transaction models.
There are two layers of transaction models: the common model and a database-specific model. The common model typically processes most of the events; it provides plausible processing for every event known to the transaction manager and contains the functionality common to all of the database engines. The database-specific model contains processing necessary for a specific database engine.
Table 35-2 lists the models and event functions that might be invoked for an event (request or slice), and how you invoke functions or specify a particular model.
The source code for the database-specific transaction models is provided and can be modified to make global changes in transaction manager functionality. The common model should not be modified; however, the source code is available for reference.
Figure 35-3 shows how events are processed with the transaction manager via the model invoker. If an event function is specified for the current table view, then the event function is invoked first. If the event function returns a return code of TM_PROCEED
, then the invoker also invokes the database-specific transaction model. If the transaction model returns a return code of TM_PROCEED
, then the common model is invoked.
Figure 35-3 Transaction manager event processing and transaction models.
A request event is sent from the traversal controller, that is, as the transaction manager traverses the transaction tree from table view to table view, to the model invoker. The invoker invokes the appropriate event function or transaction model, and passes the request along. The event function or transaction model can then generate slice events for the request and push these events onto the event stack. The model invoker then processes the slice events from the stack in a last-in, first-out order.
The slice events are processed in the exact same manner as the original request event, making no distinction between the two. For example, consider the request event TM_DELETE
which generates several slice events, including TM_GET_SAVE_CURSOR
. The model invoker does not know which event is a request and which is a slice.
Any slice event can also generate additional slice events, which are then pushed onto the top of the event stack. After all slice events are processed and the stack is empty, processing control returns to the traversal controller, to continue walking the traversal tree, to the next table view.
The invoker uses the following priorities and precedence when processing events:
The transaction model can be specified as one of the following and the model invoker determines which model to use based on the order of precedence:
Typically, a few of the events in a transaction can be processed by an event function or database-specific transaction model, while most transaction events are processed by the common model.
The following library functions allow you to push and pop events from the stack:
sm_tm_pop_model_event
returns the event number, or 0 if the stack is empty.
The following example illustrates how the requests For a list of the transaction events associated with each command and a description of the processing performed by those events, refer to page 9-3 in the Programming Guide.
It is possible for you to define your own transaction events and push them onto the stack as long as you specify them correctly and understand how the event stack performs its processing.
All transaction events have an integer associated with them. For user supplied events, the integer must be greater than 2047. The specification of the event can be in a header file or in the transaction model.
The transaction model must also list the event in the case statements at the beginning of the file. Otherwise, the model considers the event to be invalid. As part of that operation, you can write your own function to add to the model. Be sure to track any changes you make to the transaction model since it could change in future Panther releases.
An example of adding transaction events appears in the transaction model for JDB. Since referential integrity is not implemented in JDB, the transaction model checks for duplicate rows when you add new data. This is accomplished by adding two events to the JDB model and calling those events after an insert.
As an example, create a log of all the select requests made to your database. You can write an event function ( This event function ignores all other events, but when The model invoker process the events as follows:
Transaction Models and the Event Stack
TM_SELECT
and TM_VIEW
are further subdivided into slices and those slices are pushed onto the event stack in reverse order.
case TM_SELECT:
case TM_VIEW:
/* Put slices onto the stack only if it is the current
* server view
*/ tv = sm_tm_pinquire(TM_TV_NAME);
sv = sm_tm_pinquire(TM_SV_NAME);
if (tv && sv && *sv && !strcmp(tv,sv) )
{
sm_tm_push_model_event(TM_SEL_CHECK);
sm_tm_push_model_event(TM_SEL_BUILD_PERFORM);
sm_tm_push_model_event(TM_SEL_GEN);
if (!sel_cursor[0])
{
sm_tm_push_model_event(TM_GET_SEL_CURSOR);
}
} Adding Your Own Transaction Events
Example
#define DUP_GEN 9901
#define DUP_BUILD_PERFORM 9902
.
.
.
case TM_INSERT_EXEC:
if (check_pkey)
{
sm_tm_push_model_event(TM_SEL_CHECK);
sm_tm_push_model_event(DUP_BUILD_PERFORM);
sm_tm_push_model_event(DUP_GEN);
}
retcode = nsel_exec(EXEC_INSERT);
break;
case DUP_GEN:
retcode = dup_gen();
break;
case DUP_BUILD_PERFORM:
retcode = dup_build_perform();
break; Logging Transaction Events
my_eventLog
) to intercept the slice event TM_SEL_BUILD_PERFORM
, which is generated by the request TM_SELECT
and TM_VIEW
.
proc my_eventLog (event)
vars stream, err
{
if event == TM_SEL_BUILD_PERFORM
{
stream = sm_fio_open("mylog", "a")
err = sm_fio_puts("Perform select.", stream)
err = sm_fio_close(stream)
}
return TM_PROCEED
}TM_SELECT
or TM_VIEW
is encountered, it will log the appropriate information. This event function is applied to the current table view (via its Function property).
TM_SELECT
or TM_VIEW
is passed to the model invoker from the traversal controller.TM_SELECT
or TM_VIEW
event to the event function (my_eventLog
) named in the table view's Function property. The event function performs no processing and sends a return code TM_PROCEED
.TM_SELECT
or TM_VIEW
to the transaction model, which (for this example) also sends a return code of TM_PROCEED
.TM_SELECT
or TM_VIEW
to the common model, which generates several slice events, including TM_SEL_BUILD_PERFORM
and pushes them onto the event stack. The event TM_SEL_BUILD_PERFORM
is pushed near the bottom of the stack.TM_SEL_BUILD_PERFORM
moves to the top of the stack.TM_SEL_BUILD_PERFORM
from the top of the stack and sends it to the event function.TM_SEL_BUILD_PERFORM
and logs the appropriate information. It sends a return code TM_PROCEED
.Using the Transaction Model with JetNet/Oracle Tuxedo |
On a three-tier client using the JetNet middleware adapter, the transaction manager performs many of the same steps, but it uses the middleware API model, instead of the transaction model, to determine the processing for each event. The middleware API model generates service requests which can then be passed to the middleware for processing.
Figure 35-4 A three-tier JetNet client uses the middleware API model.
jetrb1
is the transaction model provided for three-tier applications using the JetNet
middleware adapter. When a client uses the transaction manager, jetrb1
determines which service request to make to satisfy the transaction manager command and provides default processing for the following transaction manager events: TM_SELECT, TM_VIEW, TM_DELETE, TM_DELETE_EXEC, TM_INSERT, TM_UPDATE, TM_UPDATE_EXEC, TM_PRE_SAVE, TM_POST_SAVE, TM_PRE_CLOSE, TM_POST_CLOSE, TM_POST_CLEAR
, and TM_VAL_LINK
.
The transaction manager can then be used on the application server to generate the SQL for the service request.
Figure 35-5 shows how the transaction manager is used in a three-tier application to generate and process a client request.
Figure 35-5 The transaction manager can be invoked on both client and server ends of the application.
The application property, tm_transaction
, determines if a service is transaction-manager enabled and, if so, which transaction manager operation to perform.
For information on using FML buffers with the transaction manager in the middleware adapter for Oracle Tuxedo, refer to page 8-2 in the JetNet/Oracle Tuxedo Guide.