PURPOSE

tpreturn - routine for returning from a service routine

SYNOPSIS

void tpreturn(int rval, long rcode, char *data, long len, long flags)

DESCRIPTION

tpreturn() indicates that a service routine has completed. tpreturn() acts like a return statement in the C language (i.e., when tpreturn() is called, the service routine returns to the System/T dispatcher). It is recommended that tpreturn() be called from within the service routine dispatched to ensure correct return of control to the System/T dispatcher.

tpreturn() is used to send a service's reply message. If the program receiving the reply is waiting in either tpcall(3c), tpgetrply(3c), or tprecv(3c), then after a successful call to tpreturn(), the reply is available in the receiver's buffer.

For conversational services, tpreturn() also tears down the connection. That is, the service routine cannot call tpdiscon(3c) directly. To ensure correct results, the program that connected to the conversational service should not call tpdiscon(3c); rather, it should wait for notification that the conversational service has completed (i.e., it should wait for one of the events, like TPEV_SVCSUCC or TPEV_SVCFAIL, sent by tpreturn()).

If the service routine was in transaction mode, tpreturn() places the service's portion of the transaction in a state where it may be either committed or rolled back when the transaction is completed. A service may be invoked multiple times as part of the same transaction so it is not necessarily fully committed nor rolled back until either tpcommit(3c) or tpabort(3c) is called by the originator of the transaction.

tpreturn() should be called after receiving all replies expected from service requests initiated by the service routine. Otherwise, depending on the nature of the service, either a TPESVCERR status or a TPEV_SVCERR event will be returned to the program that initiated communication with the service routine. Any outstanding replies which are not received will automatically be dropped by the communication manager. In addition, the descriptors for those replies become invalid.

tpreturn() should be called after closing all connections initiated by the service. Otherwise, depending on the nature of the service, either a TPESVCERR or a TPEV_SVCERR event will be returned to the program that initiated communication with the service routine. Also, an immediate disconnect event (i.e., TPEV_DISCONIMM) is sent over all open connections to subordinates.

Since a conversational service has only one open connection which it did not initiate, the communication manager knows over which descriptor data (and any event) should be sent. For this reason, a descriptor is not passed to tpreturn().

The following is a description of tpreturn()'s arguments. rval can be set to one of the following.

TPSUCCESS
The service has terminated successfully. If data is present, then it will be sent (barring any failures processing the return). If the caller is in transaction mode, then tpreturn() places the caller's portion of the transaction in a state such that it can be committed when the transaction ultimately commits. Note that a call to tpreturn() does not necessarily finalize an entire transaction. Also, even though the caller indicates success, if there are any outstanding replies or open connections, if any work done within the service caused its transaction to be marked rollback-only, then a failed message is sent (i.e., the recipient of the reply receives a TPESVCERR indication or a TPEV_SVCERR event). Note that if a transaction becomes rollback-only while in the service routine for any reason, then rval should be set to TPFAIL. If TPSUCCESS is specified for a conversational service, a TPEV_SVCSUCC event is generated.
TPFAIL
The service has terminated unsuccessfully from an application standpoint. An error will be reported to the program receiving the reply. That is, the call to get the reply will fail and the recipient receives a TPSVCFAIL indication or a TPEV_SVCFAIL event. If the caller is in transaction mode, then tpreturn() marks the transaction as rollback-only (note that the transaction may already be marked rollback-only). Barring any failures in processing the return, the caller's data is sent, if present. One reason for not sending the caller's data is that a transaction timeout has occurred. In this case, the program waiting for the reply will receive an error of TPETIME. If TPFAIL is specified for a conversational service, a TPEV_SVCFAIL event is generated.
TPEXIT
This value is the same as TPFAIL, with respect to completing the service, but the server will exit after the transaction is rolled back and the reply is sent back to the requester. If the server is restartable, then the server will automatically be restarted.

If rval is not set to one of these three values, then it defaults to TPFAIL.

