Application Development


Chapter 35. Generating Transaction Manager Events

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.

Table 35-1 Stages of transaction manager processing

Processing stage Description Event type generated

Command interpreter

Generates request events for the specified command. Sends requests to the traversal controller, one at a time.

Requests

Traversal controller

Traverses the transaction tree (derived from the screen's table views and links) for the specified request event. How the tree is traversed depends upon the type of request, the transaction tree it self, and the data on the screen. In general, the traversal controller calls the model invoker to process the request for each table view.

Model invoker

Invokes an event function (if one is specified) and the appropriate model for the specified table view. For information on how event functions are invoked, refer to page 35-6.

TM models and event functions

Processes request and slice events for the specified table view. Processing can include calling the SQL generator or database interface, or generating slice events that are routed back to the model invoker and then sent to the model or event function.

Slices

SQL generator

Generates SQL commands or sends the statement to the database interface.

Database interface

Interfaces with the DBMS.

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.

Invoking Event Functions and Models

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.

Table 35-2 How to invoke transaction manager event functions or transaction models

Type Description How to specify

Event function

Applied to a specific table view. You can use an event function to affect the processing of either the database-specific model or the common model.

Table view's Function (function) property (under Transaction).

Database-specific transaction model

Applied by default to a table view. Alternatively, a custom model can be identified for a specific table view which would supersede the default database-specific model. You can also modify a distributed model in order to customize its behavior.

Custom model called via table view's or screen's Model (model) property (under Transaction). If a custom model is not specified, a database-specific model is applied.

Common model

Applied to all table views, unless superseded by a database-specific model (default or custom) or event function that processes TM_OK event.

Not applicable; called by default on TM_PROCEED event

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.

Event Processing Steps

The invoker uses the following priorities and precedence when processing events:

  1. Read the next event from the stack. If the stack is empty, return to the traversal controller.
  2. Invoke the event function, if one is specified for the current table view. Otherwise go to step 4.
  3. Check the event function return code. If the return value is:
  4. Invoke the database-specific transaction model.

    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:

  5. Check the transaction model return code. If the return value is:
  6. Invoke the common transaction model.
  7. Check the common model return code. If the return value is:

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.

Controlling the Event Stack

The following library functions allow you to push and pop events from the stack:

Transaction Models and the Event Stack

The following example illustrates how the requests 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);
}
}

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.

Adding Your Own Transaction Events

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.

Example

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.

#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

As an example, create a log of all the select requests made to your database. You can write an event function (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
}

This event function ignores all other events, but when 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).

The model invoker process the events as follows:

  1. TM_SELECT or TM_VIEW is passed to the model invoker from the traversal controller.
  2. The invoker submits the 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.
  3. The invoker checks the return code and continues processing.
  4. The invoker sends TM_SELECT or TM_VIEW to the transaction model, which (for this example) also sends a return code of TM_PROCEED.
  5. The invoker checks the return code and continues processing.
  6. The invoker sends 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.
  7. The invoker processes the other events on the stack, just as it did for the original request—invoking the event function and then the transaction model—until TM_SEL_BUILD_PERFORM moves to the top of the stack.
  8. The invoker reads TM_SEL_BUILD_PERFORM from the top of the stack and sends it to the event function.
  9. The event function recognizes the event TM_SEL_BUILD_PERFORM and logs the appropriate information. It sends a return code TM_PROCEED.
  10. The invoker checks the return code and continues processing the event—first to the database-specific transaction model and then to the common model.
  11. The next event is called.

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.