Server API

This chapter describes functions that are used in a Tmax server and functions that are required to write a server program in ATMI. A server can act as a client, so functions that are used in a client also can be used.

1. TCS

The following describe the functions that are used in a TCS type server program.

  • Service completion functions

    tpreturn() sends a response to a client. tpforward() forwards a request to another server and ends the service.

    Function Description

    tpreturn

    Sends a response to a service request and ends the service routine.

    tpforward

    Forwards a request to another server to process a service.

  • Server initialization and termination functions

    Opens or closes a database that is connected to the application, and provides a function to process command line options. This subroutine is provided by default.

    Function Description

    tpsvrinit

    Initializes a server.

    tpsvrdone

    Ends initialization.

  • Multithread/Multicontext

    Function Description

    tpsvrthrinit

    Provides an initialization function to each thread when a service thread is created in a STD_MT type server. Supported in Tmax 5 SP2 and later.

    tpsvrthrdone

    Called when a service thread is terminated in a STD_MT type server. Supported in Tmax 5 SP2 and later.

    tpgetctxt

    Returns the currently set context ID as the first parameter of the thread that called this function.

    tpsetctxt

    Sets the context of the thread that called this function as the ID of the first parameter.

  • Unrequested message functions

    A server can send unrequested messages to clients unilaterally in Tmax. This feature is used when there is information that all clients connected to Tmax must be notified of. The clients that can receive the unrequested message must be connected to Tmax with flags set.

    Function Description

    tpsendtocli

    A server sends a message, which was registered in advance by clients, to the clients automatically without client request.

    tpgetclid

    Returns the ID of the client that is connected to the Tmax system. The ID is used for tpsendtocil().

    tpchkclid

    Checks if the client that corresponds to the client ID of the node where the server process resides is connected.

For more information about each function, refer to Tmax Reference Guide.

Service Routine Parameter

A server program consists of main(), which is provided by Tmax, and service routines. main() consists of routines that process database connections, disconnections, and command line options. Service routines receive and process requests from a client.

The server main() receives a request from a client and calls the corresponding service routine with a TPSVCINFO struct to process the request. The TPSVCINFO struct has data to be processed and information about the client that sent the request.

The TPSVCINFO struct is defined in the atmi.h header file. The following are the components of the TPSVCINFO struct.

#define XATMI_SERVICE_NAME_LENGTH 16

struct tpsvcinfo {
        char name[XATMI_SERVICE_NAME_LENGTH]; /* Requested service name */
        char *data;                           /* Request data */
        long len;                             /* Request data length */
        long flags;                           /* Service property */
        Int cd;                               /* Connection descriptor */
};
typedef struct tpsvcinfo TPSVCINFO
Member Description

name

Name of the service routine requested by a client.

data

Buffer to receive requested data from a client. This is allocated in advance with tpalloc() in the server main().

len

Length of the requested data.

flags

Notifies a service if it is in a transaction state or the caller requires a response. For example, if flags is TPTRAN, the service is in transaction mode. If flags is TPNOTRAN, the service can participate in the current transaction.

cd

Connection Descriptor. Sets the clients the response must be sent to. The server allocates the buffer in advance in main() to process the service requested by a client. It is recommended to use data in TPSVCINFO when communicating through tpreturn() or tpforward(). When accessing data in TPSVCINFO, the buffer types of the server program and the client program must be the same.

Client Program

The following is an example client program.

#include <usrinc/atmi.h>
. . .
main()
{
        struct strdata *cltdata;
        if ((cltdata = (strcut strdata *)tpalloc(“STRUCT”, “strdata”,
             sizeof(struct strdata)) ) == NULL){
                 error processing routine
        }
        . . .
        if ((tpcall (“SEL_SVC”, cltdata, 0, (char **)&cltdata, &len,
             TPNOFLAGS))== -1){
            error processing routine
        }
        . . .
}

Server Program

The following is an example service routine. main() is provided by Tmax.

#include <usrinc/atmi.h>
. . .
SEL_SVC(TPSVCINFO *msg)
/* A struct that contains client information and client request*/
{
        struct strdata *svcdata;
        /* Change the data type to match the buffer type */
        svcdata = (struct strdata *)msg->data;
        . . .
        svcdata->ip = sip;

        strcpy(msg ->data, svcdata);
        tpreturn(TPSUCCESS, 0, msg->data, sizeof(struct strdata), TPNOFLAGS);
};

1.1. tpreturn

The tpreturn() function indicates the completion of a service routine. It functions similarly to a return statement in the C language. When tpreturn() is called, the service routine returns control to the Tmax system. To return a service routine correctly, tpreturn() must be called from within the service routine itself.

A tpreturn() also sends a reply message for the service. If a program is waiting to receive a reply using tpcall(), tpgetrply(), or tprecv(), the reply will be transferred through the receiver’s buffer once tpreturn() is successfully executed.

In addition, tpreturn() allows interactive services to terminate interactive communication. A service routine cannot call tpdiscon() directly. To ensure correct behavior, a program connected to an interactive service should not call tpdiscon(). Instead, it must wait for a completion notification from the interactive service, such as a TPEV_SVCSUCC or TPEV_SVCFAIL event transmitted via tpreturn().

If a service routine is operating in transaction mode, and the client or service that invoked it did not start a transaction explicitly (i.e., tx_begin was not called), the tpreturn() will commit or roll back as part of a transaction if the return value is TPSUCCESS. A service can be invoked multiple times within the same global transaction; therefore, it will not be fully committed or rolled back until the transaction initiator explicitly calls tx_commit or tx_rollback.

tpreturn() must be called after all replies from services requested by the service routine have been received. Otherwise, a [TPESVCERR] error or a TPEV_SVCERR event may be returned to the program that communicated with the service routine, depending on service characteristics. Any replies that are not received will be automatically ignored by the Tmax system, and the corresponding descriptors will be invalidated.

Similarly, tpreturn() must be called after all interactive communication connections initiated by the service have ended. Failure to do so may result in a [TPESVCERR] error or a TPEV_SVCERR event being returned to the communicating program. Additionally, a forcible disconnection event, such as TPEV_DISCONIMM, may be sent to the service and all associated connections.

In interactive communication, if a service routine lacks communication control when calling tpreturn(), two outcomes are possible:

  1. If tpreturn() is called with rval = TPFAIL and data = NULL, a TPEV_SVCFAIL event will be sent to the communication initiator.

  2. In all other cases, a TPEV_SVCERR event will be sent. Because an interactive service can only have one interactive communication not initiated by the service itself, the Tmax system knows the descriptor to which data or events should be transmitted. For this reason, the descriptor is not passed as a parameter to tpreturn().