An application defined return code, rcode, may be sent to the program receiving the service reply. This code is sent regardless of the setting of rval as long as a reply can be successfully sent (i.e., as long as the receiving call returns success or TPESVCFAIL). In addition, for conversational services, this code can be sent only if the service routine has control of the connection when it issues tpreturn(). The value of rcode is available in the receiver in the variable, tpurcode.

data points to the data portion of a reply to be sent. If data is non-NULL, it must point to a buffer previously obtained by a call to tpalloc(3c). If this is the same buffer passed to the service routine upon its invocation, then its disposition is up to the System/T dispatcher; the service routine writer does not have to worry about whether it is freed or not. In fact, any attempt by the user to free this buffer will fail. However, if the buffer passed to tpreturn() is not the same one with which the service is invoked, then tpreturn() will free that buffer. len specifies the amount of the data buffer to be sent. If data points to a buffer which does not require a length to be specified, (e.g., an FML fielded buffer), then len is ignored (and may be 0).

If data is NULL, then len is ignored. In this case, if a reply is expected by the program that invoked the service, then a reply is sent with no data. If no reply is expected, then tpreturn() frees data as necessary and returns sending no reply.

Currently, flags are reserved for future use and must be set to 0 (if set to a non-zero value, the recipient of the reply receives a TPESVCERR indication or a TPEV_SVCERR event).

If the service is conversational, there are two cases where the caller's return code and the data portion are not transmitted:

--
if the connection has already been torn down when the call is made (i.e., the caller has received TPEV_DISCONIMM on the connection), then this call simply ends the service routine and rolls back the current transaction, if one exists.
 
--
if the caller does not have control of the connection, either TPEV_SVCFAIL or TPEV_SVCERR is sent to the originator of the connection as described above. Regardless of which event the originator receives, no data is transmitted; however, if the originator receives the TPEV_SVCFAIL event, the return code is available in the originator's tpurcode variable.

RETURN VALUES

A service routine does not return any value to its caller, the System/T dispatcher; thus, it is declared as a void. Service routines, however, are expected to terminate using either tpreturn() or tpforward(3c). A conversational service routine must use tpreturn(), and cannot use tpforward(3c). If a service routine returns without using either tpreturn() or tpforward(3c) (i.e., it uses the C language return statement or just simply ``falls out of the function'') or tpforward(3c) is called from a conversational server, the server will print a warning message in the log and return a service error to the service requester. In addition, all open connections to subordinates will be disconnected immediately, and any outstanding asynchronous replies will be dropped. If the server was in transaction mode at the time of failure, the transaction is marked rollback-only. Note also that if either tpreturn() or tpforward(3c) are used outside of a service routine (e.g., in clients, or in tpsvrinit(3c) or tpsvrdone(3c)), then these routines simply return having no effect.

ERRORS

Since tpreturn() ends the service routine, any errors encountered either in handling arguments or in processing cannot be indicated to the function's caller. Such errors cause tperrno to be set to [TPESVCERR] for a program receiving the service's outcome via either tpcall(3c) or tpgetrply(3c), and cause the event, TPEV_SVCERR, to be sent over the conversation to a program using tpsend(3c) or tprecv(3c).

If either SVCTIMEOUT in the ubbconfig file or TA_SVCTIMEOUT in the TM_MIB are non-zero, an event, .SysServiceTimeout, is posted and TPESVCERR is returned when a service timeout occurs. In this case, tperrordetail(3) will return TPED_SVCTIMEOUT.

tperrordetail(3) and tpstrerrordetail(3) can be used to get additional information about an error produced by the last TUXEDO routine called in the current thread. If an error occurred, tperrordetail returns a numeric value that can be used as an argument to tpstrerrordetail to retrieve the text of the error detail.

SEE ALSO

tpalloc(3c),
tpcall(3c),
tpconnect(3c),
tpforward(3c)
tprecv(3c),
tpsend(3c),
tperrordetail(3c),
tpservice(3c),
tpstrerrordetail(3c)