![]() ![]() ![]() ![]() ![]() ![]() |
This topic includes the following sections:
Event-based communication provides a method for an Oracle Tuxedo system process to be notified when a specific situation (event) occurs.
The Oracle Tuxedo system supports two types of event-based communication:
Unsolicited events are messages used to communicate with client programs that are not waiting for and/or expecting a message.
Brokered events enable a client and a server to communicate transparently with one another via an “anonymous” broker that receives and distributes messages. Such brokering is another client/server communication paradigm that is fundamental to the Oracle Tuxedo system.
The EventBroker is an Oracle Tuxedo subsystem that receives and filters event posting messages, and distributes them to subscribers. A poster is an Oracle Tuxedo system process that detects when a specific event has occurred and reports (posts) it to the EventBroker. A subscriber is an Oracle Tuxedo system process with a standing request to be notified whenever a specific event has been posted.
The Oracle Tuxedo system does not impose a fixed ratio of service requesters to service providers; an arbitrary number of posters can post a message buffer for an arbitrary number of subscribers. The posters simply post events, without knowing which processes receive the information or how the information is handled. Subscribers are notified of specified events, without knowing who posted the information. In this way, the EventBroker provides complete location transparency.
Typically, EventBroker applications are designed to handle exception events. An application designer must decide which events in the application constitute exception events and need to be monitored. In a banking application, for example, it might be useful to post an event whenever an unusually large amount of money is withdrawn, but it would not be particularly useful to post an event for every withdrawal transaction. In addition, not all users would need to subscribe to that event; perhaps only the branch manager would need to be notified.
The EventBroker may be configured such that whenever an event is posted, the EventBroker invokes one or more notification actions for clients and/or servers that have subscribed. The following table lists the types of notification actions that the EventBroker can take.
Clients may receive event notification messages in their unsolicited message handling routine, just as if they were sent by the tpnotify() function.
|
|
Servers may receive event notification messages as input to service routines, just as if they were sent by the tpacall() function.
|
|
Event notification messages may be stored in an Oracle Tuxedo system reliable queue, using the tpenqueue(3c) function. Event notification buffers are stored until requests for buffer contents are issued. An Oracle Tuxedo system client or server process may call the tpdequeue(3c) function to retrieve these notification buffers, or alternately TMQFORWARD(5) may be configured to automatically dispatch an Oracle Tuxedo system service routine that retrieves a notification buffer.
|
In addition, the application administrator may create an EVENT_MIB(5) entry (by using the Oracle Tuxedo administrative API) that performs the following notification actions:
Note: | Only the Oracle Tuxedo application administrator is allowed to create an EVENT_MIB(5) entry. |
For information on the EVENT_MIB(5), refer to the File Formats, Data Descriptions, MIBs, and System Processes Reference.
TMUSREVT
is the Oracle Tuxedo system-supplied server that acts as an EventBroker for user events. TMUSREVT
processes event report message buffers, and then filters and distributes them. The Oracle Tuxedo application administrator must boot one or more of these servers to activate event brokering.
TMSYSEVT
is the Oracle Tuxedo system-supplied server that acts as an EventBroker for system-defined events. TMSYSEVT
and TMUSREVT
are similar, but separate servers are provided to allow the application administrator the ability to have different replication strategies for processing notifications of these two types of events. Refer to Setting Up an Oracle Tuxedo Application for additional information.
The Oracle Tuxedo system itself detects and posts certain predefined events related to system warnings and failures. These tasks are performed by the EventBroker. For example, system-defined events include configuration changes, state changes, connection failures, and machine partitioning. For a complete list of system-defined events detected by the EventBroker, see EVENTS(5) in the File Formats, Data Descriptions, MIBs, and System Processes Reference.
System-defined events are defined in advance by the Oracle Tuxedo system code and do not require posting. The name of a system-defined event, unlike that of an application-defined event, always begins with a dot (“.”). Names of application-defined events may not begin with a leading dot.
Clients and servers can subscribe to system-defined events. These events, however, should be used mainly by application administrators, not by every client in the application.
When incorporating the EventBroker into your application, remember that it is not intended to provide a mechanism for high-volume distribution to many subscribers. Do not attempt to post an event for every activity that occurs, and do not expect all clients and servers to subscribe. If you overload the EventBroker, system performance may be adversely affected and notifications may be dropped. To minimize the possibility of overload, the application administrator should carefully tune the operating system IPC resources, as explained in Installing the Oracle Tuxedo System.
EventBroker programming interfaces are available for all Oracle Tuxedo system server and client processes, including Workstation, in both C and COBOL.
The programmer’s job is to code the following sequence:
Subscribers may be notified in a variety of ways (as discussed in “Notification Actions”), and events may be filtered. Notification and filtering are configured through the programming interface, as well as through the Oracle Tuxedo system administrative API.
To define the unsolicited message handler function, use the tpsetunsol(3c) function with the following signature:
int
tpsetunsol(*myfunc
)
If you are running on Windows-based operating systems you must declare unsolicited message handler functions as:
void _TMDLLENTRY CustomerUnsolFunc(char *data, long len, long flags)
The _TMDLLENTRY
macro is required for Windows-based operating systems to obtain the proper calling conventions between the Tuxedo libaries and your code.
On Unix systems, the _TMDLLENTRY
macro is not required because it expands to the null string.
The following table describes the single argument that can be passed to the tpsetunsol()
function.
When a client receives an unsolicited notification, the system dispatches the call-back function with the message. To minimize task disruption, you should code the unsolicited message handler function to perform only minimal processing tasks, so it can return quickly to the waiting process.
The Oracle Tuxedo system allows unsolicited messages to be sent to client processes without disturbing the processing of request/response calls or conversational communications.
Unsolicited messages can be sent to client processes by name, using tpbroadcast(3c), or by an identifier received with a previously processed message, using tpnotify(3c). Messages sent via tpbroadcast
() can originate either in a service or in another client. Messages sent via tpnotify
() can originate only in a service.
The tpbroadcast(3c) function allows a message to be sent to registered clients of the application. It can be called by a service or another client. Registered clients are those that have successfully made a call to tpinit() and have not yet made a call to tpterm().
Use the following signature to call the tpbroadcast
() function:
int
tpbroadcast(char *lmid, char *usrname, char *cltname, char *data, long len, long flags)
The following table describes the arguments to the tpbroadcast()
function.
Flag options. Refer to tpbroadcast(3c) in the Oracle Tuxedo ATMI C Function Reference for information on available flags.
|
The following example illustrates a call to tpbroadcast
() for which all clients are targeted. The message to be sent is contained in a STRING
buffer.
char *strbuf;
if ((strbuf = tpalloc("STRING", NULL, 0)) == NULL) {
error routine
}
(void) strcpy(strbuf, "hello, world");
if (tpbroadcast(NULL, NULL, NULL, strbuf, 0, TPSIGRSTRT) == -1)
error routine
The tpnotify(3c) function is used to broadcast a message using an identifier received with a previously processed message. It can be called only from a service.
Use the following signature to call the tpnotify
() function:
int
tpnotify(CLIENTID *clientid, char *data, long len, long flags)
The following table describes the arguments to the tpnotify()
function.
Flag options. Refer to tpnotify(3c) in the Oracle Tuxedo ATMI C Function Reference for information on available flags.
|
To check for unsolicited messages while running the client in “dip-in” notification mode, use the tpchkunsol(3c) function with the following signature:
int
tpchkunsol()
The function takes no arguments.
If any messages are pending, the system invokes the unsolicited message handling function that was specified using tpsetunsol(). Upon completion, the function returns either the number of unsolicited messages that were processed or -1
on error.
If you issue this function when the client is running in SIGNAL
-based, thread-based notification mode, or is ignoring unsolicited messages, the function has no impact and returns immediately.
The tpsubscribe(3c) function enables an Oracle Tuxedo system ATMI client or server to subscribe to an event.
A subscriber can be notified through an unsolicited notification message, a service call, a reliable queue, or other notification methods configured by the application administrator. (For information about configuring alternative notification methods, refer to Setting Up an Oracle Tuxedo Application.)
Use the following signature to call the tpsubscribe()
function:
long handle
tpsubscribe (char *eventexpr
, char *filter
, TPEVCTL *ctl
, longflags
)
The following table describes the arguments to the tpsubscribe()
function.
Pointer to a set of one or more events to which a process can subscribe. Consists of a NULL-terminated string of up to 255 characters containing a regular expression. Regular expressions are of the form specified in tpsubscribe(3c), as described in the Oracle Tuxedo ATMI C Function Reference). For example, if
eventexpr is set to:
|
|
Pointer to a string containing a Boolean filter rule that must be evaluated successfully before the EventBroker posts the event. Upon receiving an event to be posted, the EventBroker applies the filter rule, if one exists, to the posted event’s data. If the data passes the filter rule, the EventBroker invokes the notification method specified; otherwise, the EventBroker ignores the notification method. The caller can subscribe to the same event multiple times with different filter rules.
By using the event-filtering capability, subscribers can discriminate among the events about which they are notified. For example, a poster can post an event for withdrawals greater than $10,000, but a subscriber may want to specify a higher threshold for being notified, such as $50,000. Or, a subscriber may want to be notified of large withdrawals made by specific customers.
Filter rules are specific to the typed buffers to which they are applied. For more information on filter rules, refer to tpsubscribe(3c) in the Oracle Tuxedo ATMI C Function Reference.
|
|
|
|
Flag options. For more information on available flag options, refer to tpsubscribe(3c) in the Oracle Tuxedo ATMI C Function Reference.
|
You can subscribe to both system- and application-defined events using the tpsubscribe
() function.
For purposes of subscriptions (and for MIB
updates), service routines executed in an Oracle Tuxedo system server process are considered to be trusted code.
If a subscriber is an Oracle Tuxedo system client process and ctl
is NULL, when the event to which the client has subscribed is posted, the EventBroker sends an unsolicited message to the subscriber as follows. When an event name is posted that evaluates successfully against eventexpr
, the EventBroker tests the posted data against the associated filter rule. If the data passes the filter rule (or if there is no filter rule for the event), then the subscriber receives an unsolicited notification along with any data posted with the event.
In order to receive unsolicited notifications, the client must register an unsolicited message handling routine using the tpsetunsol() function.
ATMI clients receiving event notification via unsolicited messages should remove their subscriptions from the EventBroker list of active subscriptions before exiting. This is done using the tpunsubscribe() function.
Event notification via service call enables you to program actions that can be taken in response to specific conditions in your application without human intervention. Event notification via reliable queue ensures that event data is not lost. It also provides the subscriber the flexibility of retrieving the event data at any time.
If the subscriber (either a client or a server process) wants event notifications sent to service routines or to stable-storage queues, then the ctl
parameter of tpsubscribe
() must point to a valid TPEVCTL
structure.
The TPEVCTL
structure contains the following elements:
longflags
;
charname1
[32];
charname2
[32];
TPQCTL qctl;
The following table summarizes the TPEVCTL
typed buffer data structure.
Flag options. For more information on flags, refer to tpsubscribe(3c) in the Oracle Tuxedo ATMI C Function Reference.
|
|
TPQCTL structure. For more information, refer to tpsubscribe(3c) in the Oracle Tuxedo ATMI C Function Reference.
|
The tpunsubscribe(3c) function enables an Oracle Tuxedo system ATMI client or server to unsubscribe from an event.
Use the following signature to call the tpunsubscribe()
function:
int
tpunsubscribe (long subscription, long flags)
The following table describes the arguments to the tpunsubscribe()
function.
Subscription handle returned by a call to tpsubscribe().
|
|
Flag options. For more information on available flag options, refer to tpunsubscribe(3c) in the Oracle Tuxedo ATMI C Function Reference.
|
The tppost(3c) function enables an Oracle Tuxedo ATMI client or server to post an event.
Use the following signature to call the tppost()
function:
tppost(char *eventname
, char *data
, longlen
, longflags
)
The following table describes the arguments to the tppost()
function.
Pointer to an event name containing up to 31 characters plus NULL. The first character cannot be a dot (“.”) because the dot is reserved as the first character in names of Oracle Tuxedo system-defined events. When defining event names, keep in mind that subscribers can use wildcard capabilities to subscribe to multiple events with a single function call. Using the same prefix for a category of related event names can be helpful.
|
|
Pointer to a buffer previously allocated using the tpalloc() function.
|
|
Flag options. For more information on available flag options, refer to tppost(3c) in the Oracle Tuxedo ATMI C Function Reference.
|
The following example illustrates an event posting taken from the Oracle Tuxedo system sample application bankapp
. This example is part of the WITHDRAWAL
service. One of the functions of the WITHDRAWAL
service is checking for withdrawals greater than $10,000 and posting an event called BANK_TLR_WITHDRAWAL
.
.
.
.
/* Event logic related */
static float evt_thresh = 10000.00 ; /* default for event threshold */
static char emsg[200] ; /* used by event posting logic */
.
.
.
/* Post a BANK_TLR_WITHDRAWAL event ? */
if (amt < evt_thresh) {
/* no event to post */
tpreturn(TPSUCCESS, 0,transb->data , 0L, 0);
}
/* prepare to post the event */
if ((Fchg (transf, EVENT_NAME, 0, "BANK_TLR_WITHDRAWAL", (FLDLEN)0) == -1) ||
(Fchg (transf, EVENT_TIME, 0, gettime(), (FLDLEN)0) == -1) ||
(Fchg (transf, AMOUNT, 0, (char *)&amt, (FLDLEN)0) == -1)) {
(void)sprintf (emsg, "Fchg failed for event fields: %s",
Fstrerror(Ferror)) ;
}
/* post the event */
else if (tppost ("BANK_TLR_WITHDRAWAL", /* event name */
(char *)transf, /* data */
0L, /* len */
TPNOTRAN | TPSIGRSTRT) == -1) {
/* If event broker is not reachable, ignore the error */
if (tperrno != TPENOENT)
(void)sprintf (emsg, "tppost failed: %s", tpstrerror (tperrno));
}
This example simply posts the event to the EventBroker to indicate a noteworthy occurrence in the application. Subscription to the event by interested clients, who can then take action as required, is done independently.
The following example illustrates a portion of a bankapp
application server that subscribes to BANK_TLR_.*
events, which includes the BANK_TLR_WITHDRAWAL
event shown in the previous example, as well as any other event names beginning with BANK_TLR_
. When a matching event is posted, the application notifies the subscriber via a call to a service named WATCHDOG
.
.
.
.
/* Event Subscription handles */
static long sub_ev_largeamt = 0L ;
.
.
.
/* Preset default for option 'w' - watchdog threshold */
(void)strcpy (amt_expr, "AMOUNT > 10000.00") ;
.
.
.
/*
* Subscribe to the events generated
* when a "large" amount is transacted.
*/
evctl.flags = TPEVSERVICE ;
(void)strcpy (evctl.name1, "WATCHDOG") ;
/* Subscribe */
sub_ev_largeamt = tpsubscribe ("BANK_TLR_.*",amt_expr,&evctl,TPSIGRSTRT) ;
if (sub_ev_largeamt == -1L) {
(void)userlog ("ERROR: tpsubscribe for event BANK_TLR_.* failed: %s",
tpstrerror(tperrno)) ;
return -1 ;
}
.
.
.
{
/* Unsubscribe to the subscribed events */
if (tpunsubscribe (sub_ev_largeamt, TPSIGRSTRT) == -1)
(void)userlog ("ERROR: tpunsubscribe to event BANK_TLR_.* failed: %s",
tpstrerror(tperrno)) ;
return ;
}
/*
* Service called when a BANK_TLR_.* event is posted.
*/
void
#if defined(__STDC__) || defined(__cplusplus)
WATCHDOG(TPSVCINFO *transb)
#else
WATCHDOG(transb)
TPSVCINFO *transb;
#endif
{
FBFR *transf; /* fielded buffer of decoded message */
/* Set pointr to TPSVCINFO data buffer */
transf = (FBFR *)transb->data;
/* Print the log entry to stdout */
(void)fprintf (stdout, "%20s|%28s|%8ld|%10.2f\n",
Fvals (transf, EVENT_NAME, 0),
Fvals (transf, EVENT_TIME, 0),
Fvall (transf, ACCOUNT_ID, 0),
*( (float *)CFfind (transf, AMOUNT, 0, NULL, FLD_FLOAT)) );
/* No data should be returned by the event subscriber's svc routine */
tpreturn(TPSUCCESS, 0,NULL, 0L, 0);
}
![]() ![]() ![]() |