Back to home page

Enduro/X

 
 

    


0001 tpsrvgetctxdata(3)
0002 ==================
0003 :doctype: manpage
0004 
0005 
0006 NAME
0007 ----
0008 tpsrvgetctxdata - Get server context data for multi threaded server
0009 
0010 
0011 SYNOPSIS
0012 --------
0013 #include <atmi.h>
0014 
0015 char * tpsrvgetctxdata (void);
0016 
0017 char * tpsrvgetctxdata2 (char *p_buf, long *p_len);
0018 
0019 Link with '-latmisrv|-latmisrvnomain|-latmisrvinteg -latmi -lubf -lnstd 
0020 -lpthread -lrt -lm'
0021 
0022 DESCRIPTION
0023 -----------
0024 Get server context data. This function is intended to be used by XATMI server 
0025 function. When main thread service dispatcher invokes the service function, by 
0026 using *tpsrvgetctxdata()* it is possible to flip over the work load to thread. 
0027 Function allocates memory block by *malloc()* and fills with the thread data. If 
0028 global transaction is started, then it is suspended and transaction data is 
0029 written to returned context data.
0030 
0031 If the size of allocated memory block is needed to be know, then *tpsrvgetctxdata2()*
0032 can be used, for which 'p_len' is mandatory attributed. In case if 'p_buf' is NULL,
0033 the 'p_len' will be set to block size allocated. In case of 'p_buf' is not NULL
0034 i.e. using user buffer, then on input 'p_len' indicates the buffer size. The function
0035 will validate the size, if shorter than context data needed, the function will
0036 terminate with error. In case of success *tpsrvgetctxdata2()* will either return
0037 user pointer passed in 'p_buf' if was not NULL or memory block allocated by function.
0038 
0039 Returned pointer if was allocated by *tpsrvgetctxdata()* or *tpsrvgetctxdata2()* 
0040 must be freed by caller by using *tpsrvfreectxdata()* to avoid memory leak.
0041 Currently *tpsrvfreectxdata()* is just a wrapper for system function *free()*, but
0042 this can change in future.
0043 
0044 Sample app, original request goes to 'TESTSVFN' but it is servered by later by 
0045 new thread on function '_TH_TESTSVFN'.
0046 -------------------------------------------------------------------------------
0047 
0048 #include <unistd.h>     /* Symbolic Constants */
0049 #include <sys/types.h>  /* Primitive System Data Types */ 
0050 #include <errno.h>      /* Errors */
0051 #include <stdio.h>      /* Input/Output */
0052 #include <stdlib.h>     /* General Utilities */
0053 #include <pthread.h>    /* POSIX Threads */
0054 
0055 
0056 #include <ndebug.h>
0057 #include <atmi.h>
0058 #include <ndrstandard.h>
0059 #include <ubf.h>
0060 #include <test.fd.h>
0061 #include <string.h>
0062 
0063 struct thread_server
0064 {
0065     char *context_data; /* malloced by enduro/x */
0066     char *buffer; /* buffer data, managed by enduro/x */
0067 };
0068 /* note we must malloc this struct too. */
0069 typedef struct thread_server thread_server_t;
0070 
0071 /* threaded function... */
0072 void _TH_TESTSVFN (void *ptr)
0073 {
0074     int ret=EXSUCCEED;
0075     double d;
0076     int i;
0077     thread_server_t *thread_data = (thread_server_t *)ptr;
0078     UBFH *p_ub = (UBFH *)thread_data->buffer;
0079     
0080     if (EXSUCCEED!=tpinit(NULL))
0081     {
0082         NDRX_LOG(log_error, "Failed to init worker client");
0083         exit(1);
0084     }
0085     
0086     /* restore context. */
0087     if (EXSUCCEED!=tpsrvsetctxdata(thread_data->context_data, SYS_SRV_THREAD))
0088     {
0089         NDRX_LOG(log_error, "Failed to set context");
0090         exit(1);
0091     }
0092     
0093     /* free up the transport data.*/
0094     tpsrvfreectxdata(thread_data->context_data);
0095     free(thread_data);
0096     
0097     NDRX_LOG(log_debug, "TESTSVFN got call");
0098 
0099     /* Just print the buffer 
0100     Bprint(p_ub);*/
0101 
0102     tpreturn(  ret==SUCCEED?TPSUCCESS:TPFAIL,
0103                 0L,
0104                 (char *)p_ub,
0105                 0L,
0106                 0L);
0107 
0108    /* this is not the end of the life - do tpterm for this thread...! */
0109     tpterm();
0110     NDRX_LOG(log_debug, "Thread is done - terminating...!");
0111 }
0112 
0113 
0114 /* main server thread... 
0115  * NOTE: p_svc - this is local variable of enduro's main thread (on stack).
0116  * but p_svc->data - is auto buffer, will be freed when main thread returns.
0117  *                      Thus we need a copy of buffer for thread.
0118  */
0119 void TESTSVFN (TPSVCINFO *p_svc)
0120 {
0121     int ret=SUCCEED;
0122     UBFH *p_ub = (UBFH *)p_svc->data; /* this is auto-buffer */
0123     pthread_t thread;
0124     pthread_attr_t attr; 
0125     long size;
0126     char btype[16];
0127     char stype[16];
0128     
0129     pthread_attr_init(&attr);
0130     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
0131 
0132     if (0==(size = tptypes (p_svc->data, btype, stype)))
0133     {
0134         NDRX_LOG(log_error, "Zero buffer received!");
0135         exit(1);
0136     }
0137     
0138     thread_server_t *thread_data = malloc(sizeof(thread_server_t));
0139     
0140     /* not using sub-type - on tpreturn/forward for thread it will be auto-free 
0141 */
0142     thread_data->buffer =  tpalloc(btype, NULL, size);
0143     
0144     
0145     if (NULL==thread_data->buffer)
0146     {
0147         NDRX_LOG(log_error, "tpalloc failed of type %s size %ld", btype, size);
0148         exit(1);
0149     }
0150     
0151     /* copy off the request data */
0152     memcpy(thread_data->buffer, p_svc->data, size);
0153     
0154     thread_data->context_data = tpsrvgetctxdata();
0155     
0156     if (EXSUCCEED!=pthread_create (&thread, &attr, (void *) &_TH_TESTSVFN, 
0157 thread_data))
0158     {
0159         ret=FAIL;
0160         goto out;
0161     }
0162     
0163 out:
0164     if (SUCCEED==ret)
0165     {
0166         /* serve next.. */
0167         tpcontinue();
0168     }
0169     else
0170     {
0171         /* return error back */
0172         tpreturn(  TPFAIL,
0173                 0L,
0174                 (char *)p_ub,
0175                 0L,
0176                 0L);
0177     }
0178 }
0179 /*
0180  * Do initialization
0181  */
0182 int tpsvrinit(int argc, char **argv)
0183 {
0184     NDRX_LOG(log_debug, "tpsvrinit called");
0185 
0186     if (SUCCEED!=tpadvertise("TESTSV", TESTSVFN))
0187     {
0188         NDRX_LOG(log_error, "Failed to initialize TESTSV (first)!");
0189     }
0190 }
0191 
0192 /**
0193  * Do de-initialization
0194  */
0195 void tpsvrdone(void)
0196 {
0197     NDRX_LOG(log_debug, "tpsvrdone called");
0198 }
0199 
0200 -------------------------------------------------------------------------------
0201 
0202 This function is available only for XATMI servers.
0203 
0204 RETURN VALUE
0205 ------------
0206 On success, *tpsrvgetctxdata()* return pointer to context data block; on error, 
0207 NULL is returned, with *tperrno* set to indicate the error.
0208 
0209 
0210 ERRORS
0211 ------
0212 Note that *tpstrerror()* returns generic error message plus custom message with 
0213 debug info from last function call.
0214 
0215 *TPEINVAL* the 'p_len' indicates buffer shorter than needed for context data.
0216 
0217 *TPEPROTO* Global transaction was started and it was marked for abort-only, 
0218 there was any open call descriptors with-in global transaction, 
0219 
0220 *TPERMERR* Resource Manager failed (failed to suspend global transaction). The 
0221 *tpstrerror()* will provide more info from last call.
0222 
0223 *TPESYSTEM* System failure occurred during serving. See logs i.e. user log, or 
0224 debugs for more info. This could also be a problem with dynamical driver 
0225 loading.
0226 
0227 *TPEOS* System failure occurred during serving. See logs i.e. user log, or 
0228 debugs for more info.
0229 
0230 EXAMPLE
0231 -------
0232 See *atmitest/test017_srvthread/atmisv17.c* for sample code.
0233 
0234 BUGS
0235 ----
0236 Report bugs to support@mavimax.com
0237 
0238 SEE ALSO
0239 --------
0240 *tpsrvsetctxdata(3)* *tpsrvfreectxdata(3)* *tpcontinue(3)* *tpinit(3)*
0241 
0242 COPYING
0243 -------
0244 (C) Mavimax, Ltd
0245