The following shows how to use the function with an example:

  • Prototype

    # include <atmi.h>
    void  tpreturn (int  rval, long  rcode, char  *data, long  len, long  flags)
  • Parameter

    Parameter Description

    rval

    The following are available for rval. Any other values than those listed below will all be considered TPFAIL.

    • TPSUCCESS

      The service is successfully completed. If data exists and no error occurs during a tpreturn() execution, the data will be transmitted. If the caller is in transaction mode, a part of this transaction will be determined as it can be committed. It allows the other services belonging to the transaction to be committed if all of them are successfully completed and ready for commit. But the transaction will be rolled back if any of them fails.

      Note that calling tpreturn() does not mean to complete the entire transaction. In addition, if there is any waiting reply or interactive connection or a job performed within the service tries to roll back the transaction, the message will be sent as a failure even though the caller has returned TPSUCCESS. That is, the receiver of the reply will receive a [TPESVCERR] error or TPEV_SVCERR event. Note that, if transaction is rolled back within a service routine, rval is set to TPFAIL. If TPSUCCESS returns in an interactive service, a TPEV_SVCSUCC event will occur.

    • TPFAIL

      The service is terminated due to an error in the application. The error is returned to the program that receives the reply. That is, the call to receive the reply fails and the receiver receives a [TPSVCFAIL] or TPEV_SVCFAIL event. This value cannot sent data.

      If the caller is in transaction mode and uses auto-transaction, tpreturn() will roll back the transaction. The transaction might have already been determined to be rolled back.

    • TPEXIT

      When a service is returned, this flag is used to forcibly terminate the server process. Any process closed via tpexit() can be restarted through TMM.

    • TPDOWN

      Similar to TPEXIT, but a process terminated through TPDOWN cannot be restarted using TMM.

    • TMSUCCESS

      Equivalent to TPSUCCESS.

    • TMFAIL

      Equivalent to TPFAIL.

    rcode

    The rcode is a return code defined by the user in the application. It is transmitted to the program that receives the service reply. This code is sent regardless of the rval value, as long as the reply can be successfully delivered to the client.

    The client is considered to have received the reply successfully in the following cases: * The receiving call was successful. * A reply was returned through [TPSVCFAIL]. * The client received either a TPEV_SVCSUCC or TPEV_SVCFAIL event.

    The rcode value is transferred to the receiver using the global variable tpurcode.

    data

    The reply data to be sent. If not NULL, it must indicate a buffer that was allocated by tpalloc() in advance. If the buffer is the same as the one transferred to the service routine, the Tmax systems will handle it.

    Therefore, the service routine writer does not need to take care of whether to or not to free the buffer. Indeed, if theuser attempts to free the buffer, the attempts will fail. However, if the buffer transferred with tpreturn() is not the same as the one transferred along with the service request, tpreturn() will free the buffer.

    len

    The length of the data sent.

    If the data points to a buffer that does not require a specified length, the len will be ignored (0 is used in general). But if data points to a buffer that requires a specified length, the len must not be 0. If data is NULL, the len is ignored. In this case, if the program that calls the service is waiting for a reply, the reply without any data will be transmitted. If no reply is expected, tpreturn() will free the data and returns without transmitting any reply, accordingly.

    flags

    Not currently supported. Must be set to 0.

    If the service is an interactive type, data would not be transferred in the following two cases:

    The interactive service was already disconnected when tpreturn( ) is called. That is, the caller receives TPEV_DISCONIMM event. In this case, the tpreturn() simply ends the service routine and if it is in a transaction mode, it will roll back the current transaction. In this case, the caller’s data cannot be transferred.

    If the caller does not have the communication control, either TPEV_SVCFAIL or TPEV_SVCERR event will be transferred to the communication starter as mentioned earlier. Regardless of the event that the communication starter receives, no data is transferred. If the communication starter receives the TPEV_SVCFAIL event, the return code could be used as a tpurcode variable of the starter.

  • Return Value

    The service routine does not return any value to the caller, that is, the Tmax systems. It is a rule that the service routine returns with tpreturn(). If the service routine returns using a return sentence of C language, instead of using tpreturn(), the server will return a service error to the service requester. In addition, a connection that has been kept for interactive communication is disconnected forcibly and all the replies that are waiting asynchronously are ignored.

    If the server is in transaction mode, the transaction will be rolled back. In addition, if tpreturn() is used outside the service routine, it will simply return without performing anything.

  • Error

    Since tpreturn() ends a service routine, if an error occurs while a parameter is being processed, it cannot be not transferred to the service routine, the caller. Errors are sent as follows.

    Type Description

    Synchronous/Asynchronous communication

    For programs that receive the service result through tpcall() or tpgetrply(), the tperrno is set to [TPESVCERR].

    Interactive communication

    For programs using tpsend() or tprecv(), a TPEV_SVCERR event is generated.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    
    SERVICE1(TPSVCINFO *msg)
    {
        char *buf;
        long len;
    
        buf=tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processsing }
        buf=msg->data;
        data process....
    
        ret=tpcall(“SERVICE2”, buf, sizeof(buf), &buf, &len, TPNOFLAGS);
        if (ret==-1) { error processing }
        data process....
    
        if (buf !=”SUCCESS”) {
            printf(“svc fail..\n”);
            tpreturn (TPFAIL, -1, NULL,0,0);
        }
        else {
            tpreturn(TPSUCCESS, 0, msg->data, msg->len, 0);
        }
    }
  • Related functions

    tpalloc(), tpcall(), tpconnect(), tpdiscon(), tpgetrply(), tprecv(), tpsend()

1.2. tpforward

The tpforward function terminates the current service routine and forwards the client’s request to another service routine, specified by svc.

Like tpreturn(), this function must be called within a service routine under Tmax system control. However, unlike tpreturn(), the forwarding service routine does not send a reply to the client. Instead, it transfers the responsibility for replying to the target service. After forwarding, the service routine immediately returns control to the Tmax system and can no longer perform additional operations.

A service request forwarded with tpforward() does not expect a response from the forwarding routine. Therefore, the request can be forwarded to any service without generating forwarding errors. The final service in the chain must eventually call tpreturn() to send a reply to the original client. tpforward() can also forward requests across nodes.

If the service routine is executing in transaction mode, tpforward() does not commit or roll back the transaction. The transaction must be completed by the transaction originator, using tx_commit() or tx_rollback(). If a service routine begins a transaction with tx_begin(), the transaction must be completed (committed or rolled back) before calling tpforward(). All services in a forwarding chain must either participate in the transaction or operate outside transaction mode.

tpforward() must be called only after replies for all outstanding service requests have been received. Any unreceived replies are invalidated, and the forward request will not be sent. tpforward() cannot be used in interactive communications.

The following shows the tpforward function flow:

