![]() ![]() ![]() ![]() ![]() ![]() |
This topic includes the following sections:
Before you begin developing your Oracle Tuxedo Application-to-Transaction Monitor Interface (ATMI) application, it may be helpful to review the various concepts related to its design and the tools that are available to you. These concepts include identifying clients or the various ways input from the outside world is gathered and presented to your business for processing, and identifying servers or the programs containing the business logic that process the input data. Also important is reviewing the concept of typed buffers or how a client program allocates a memory area before sending data to another program. Another concept worth reviewing is that of the Oracle Tuxedo messaging paradigms. ATMI client programs access the Oracle Tuxedo system by calling the ATMI library. Most calls in the ATMI library support these different communication styles available to programmers, such as request/response and conversational. These are the building blocks of every Oracle Tuxedo application.
For more information about concepts, such as application queues, event-based communication, and using ATMI, and on the tools available to you, refer to “Basic Architecture of the Oracle Tuxedo ATMI Environment” in Introducing Oracle Tuxedo ATMI. For information about programming an application, refer to Programming Oracle Tuxedo ATMI Applications Using C and Programming Oracle Tuxedo ATMI Applications Using COBOL.
Creating an Oracle Tuxedo client is just like creating any other program in the C or C++ programming language. The Oracle Tuxedo system provides you with a C-based programming interface known as the Oracle Tuxedo Application-to-Transaction Monitor Interface or ATMI. The ATMI is an easy-to-use interface that enables the rapid development of Oracle Tuxedo clients and servers.
Note: | Oracle Tuxedo ATMI also supports a COBOL interface. (The examples shown here illustrate the C/C++ API.) |
Clients perform the following basic tasks:
tpchkauth()
to determine the level of security required to join an application. Possible responses are: no security enabled, application password enabled, application authentication enabled, access control lists enabled, link-level encryption, public key encryption, auditing. (This is optional depending on whether you are using security levels.)tpinit()
to connect to an Oracle Tuxedo application. Any required security information is passed to the application as arguments for tpinit()
.tpterm()
to disconnect from an Oracle Tuxedo application.
Developers use the ATMI programming interface to create an Oracle Tuxedo client and server. However, Oracle Tuxedo servers are not written by application developers as complete programs (that is, with a standard main
). Instead, application developers write a set of specific business functions (known as services) that are compiled along with the Oracle Tuxedo binaries to produce a server executable.
When an Oracle Tuxedo server is booted, it continues running until it receives a shutdown message. A typical Oracle Tuxedo server may perform thousands of service calls before being shut down and rebooted.
tpsvrinit()
function only when the Oracle Tuxedo server is booted. Programmers use this function to open an application resource (such as a database) for later use.tpsvrdone()
function only when the Oracle Tuxedo server is shut down. Programmers use this function to close any application resources opened by tpsvrinit()
.tpreturn()
function to end a service request and return a buffer, if required, to the calling client.
All communication in the Oracle Tuxedo system is transmitted through typed buffers. The Oracle Tuxedo system offers application developers the choice of many different buffer types to facilitate this communication. All buffers passed through the Oracle Tuxedo system have special headers, and must be allocated and freed through the Oracle Tuxedo ATMI (tpalloc()
, tprealloc()
, and tpfree()
).
The typed buffers facility allows for generic well-defined processing to be implemented once a buffer type is shared across any type of network and protocol and any type of CPU architecture and operating system supported by the Oracle Tuxedo system. The advantage of typed buffers in a distributed environment is that they relieve your clients and servers from the details of preparing data to be transferred between heterogeneous computers linked by various communications networks. This affords an application programmer time to concentrate on their business logic, instead of focusing attention on writing this facility into their own programs.
The Oracle Tuxedo ATMI offers several communication models that you can use in your application:
To make a synchronous call, an Oracle Tuxedo ATMI client uses the ATMI function tpcall()
to send a request to an Oracle Tuxedo ATMI server. The function does not invoke an Oracle Tuxedo server by name; instead, it invokes a specified service, which is provided by any server that offers the service and is available. The client then waits for the requested service to be performed. Until it receives a reply to its request, the client is not available for any other work. In other words, the client blocks until it receives a reply.
To make an asynchronous call, a client calls two ATMI functions: the tpacall(3c) function, to request a service, and the tpgetrply(3c) function, to retrieve the reply. This method is commonly used when a client can perform additional tasks after issuing a request and before receiving a reply.
Services can act as Oracle Tuxedo ATMI clients and call other Oracle Tuxedo services. In other words, you can request a service that, in turn, requests other services. For example, suppose an Oracle Tuxedo client calls service X and waits for a reply. Service X then calls service Y and also waits for a reply. When service X receives a reply, it returns the reply to the calling client. This method is efficient because service X can take the reply from service Y, do more work on it, and modify the return buffer before sending a final reply back to the client.
With call forwarding, a nested service can return a reply directly to an ATMI client without going through the first service that was called, thereby freeing the first service to handle other requests. This capability is useful when the first service is acting strictly as a delivery agent, without adding data to the reply returned by the nested service.
To facilitate call forwarding, a service called by a client uses the tpforward(3c) function to pass the request to another service Y. This is the only situation in which an Oracle Tuxedo service can end a service call without calling tpreturn(3c).
Call forwarding is transparent to the client. In other words, the same client code is valid for service requests handled by one service and requests handled by more than one service.
If multiple buffers need to be sent between an Oracle Tuxedo ATMI client and an Oracle Tuxedo service in a stateful manner, then the Oracle Tuxedo conversation may be a suitable option.
Use Oracle Tuxedo conversations judiciously because a server engaged in a conversation is unavailable until the conversation has ended. To implement a conversation, incorporate the following steps into your code:
tpconnect()
function.tpsend()
and tprecv()
functions. A special flag is set in the service calls to indicate which participant has control of the conversation.tpreturn()
or the tpdiscon()
function.
To enable unsolicited notification, an Oracle Tuxedo ATMI client creates an unsolicited message handle using the tpsetunsol()
function. To send an unsolicited message, an Oracle Tuxedo client or server can use either the tpnotify()
function, to send a message to a single client, or the tpbroadcast()
function, to send a message to multiple clients at the same time. When a client receives a message, the Oracle Tuxedo system calls the client’s unsolicited handler function.
In a signal-based system, a client does not have to poll for unsolicited messages. However, in a non-signal based system, a client must check for unsolicited messages using the tpchkunsol()
function. Whenever a client makes a service request, tpchkunsol()
is called implicitly.
Note: | If you call tpnotify() with the tpack flag bit set, you will receive an acknowledgement of your request. |
In event-based communication, events can also be posted to application queues, log files, and system commands. Any Oracle Tuxedo ATMI client can subscribe to a user-defined event using the tpsubscribe()
function and receive an unsolicited message whenever an Oracle Tuxedo service or client issues a tppost()
function. ATMI clients can also subscribe to system-defined events that are triggered whenever the Oracle Tuxedo system detects the event. When a server dies, for example, the .SysServerDied
event is posted. No application server is needed to post this event, because it is performed by the Oracle Tuxedo system.
To interface with the /Q system, an Oracle Tuxedo client uses two ATMI functions: tpenqueue()
, to put messages into the queue space, and tpdequeue()
, to take messages out of the queue space.
The following model represents peer-to-peer asynchronous messaging. Here, a client enqueues a message to a service using tpenqueue()
. Optionally, the names of a reply queue and a failure queue can be included in the call to tpenqueue()
. The client can also specify a correlation identifier value to accompany the message. This value is persistent across queues so that any reply or failure message associated with the queued message can be identified when it is read from the reply or the failure queue.
The client can use the default queue ordering (for example, a time after which the message should be dequeued), or can specify an override of the default queue ordering (asking, for example, that this message be put at the top of the queue or ahead of another message on the queue). The call to tpenqueue()
sends the message to the TMQUEUE
server, the message is queued to stable storage, and an acknowledgment is sent to the client. The acknowledgment is not seen directly by the client, but can be assumed when the client gets a successful return. (A failure return includes information about the nature of the failure.) A message identifier assigned by the queue manager is returned to the application. The identifier can be used to dequeue a specific message. It can also be used in another tpenqueue()
to identify a message on the queue ahead of the next message to be enqueued.
Before an enqueued message is made available for dequeuing, the transaction in which the message is enqueued must be committed successfully. A client uses tpdequeue()
to dequeue messages from the queue.
In the following graphic, forwarding a message to another server is illustrated.
The client enqueues a message intended for service X on the server. The service receives this message when it is active and when the handling instructions for the message are met (for example, the message can be encoded to be activated on Friday at 6 PM). Once the service is completed, it returns the reply to the queue space, from which it can be retrieved by the client.
This system of queuing is transparent to services. In other words, the same application code is used for a service, regardless of whether the service is invoked through queuing or direct service invocation using tp(a)call
.
To implement transactions, an application programmer uses three ATMI functions:
Any code placed outside the begin and commit/abort sequence is not included in the transaction.
In the following example, a client begins a transaction, requests two services, and then commits the transaction. Because the service requests are made between the beginning and the commitment of the transaction, both services join the transaction.
![]() ![]() ![]() |