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