figure 6 1
tpforward
  • Prototype

    # include <atmi.h>
    void  tpforward (char  *svc, char *data, long len, long flags)
  • Parameter

    Parameter Description

    svc

    The name of a service to receive a buffer.

    data

    If not NULL, must be a pointer to a buffer that has been previously allocated by tpalloc().

    If a buffer is the same as the one transmitted to a service routine, the Tmax system must handle this buffer. If a service routine writer attempts to release the buffer, this attempt will fail. However, if the buffer transmitted to tpforward() is not the same as the one transferred at the time of calling the service, tpforward() will release the buffer.

    len

    The length of data to be transmitted. If data indicates a buffer that does not require a specific length (e.g., a STRUCT Type buffer), len will be ignored and is set to 0. If data is NULL, len will be ignored and a request that has a data length of 0 will be transmitted.

    A service routine writer cannot regain control after calling a tpforward(), blocking transmission in the form that a TPSIGRSTRT is defined implicitly is used. Therefore, if a signal is generated during a tpforward() operation to stop an operation, processing will continued later. If a blocking condition is encountered, it will wait until a timeout occurs and then sends a service request.

    flags

    Not supported in the current version. Set to TPNOFLAGS.

  • Return Value

    A service routine does not return any value to the Tmax system, that is, a caller. In other words, a service routine will be declared as void.

  • Error

    If tpforward() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESVCERR]

    An invalid buffer is used; tpacall()/tpconnect() returns a cd; tpforward() was used instead of tpreturn() during an interactive communication; a TPEV_DISCONIMM event occurred; or an XA operation (tx_begin(), tx_rollback(), and tx_commit()) failed in transaction mode.

    [TPETIME]

    A transaction timeout occurs during a service routine or while a service request is being transmitted.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    
    SWITCH(TPSVCINFO *msg)
    {
        int switch;
        char *buf;
    
        buf = (char *)tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processing }
    
        strcpy(buf, msg->data);
        data process…
    
        if (switch>5)
           tpforward(“SERVICE1”, buf, 0, 0);
        else
           tpforward(“SERVICE2”, buf, 0, 0);
    }
  • Related functions

    tpalloc(), tpconnect(), tpreturn()

1.3. tpsvrinit

The tpsvrinit function initializes a service routine. It is called during the startup of a Tmax application server program, before any service requests are processed. Within the tpsvrinit() routine, it is possible to perform Tmax communication or define a transaction.

If the application program does not provide tpsvrinit(), a default routine provided by Tmax is called instead. For servers that belong to a server group handling transactions, the default tpsvrinit() calls tx_open() and userlog() to indicate that the server has started successfully.

Command-line parameters (CLOPT) of an application program can be passed to the server for processing by tpsvrinit(). See the CLOPT item in the SERVER section of the Tmax configuration file. The parameters are passed via argc and argv.

Since getopt() is used within the Tmax server main, optarg, optind, and opterr are available for parameter parsing and error detection within tpsvrinit().

  • Prototype

    # include <tmaxapi.h>
    int  tpsvrinit (int  argc, char  **argv)
  • Parameter

    Parameter Description

    argc

    The number of command-line parameters.

    argv

    A command-line parameter.

  • Return Value

    Return Value Description

    0

    The function call succeeded.

    Negative value

    The function call failed. No service request is received, the server process shuts down, and no error occurs.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    #include <usrinc/tmaxapi.h>
    
    EXEC SQL INCLUDE sqlca.h;
    tpsvrinit(int argc, char **argv)
    {
        EXEC SQL begin declare section;
        char user_name[30];
        char user_passwd[30];
        EXEC SQL end declare section;
        EXEC SQL CONNECT scott IDENTIFIED BY tiger;
        return(0);
    }
    
    SERVICE(TPSVCINFO *msg)
    {
        int ret, cd;
        char *buf;
        buf=tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processing }
    
        data process....
        cd=tpgetclid();
        if (cd==-1) { error processing }
        ret=tpsendtocli(cd, buf, 0, TPNOFLAGS);
        if (ret==-1) { error processing }
    
        data process....
        printf(“ Sevice end\n”);
        EXEC SQL COMMIT WORK RELEASE;
        tpreturn(TPSUCCESS, buf, strlen(buf), 0);
    }
  • Related functions

    tx_open(), tpsvrdone()

1.4. tpsvrdone

The tpsvrdone() function sets a routine to be executed when a server process is terminated. The Tmax application server’s main program (i.e., the main() provided by the Tmax system) calls tpsvrdone() before ending the process, after handling all service requests. When this routine is executed, the server process remains part of Tmax but no longer provides services. Within the tpsvrdone() routine, it is possible to perform Tmax communication or define a transaction.

If tpsvrdone() is executed while keeping an interactive connection, waiting for asynchronous replies, or during a transaction, Tmax will disconnect the interactive connection, ignore any pending asynchronous replies, and stop the transaction. The server will then be terminated immediately.

If a program does not define a tpsvrdone() routine, a default routine provided by Tmax is used. For servers that belong to a server group handling transactions, the default routine calls tx_close() and userlog() to indicate that the server is terminating. If tpreturn() or tpforward() are called within tpsvrdone(), the routine simply returns without performing any operations.

  • Prototype

    # include <tmaxapi.h>
    int tpsvrdone(void)
  • Return Value

    Since tpsvrdone() is written by the developer to perform necessary operations before terminating a server process, it does not return a value and does not produce an error.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    
    EXEC SQL INCLUDE sqlca.h;
    
    SERVICE(TPSVCINFO *msg)
    {
        int ret, cd;
        char *buf;
    
        EXEC SQL begin declare section;
        ….
        EXEC SQL end declare section;
        EXEC SQL CONNECT : scott IDENTIFIED BY : tiger;
        buf=tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processing }
        data process….
    
        cd=tpgetclid();
        if (cd==-1) { error processing }
        ret=tpsendtocli(cd, buf, 0, TPNOFLAGS);
        if (ret==-1) { error processing }
        data process....
    
        tpreturn(TPSUCCESS,0,buf, strlen(buf), 0);
    }
    
    int tpsvrdone()
    {
        printf(“ Sevice end\n”);
    }
  • Related functions

    tx_close(), tpsvrinit()

1.5. tpsvrthrinit

The tpsvrthrinit function is available only in Multithread and Multicontext servers. While a Tmax server provides tpsvrinit() for initialization when a server process starts, Multithread and Multicontext servers also provide tpsvrthrinit() for thread-specific initialization. This function is called when a new service thread is created in the thread pool, after tpsvrinit() has executed.

A thread pool operates according to the MINTHR and MAXTHR settings. When a server process starts, the number of service threads specified in MINTHR is created, and each of these threads calls tpsvrthrinit(). If no idle service threads are available, additional threads are created as needed, up to the value specified in MAXTHR. If MINTHR is set to 0, no service threads are created at startup. In this case, only tpsvrinit() is called, and the process waits until a service request arrives.

The tpsvrthrinit() function is executed after tpsvrinit() and before a thread processes its first service request. It receives the same parameters as tpsvrinit(), which are defined in the CLOPT field of the SERVER section in the configuration file. When implementing this function, developers must ensure that the parameters passed to tpsvrinit() and tpsvrthrinit() are consistent. For more information, refer to tpsvrinit.

  • Prototype

    # include <tmaxapi.h>
    int  tpsvrthrinit (int  argc, char  **argv)
  • Parameter

    Parameter Description

    argc

    The number of command-line parameters.

    argv

    A command-line parameter.

  • Return Value

    If initialization through tpsvrthrinit() fails, the function returns -1, and the server process cancels startup and shuts down.

    Return Value Description

    0

    The function call succeeded.

    Negative value

    The function call failed. The server process cancels startup and shuts down.

  • Example

    #include <stdio.h>
    #include <pthread.h>
    #include <usrinc/atmi.h>
    
    void tpsvrthrinit(int argc, char **argv)
    {
        param_t *param;
        param = get_threadspecificdata();
        if (pthread_create(&param->tid, NULL, THREAD_ROUTINE, (void *)param) != 0) {
            printf("user_create_thread failed\n");
            return -1;
        }
        pthread_mutex_init(&param->mutex, NULL);
        pthread_cond_init(&param->cond, NULL);
        return 0;
    }
    
    void tpsvrthrdone()
    {
        void *ret;
        param_t *param;
    
        param = get_threadspecificdata();
        param->state = EXIT;
        pthread_cond_signal(&param->cond);
        pthread_join(param->tid, &ret);
    
        pthread_mutex_destroy(&param->mutex);
        pthread_cond_destroy(&param->cond);
        printf("user_create_thread destroyed\n");
    }
    
    SERVICE(TPSVCINFO *msg)
    {
        param_t *param;
        param = get_threadspecificdata();
        ...
        ret = tpgetctxt(&param->ctxtid, TPNOFLAGS);
        ret = pthread_cond_signal(&param->cond);
        ...
    }
    
    void *THREAD_ROUTINE(void *arg)
    {
        param_t *param;
        param = (param_t *)arg;
    
        while(1) {
            pthread_mutex_lock(&param->mutex); {
                pthread_cond_wait(&param->cond, &param->mutex);
                if (param->state == EXIT)
                    break;
                if (tpsetctxt(param->ctxtid, TPNOFLAGS) == -1) {
                    printf("tpsetctxt(%d) failed, [tperrno:%d]", param->ctxtid, tperrno);
                    return NULL;
                }
    
                tpcall("MTOUPPER", sndbuf, 0, &rcvbuf, &rcvlen, TPNOFLAGS);
                ...
    
                if (tpsetctxt(TPNULLCONTEXT, TPNOFLAGS) == -1) {
                    printf("tpsetctxt(TPNULLCONTEXT) failed, [tperrno:%d]", tperrno);
                    return NULL;
                }
                ...
            } pthread_mutex_unlock(&param->mutex);
        }
        return NULL;
    }
  • Related function

    tpsvrthrdone()

1.6. tpsvrthrdone

The tpsvrthrdone function is available only in Multithread and Multicontext servers. When a server process is terminated, these servers terminate service threads before executing tpsvrdone(). If tpsvrthrdone() is defined, each service thread automatically calls this function when it is terminated.

Developers should implement tpsvrthrdone() to perform any necessary cleanup before a thread ends. Within this function, Tmax communication or transaction operations can be performed. If the function returns before completing required tasks, any incomplete work will be discarded when the thread terminates.

A client can also allocate a previously created context to the current client using context-related functions. Most ATMI functions operate on a per-context basis. While a client can create and use multiple contexts, only one context is active at a time.

For example, if context1 makes a tpacall(), then context1 must also be set as the current context when calling tpgetrply(). Otherwise, tpgetrply() cannot be executed normally if another context is active. For more information, refer to tpsvrdone.

  • Prototype

    # include <tmaxapi.h>
    int tpsvrthrdone(void)
  • Return Value

    Since tpsvrthrdone() is used by the developer to perform necessary operations before terminating a server process, it does not return a value and does not produce an error.

  • Example

    See the example in tpsvrdone.

  • Related function

    tpsvrthrinit()

1.7. tpgetctxt

This function returns the context ID, which is currently set in a thread, as the first parameter. This function is used differently in the client and server. For more information, refer to tpgetctxt.

1.8. tpsetctxt

This function sets the current context. This function is used differently in the client and server. For more information, refer to tpsetctxt.

1.9. tpsendtocli

The tpsendtocli function sends an unrequested message to a specified client. It is available only on servers. If tpbroadcast() sends an unsolicited message to any client connected to the Tmax systems, tpsendtocli() sends a message only to a client that has requested the service provided by the server process.

  • Prototype

    # include <tmaxapi.h>
    int  tpsendtocli (int  clid,  char  *data,  long  len,  long  flags)
  • Parameter

    Parameter Description

    clid

    A unique client number retrieved with tpgetclid().

    data

    A buffer allocated by tpalloc(). If data points to a buffer that does not require a specified length, the len value is ignored and 0 is used by default. If data points to a buffer that requires a specified length, len cannot be 0. If data is NULL, len is ignored.

    len

    The length of the buffer to be sent.

    flags

    Determines the function behavior.

    The following flags are available.

    • TPNOFLAG(0)

      Messages must be received by the client. However, if the client cannot process messages quickly enough, it may take a long time to receive the requested result.

    • TPUDP

      This flag does not indicate that communication with the client uses the UDP protocol. If a caller transmits data while the internal buffer (used for message transfer) is full, the data may be discarded. In other words, this flag allows data to be lost in situations similar to UDP communication.

    • TPFLOWCONTROL

      Checks the status of the client to determine whether another request message can be sent. If too many messages are accumulated, tpsendtocli() returns -1, and tperrno is set to TPEQFULL. This flag helps reduce the load on the Tmax system.

  • Return Value

    Return Value Description

    1

    The function call succeeded.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tpsendcli() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPEBADDESC]

    The clid is invalid.

    [TPEPROTO]

    tpsendtocli() was called under an inappropriate condition.

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

    [TPEQFULL]

    A duplicate message exists.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    #include <usrinc/tmaxapi.h>
    
    SERVICE(TPSVCINFO *msg)
    {
        int ret, clid;
        char *buf;
    
        buf = (char *)tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processing }
        strcpy(buf, msg->data);
        data process….
        clid = tpgetclid();
        if (clid==-1) { error processing }
    
        ret=tpsendtocli(clid, (char *)buf, 0, 0);
        if (ret==-1) { error processing }
        tpreturn(TPSUCCESS, 0, 0, 0);
    }
  • Related function

    tpbroadcast()

1.10. tpgetclid

The tpgetclid function retrieves the unique clid of the caller. A clid is a unique identifier for both clients and servers. For clients, it is assigned by CLH at the time of tpstart. For servers, a value starting from 'spri + max client index' is assigned. When tpgetclid() called from within a service, it returns the clid of the caller that invoked tpcall() or tpacall(). The clid is guaranteed to be unique within the domain system. Even in multi-node domain systems, each client and server is assigned a globally unique number.

When this function is used by a server, it is typically used to retrieve the ID of the client that called the service, so the server can send a message to the client using tpsendtocli(). If another service is called through tpcall or tpacall while the service is executing, the actual client’s clid cannot be retrieved.

When this function is used by a client, it returns the client’s own clid. To retrieve the clid of the original client that initiated the first tpcall() in a service chain (including secondary services relayed through tpforward()), use tpgetfclid().

  • Prototype

    #include <tmaxapi.h>
    int  tpgetclid(void)
  • Return Value

    Value Description

    An integer greater than 0

    The function call succeeded. An integer that is greater than 0, which corresponds the client’s number is returned.

    -1

    The function call failed, and an error code is set in tperrno.

  • Errors

    If tpgetclid() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    tpgetclid() was called under an inappropriate condition. For example, it was used within a client program.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    #include <usrinc/tmaxapi.h>
    
    SERVICE(TPSVCINFO *msg)
    {
        int ret, clid;
        char *buf;
    
        buf = (char *)tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processing }
        strcpy(buf, msg->data);
        data process…
    
        clid = tpgetclid();
        if (clid==-1) { error process }
    
        ret=tpsendtocli(clid, buf, strlen(buf), 0);
        if (ret==-1) { error processing }
        data process….
    
        tpreturn(TPSUCCESS,0,buf, strlen(buf), 0);
    }
  • Related function

    tpsendtocli()

1.11. tpchkclid

The tpchkclid function checks whether a client is currently connected to the node where a server process resides. When developing an RDP-type server program, if a service routine stores a connected client ID and the usermain() routine sends a message using tpsendtocli(), this function can help prevent unnecessary errors.

In RDP-type server programs, tpsendtocli() cannot be used unless the client is directly connected to the node where the server process resides.

  • Prototype

    #include <tmaxapi.h>
    int tpchkclid(int clid)
  • Parameter

    Parameter Description

    clid

    The ID of the client retrieved using tpgetclid().

  • Return Value

    Return Value Description

    -2

    The client is not connected to the local node.

    -1

    The client is not connected.

    1

    The client is correctly connected.

  • Error

    If tpchkclid() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPEINVAL]

    The client is not connected to the local node, or the specified client number is incorrect.

    [TPENOREADY]

    The client is not properly connected.

  • Example

    int _discon(char **buf)
    {
        int clid, n;
        clid = tpgetclid();
        n = tpchkclid(clid);
        if (n < 0) {
            printf(“Invalid Client\n”);
            return -1;
        }
       ...
    }
  • Related function

    tpgetclid()

2. UCS

The following describes the functions that are used in a UCS type server program.

  • Schedule related API

    In a UCS type, the user-developed usermain() routine is used like the main() routine so the usermain() routine must handle various messages received from TMM and CLH using a scheduling API.

    Function Description

    tpschedule

    Checks if a message is received in CLH or in a user-defined FD within a specified amount of time (sec).

    tpuschedule

    Checks if a message is received in CLH or in a user-defined FD within a specified amount of time (microsec).

  • Socket FD related macros

    Socket related macros are used to use a user socket FD in a USC scheduler such as tpschedule(). These macros are similar to FD_SET, FD_CLR, and FD_ISSET, which are used in a regular network program.

    Function Description

    tpsetfd

    Registers the socket FD in an external socket scheduler of the UCS process.

    tpissetfd

    Checks if a message is received in the FD.

    tpclrfd

    Releases the FD from a USC scheduler.

  • Service Forwarding

    When operating with a general host system, a server program, instead of a client, opens a socket to send and receive data. If the connection to an external host system is unstable or the service runtime is long, the server program enters a blocking state and cannot perform additional services.

    To resolve this situation, a service routine stores only the client information after receiving a client request. The service routine then sends the request to an external host. The usermain() routine is used to send the response to another service routine with the stored client information. If the service routine sends the result value to a client, a server program can perform all processes without being blocked.

    figure 10 1
    UCS Type Service Forwarding
    Function Description

    tpsavectx

    Stores the client information in a server library.

    tpgetctx

    Stores the CTX_T struct value of the server library to a user variable.

    tpcancelctx

    Deletes the CTX_T struct content from a server library.

    tprelay

    Sends client maintenance to another service routine with the client information/transaction information, which was obtained using tpgetctx() or tpsavectx(). Similar to tpforward(), which is used in a TCS type server program.

  • Asynchronous communication in the usermain() routine

    If asynchronous communication that requires a long service time is used in the usermain() routine, tpgetreply() may cause blocking, which prolongs the schedule. If the service result is processed through a callback function instead of tpgetreply(), the result value can be processed without affecting the schedule. However, if asynchronous communication occurs every time in the usermain(), which has a short loop time, the maximum number of asynchronous services may be exceeded, which generates an error.

    Function Description

    tpregcb

    Sets a callback function that processes asynchronous service requests.

    tpunregcb

    Releases the set callback function.

For more information about each function, refer to Tmax Reference Guide.

2.1. tpschedule

The tpschedule function waits for data sent from a UCS server process. It is available only in UCS-type server processes. The function sleeps for up to the specified maximum timeout period, and if data arrives within this period, it returns immediately.

tpschedule() returns after the service corresponding to the received data has been automatically executed. Therefore, the user must not execute the service manually after the data arrival.

Services are always executed by the system. Keep this in mind, even when running a UCS-type service program.

  • Prototype

    #include <ucs.h>
    int  tpschedule(int timeout)
  • Parameter

    Parameter Description

    timeout

    The amount of time to wait in seconds.

    • -1 : Only checks for data arrival and immediately returns.

    • 0 : Waits indefinitely for data to be arrived.

  • Return Value

    Return Value Description

    Positive integer

    The function call succeeded and data arrived.

    -1

    An error occurred because no data arrived within the timeout period or the function call failed. If no data arrives within the timeout period, -1 is returned and tperrno is set to 13 (TPETIME). In other cases, different error codes are set.

  • Error

    If tpschedule() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

    [TPETIME]

    No data arrived until the timeout period expired.

    [TPEPROTO]

    The function was called under an inappropriate condition. For example, it was called from within a service.

  • Example

    #include <stdio.h>
    #include <usrinc/atmi.h>
    #include <usrinc/ucs.h>
    int usermain(int argc, char *argv[])
    {
        ...
        while(1)
        {
            ...
            tpschedule(3);
            ret = tpcall(“SERVICE”, (char *)buf, strlen(buf), (char **)&buf,
                          (long *)&rlen, TPNOFLAGS);
            if (ret == -1) { error processing}
            ...
        }
    }
  • Related functions

    tpsleep(), tp_sleep(), tp_usleep()

2.2. tpuschedule

The tpuschedule function waits for data in microseconds. It is available only in UCS-type server processes. The function sleeps for up to the specified timeout period and returns immediately if data arrives within that time.

  • Prototype

    #include <ucs.h>
    int tpuschedule (int timeout)
  • Parameter

    Parameter Description

    timeout

    The amount of time to wait in microseconds.

    • –1 : Only checks for data arrival and returns immediately.

    • 0 : Waits until data arrives.

  • Return Value

    Return Value Description

    0

    No data arrived until the timeout period expired.

    Positive integer

    Data arrived before the timeout period expired.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tpuschedule() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    ...
    #include <stdio.h>
    #include <usrinc/atmi.h>
    #include <usrinc/ucs.h>
    
    int usermain(int argc, char *argv[])
    {
        ...
        while(1)
        {
            ...
            tpuschedule(3000000);
            ret = tpcall(“SERVICE”, (char *)buf, strlen(buf), (char **)&buf,
                          (long *)&rlen, TPNOFLAGS);
            if (ret == -1) { error processing }
            ...
         }
    }
  • Related function

    tpschedule()

2.3. tpsetfd

The tpsetfd function registers a socket file descriptor (fd) in the external socket scheduler of a UCS process. It is used when a UCS-type process manages user-defined sockets.

A UCS scheduler monitors both messages received on a socket fd and messages from TMM and CLH. If a message is received on a user-defined socket, tpschedule() returns a normal result (UCS_USER_MSG) without requiring an additional process. To determine which socket received the message, tpistfd() must be used.

  • Prototype

    #include <ucs.h>
    int  tpsetfd (int  fd)
  • Parameter

    Parameter Description

    fd

    The socket fd to register.

  • Return Value

    Value Description

    1

    The function call succeeded.

    -1

    The function call failed, and an error code is set in tperrno.

  • Errors

    If tpsetfd() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <errno.h>
    #include <usrinc/ucs.h>
    ...
    #define SERV_ADDR “168.126.185.129”
    #define SERV_PORT 1500
    
    int fd_read(int, char *, int);
    extern int errno;
    
    int usermain(int argc, char *argv[])
    {
        ...
        int listen_fd, n, newfd;
        struct sockaddr_in my_addr, child_addr;
        socklen_t child_len;
        buf = tpalloc(“STRING”, NULL, 0);
        if (buf == NULL){
            error processing
        }
    
        memset((void *)&my_addr, NULL, sizeof(my_addr));
        memset((void *)&child_addr, NULL, sizeof(child_addr));
        listen_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (listen_fd == -1){
            error processing
        }
    
        my_addr.sin_family = AF_INET;
        inaddr = inet_addr(SERV_ADDR);
        my_addr.sin_port = htons((unsigned short)SERV_PORT);
    
        if (inaddr != -1){
            memcpy((char *)&my_addr.sin_addr, (char *)&inaddr, sizeof(inaddr));
        }
        ret = bind(listen_fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
        if (ret == -1){
            error processing
        }
        ret = listen(listen_fd, 5);
        if (ret == -1){
            error processing
        }
    
        ret = tpsetfd(listen_fd);
        if (ret == -1){
            error processing
        }
        ...
    
        while(1) {
            n = tpschedule(10);
            ...
            if (n == UCS_USER_MSG){
                if (tpissetfd(listen_fd)) {
                    child_len = sizeof(child_addr);
                    newfd = accept(listen_fd, &child_addr, &child_len);
                    if (newfd == -1){
                        error processing
                    }
    
                ret = tpsetfd(newfd);
                if (ret == -1){
                    error processing
                }
            }
    
            if (tpissetfd(newfd)){
                /* Read the buffer from the socket */
                fd_read(newfd, buf, 1024);
                ret = tpcall(“SERVICE”, (char *)buf, sizeof(buf), (char **)&buf,
                               (long *)&rlen, TPNOFLAGS);
                if (ret == -1){
                    error processing
                }
                ...
                tpclrfd(newfd);
                close(newfd);
            }
            ...
        }
        return 1;
    }
  • Related functions

    tpclrfd(), tpissetfd()

2.4. tpissetfd

The tpissetfd function checks whether data has arrived on a socket FD from a UCS process in a server. It is used to schedule external sockets in UCS-type server processes.

  • Prototype

    #include <ucs.h>
    int  tpissetfd (int fd)
  • Parameter

    Parameter Description

    fd

    The FD in the fdset to test.

  • Return Value

    Return Value Description

    Positive value

    The message arrived.

    0

    No message arrived.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tpissetfd() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <errno.h>
    #include <usrinc/ucs.h>
    ...
    
    #define SERV_ADDR “168.126.185.129”
    #define SERV_PORT 1500
    
    int fd_read(int, char *, int);
    extern int errno;
    
    int usermain(int argc, char *argv[])
    {
        ...
        int listen_fd, n, newfd;
        struct sockaddr_in my_addr, child_addr;
        socklen_t child_len;
    
        buf = tpalloc(“STRING”, NULL, 0);
        if (buf == NULL){ error processing }
    
        memset((void *)&my_addr, NULL, sizeof(my_addr));
        memset((void *)&child_addr, NULL, sizeof(child_addr));
    
        listen_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (listen_fd == -1){ error processing }
    
        my_addr.sin_family = AF_INET;
        inaddr = inet_addr(SERV_ADDR);
        my_addr.sin_port = htons((unsigned short)SERV_PORT);
        if (inaddr != -1)
            memcpy((char *)&my_addr.sin_addr, (char *)&inaddr, sizeof(inaddr));
    
            ret = bind(listen_fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
            if (ret == -1){ error processing }
            ret = listen(listen_fd, 5);
            if (ret == -1){ error processing }
    
            tpsetfd(listen_fd);
            ...
            while(1) {
                n = tpschedule(10);
                ...
                if (n == UCS_USER_MSG){
                    if (tpissetfd(listen_fd)) {
                        child_len = sizeof(child_addr);
                        newfd = accept(listen_fd, &child_addr, &child_len);
                        if (newfd == -1){ error processing }
                        tpsetfd(newfd);
                }
                if (tpissetfd(newfd)){
                    /* Read the buffer from the socket */
                    fd_read(newfd, buf, 1024);
                    ret = tpcall(“SERVICE”, (char *)buf, sizeof(buf), (char **)&buf,
                                  (long *)&rlen, TPNOFLAGS);
                    if (ret == -1){ error processing }
                    ...
                    tpclrfd(newfd);
                    close(newfd);
                }
            ...
            }
        }
        return 1;
    }
  • Related functions

    tpissetfd(), tpsetfd()

2.5. tpclrfd

The tpclrfd function turns off a socket fd in an internal fdset of a UCS-type process. It is used for scheduling an external socket in a UCS-type server process.

  • Prototype

    #include <ucs.h>
    int  tpclrfd (int fd)
  • Parameter

    Parameter Description

    fd

    The socket of an internal fdset to be turned off.

  • Return Value

    Return Value Description

    1

    The function call succeeded.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tpclrfd() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <errno.h>
    #include <usrinc/ucs.h>
    ….
    #define SERV_ADDR “168.126.185.129”
    #define SERV_PORT 1500
    
    int fd_read(int, char *, int);
    extern int errno;
    
    int usermain(int argc, char *argv[])
    {
        ...
        int listen_fd, n, newfd;
        struct sockaddr_in my_addr, child_addr;
        socklen_t child_len;
        buf = tpalloc(“STRING”, NULL, 0);
        if (buf == NULL){ error processing }
    
        memset((void *)&my_addr, NULL, sizeof(my_addr));
        memset((void *)&child_addr, NULL, sizeof(child_addr));
        listen_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (listen_fd == -1){ error processing }
        my_addr.sin_family = AF_INET;
        inaddr = inet_addr(SERV_ADDR);
        my_addr.sin_port = htons((unsigned short)SERV_PORT);
        if (inaddr != -1){
            memcpy((char *)&my_addr.sin_addr, (char *)&inaddr, sizeof(inaddr));
        }
    
        ret = bind(listen_fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
        if (ret == -1){ error processing }
        ret = listen(listen_fd, 5);
        if (ret == -1){ error processing }
    
        tpsetfd(listen_fd);
        ...
        while(1) {
            n = tpschedule(10);
            ...
            if (n == UCS_USER_MSG){
            if (tpissetfd(listen_fd)) {
                child_len = sizeof(child_addr);
                newfd = accept(listen_fd, &child_addr, &child_len);
                if (newfd == -1){ error processing }
                tpsetfd(newfd);
            }
    
            if (tpissetfd(newfd)){
                /* Read the buffer from the socket */
                fd_read(newfd, buf, 1024);
                ret = tpcall(“SERVICE”, (char *)buf, sizeof(buf), (char **)&buf,
                             (long *)&rlen, TPNOFLAGS);
                if (ret == -1){ error processing }
                    ...
                ret = tpclrfd(newfd);
                if (ret == -1){ error processing }
                close(newfd);
            }
            ...
       }
       return 1;
    }
  • Related function

    tpissetfd()

2.6. tpsavectx

The tpsavectx function manages client information in a UCS process. This function is used along with tprelay(), which forwards a request to another service. It works in the same way as a general service program, which calls for other services as a tpforward(). Consequently, a called service sends a processing result to the client.

The tpsavectx() function can be used to communicate with an external process that has heterogeneous protocols that are time-consuming and can block channels.

The function can be used in the following format:

Client → svc1 → svc2(service, tpsavectx) → External channel
Client ← svc3 ← svc2(usermain, tprelay) ← External channel
  1. The client sends a service request to svc1.

  2. svc1 calls svc2 using tpforward (...TPNOREPLY).

  3. svc2 is a service which runs in a UCS process, and it calls tpsavectx() in a service routine to save the client information to communicate with an external system.

  4. The result is sent to a usermain and forwarded to svc3 via tprelay(). svc3 considers that svc2 has called it via tpforward(), so it finally sends the result to the client.

In this process, because svc1 calls a service via tpforward with the TPNOREPLY flag, it can prevent channel congestion. This enables a large numbers of clients to be handled with a small number of processes. Additionally, a single UCS process can act as both the sending and receiving processes. It can organize a relatively simple system with efficient system management.

  • Prototype

    #include <ucs.h>
    CTX_T * tpsavectx(void)
  • Return Value

    Return Value Description

    CTX_T

    The function call succeeded.

    NULL

    The function call failed. An error code is set in tperrno.

  • Error

    If tpsavectx() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPEPROTO]

    The tpsavectx() function must be used within a service routine. If it is used outside a service routine, a TPEPROTO error occurs. It cannot be used in tpsvrinit() or tpsvrdone().

    [TPESYSTEM]

    A memory allocation error occurred.

  • Example

    ...
    #include <stdio.h>
    #include <usrinc/ucs.h>
    
    CTX_T *ctx = NULL;
    
    usermain(int argc, char *argv[])
    {
        int ret, i;
        char *rcvbuf, *sndbuf;
        long sndlen;
    
        rcvbuf = (char *)tpalloc(“CARRAY”,NULL, 1024);
        if (rcvbuf == NULL){ error processing }
    
        i = 0;
        while(1) {
            tpschedule(1);
            if (ctx != NULL)
            {
                i++;
                if ((sndbuf = (char *)tpalloc(“CARRAY”,NULL, 1024)) == NULL)
                { error processing }
                else
                {
                    ...
                    ret = tprelay(“TPRETURN”, sndbuf, sndlen, 0, ctx);
                    if (ret==-1) { error processing }
                    data process...
                    ctx = NULL;
                    tpfree(sndbuf);
                }
            }
        }
    }
    
    int RELAY(TPSVCINFO *rqst)
    {
        ...
        ctx = tpsavectx();
        tpreturn(TPSUCCESS, 0, rqst->data, rqst->len, 0);
    }
  • Related functions

    tpreturn(), tpforward(), tprelay()

2.7. tpgetctx

The tpgetctx function copies the current client information to a CTX_T structure that was declared and allocated by the user. If tpgetctx() is used without tprelay(), the client will continue to wait for a response even after the service routine completes.

The information retrieved by tpgetctx() cannot be canceled with tpcancelctx(). Therefore, tprelay() must be used only in a service routine.

  • Prototype

    #include <tmaxapi.h>
    int tpgetctx (CTX_T *ctxp)
  • Parameter

    Parameter Description

    ctxp

    Retrieves and copies the client information stored with tpsavectx() to the CTX_T structure.

  • Example

    RELAY_SVC(TPSVCINFO *msg)
    {
        CTX_T *ctxp;
        ctxp=(CTX_T *)malloc(sizeof(CTX_T);
        ....
        ret = tpgetctx(ctxp);
        if (ret<0) {
            error process routine
        }
        .....
    }

2.8. tpcancelctx

The tpcancelctx function cancels data stored in a client context using tpsavectx(). Even if tprelay() is not executed, the service routine can terminate normally, and the result will still be returned.

tpgetctx() can be used only in a service routine.

  • Prototype

    #include <ucs.h>
    int tpcancelctx(CTX_T *ctxp);
  • Parameter

    Parameter Description

    ctxp

    Deletes a CTX_T structure saved in a library.

    • CTX_T structure definition

      typedef struct {
          int   version[4];
          char  data[CTX_USR_SIZE - 16];
      } CTX_T;
  • Example

    RELAY_SVC(TPSVCINFO *msg) {
        .....
        ctxp = (CTX_T *)tpsavectx();
        .....
        ret=tpcancelctx(ctxp);
        if (ret<0) {
              error process routine
         }
         .....
         tpreturn(TPFAIL, sqlca.sqlcode, NULL, 0, TPNOFLAGS);
    }

2.9. tprelay

The tprelay function is available only in a UCS server process. It can be used in multiple nodes. When a client requests a service, this function requests another service with information about the client. Since the service called by the function notices that it was called by the client, not the function, it returns the result to the client.

A service execution result can be sent to a client that called for a request, so a fast response can be induced with a simple structure in a UCS process. In general, this function is useful when processing a service, because it is integrated with an external application which is a program routine that can obtain results after calling a service two or three times.

If a server process is terminated after saving client information using tpsavcctx() or tpgetctx() but before a request is sent to another service using tprelay(), an error response will be sent to the service caller automatically. For more information about error responses, refer to the CTX_EREPLY option in the SERVER section of the environment configuration. These operations are supported for Tmax versions 5 SP2 or later. In earlier versions, an error response will not be sent to the service caller.

  • Prototype

    #include <ucs.h>
    int  tprelay(char *svc, char *data, long len, long flags, CTX_T *ctxp);
  • Parameter

    Parameter Description

    svc

    The service name registered in the Tmax configuration file.

    data

    The data to be sent when the service is called. If not NULL, must use a buffer allocated by tpalloc().

    len

    The length of the data to be sent. For CARRAY and X_OCTET structure array types, this parameter must be specified.

    flags

    Not currently supported. Set to TPNOFLAGS.

    ctxp

    The information structure retrieved by tpgetctx() or tpsavectx().

  • Return Value

    Return Value Description

    1

    The function call succeeded.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tprelay() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPEINVAL]

    The parameter is invalid. For example, ctxp is NULL, or an incorrect buffer is used.

    [TPESYSTEM]

    An error occurred in the Tmax system.

  • Example

    ...
    #include <stdio.h>
    #include <usrinc/ucs.h>
    CTX_T *ctx = NULL;
    
    DUMMY(TPSVCINFO *msg)
    {
        data process ...
    }
    
    usermain(int argc, char *argv[])
    {
        int ret, i;
        char *rcvbuf, *sndbuf;
        long sndlen;
    
        rcvbuf = (char *)tpalloc(“CARRAY”,NULL, 1024);
        if (rcvbuf == NULL){ error processing }
        i = 0;
    
        while(1) {
            tpschedule(1);
            if (ctx != NULL)
            {
                i++;
                if ((sndbuf = (char *)tpalloc(“CARRAY”,NULL, 1024)) == NULL)
                { error processing }
                else
                {
                     ...
                     ret = tprelay(“TPRETURN”, sndbuf, sndlen, 0, ctx);
                     if (ret==-1) { error processing }
                     data process...
                     ctx = NULL;
                     tpfree(sndbuf);
                 }
            }
        }
    }
    
    int RELAY(TPSVCINFO *rqst)
    {
       ...
       ctx = tpsavectx();
       tpreturn(TPSUCCESS, 0, rqst->data, rqst->len, 0);
    }
  • Related functions

    tpreturn(), tpforward()

2.10. tpregcb

The tpregcb function sets a routine that receives a response for an asynchronous UCS request from a server. This routine is used when a UCS type process receives a response from a server program. It is used instead of tpgetrply() in a UCS-type server process.

  • Prototype

    # include <ucs.h>
    int  tpregcb (UcsCallback)
  • Parameter

    Parameter Description

    UcsCallback

    The callback function that handles a response for an asynchronous request in a UCS.

    The UCSMSGINFO structure contains the response message information used to process asynchronous responses in UCS-type servers. The callback routine registered in the tpregcb() function receives this structure as the argument, and executes the response handling logic.

    The response message contains the user response code, error code, message type, connection descriptor, and the length of the response data and the pointer to the response data itself. The UCSMSGINFO structure is defined in the header file <ucs.h> with the following items:

    typedef struct {
            long    urcode;     /* user response code */
            int     errcode;    /* response error code */
            int     msgtype;    /* message type (used as internal identifier) */
            int     cd;         /* connection descriptor */
            int     len;        /* length of response data */
            char    *data;      /* pointer to the response data */
    } UCSMSGINFO;
    Field Description

    urcode

    The user-defined code in the response message.

    errcode

    The error code for the response.

    msgtype

    The message type identifier that is internally used.

    cd

    The connection descriptor for the response.

    len

    The actual length of the response data.

    data

    The pointer to the response data.

  • Return Value

    Return Value Description

    1

    The function call succeeded.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tpregcb() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    ...
    #include <stdio.h>
    #include <usrinc/atmi.h>
    #include <usrinc/ucs.h>
    
    void reply_receive(UCSMSGINFO *reply);
    DUMMY(TPSVCINFO *msg)
    {
        data process ….
    }
    
    int usermain(int argc, char *argv[])
    {
        int ret;
        char *buf
    
        ret = tpregcb(reply_receive);
        if (ret == -1){ error processing }
        buf=tpalloc(“STRING”, NULL, 0);
        if (buf==NULL) { error processing }
        data process…
        while(1)
        {
            ...
            tpschedule(3);
            cd = tpacall(“SERVICE”, buf, strlen(buf), TPNOFLAGS);
            if (cd < 0) { error processing }
            ...
        }
    }
    
    void reply_receive(UCSMSGINFO *reply)
    {
        rtcd = reply->errcode;
    
        if(rtcd != 0)
        {
             printf("[tperrno(%d) : %s]\n", rtcd,tpstrerror(rtcd));
             /* Error handling code */
        }
    
        printf(“data....%s\n”, reply->data);
    }
  • Related function

    tpunregcb()

2.11. tpunregcb

The tpunregcb function resets a routine that receives the response to an asynchronous request. It is used in UCS-type server processes.

  • Prototype

    #include <ucs.h>
    int  tpunregcb (void)
  • Return Value

    Return Value Description

    1

    The function call succeeded.

    -1

    The function call failed. An error code is set in tperrno.

  • Error

    If tpunregcb() fails, one of the following codes is set in tperrno.

    Error Code Description

    [TPESYSTEM]

    An error occurred in the Tmax system. Detailed information is recorded in the log file.

    [TPEOS]

    An error occurred in the operating system.

  • Example

    ...
    #include <usrinc/atmi.h>
    #include <usrinc/ucs.h>
    void reply_receive(UCSMSGINFO *reply);
    
    int usermain(int argc, char *argv[])
    {
        ...
        ret = tpregcb(reply_receive);
        if (ret == -1){ error processing  }
    
        ret = tpunregcb();
        if (ret == -1){  error processing  }
        while(1)
        {
            ...
            tpschedule(3);
            cd = tpacall(“SERVICE”, buf, strlen(buf), TPNOFLAGS);
            if (cd < 0) { error processing  }
            ...
        }
    }
    
    void reply_receive(UCSMSGINFO *reply)
    {
        printf(“first reply receive\n”);
        printf(“data....%s\n”, reply->data);
    }
  • Related function

    tpregcb()