0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <stdlib.h>
0037 #include <stdio.h>
0038 #include <ndrstandard.h>
0039 #include <atmi.h>
0040 #include <atmi_tls.h>
0041 #include <string.h>
0042 #include "thlock.h"
0043 #include "userlog.h"
0044 #include "utlist.h"
0045 #include <typed_buf.h>
0046
0047
0048
0049
0050
0051 __thread atmi_tls_t *G_atmi_tls = NULL;
0052
0053 exprivate pthread_key_t M_atmi_tls_key;
0054 exprivate pthread_key_t M_atmi_switch_key;
0055
0056 exprivate MUTEX_LOCKDECL(M_thdata_init);
0057 exprivate int M_first = EXTRUE;
0058
0059
0060
0061
0062
0063
0064 expublic void * ndrx_atmi_tls_get(long priv_flags)
0065 {
0066 atmi_tls_t *tls = G_atmi_tls;
0067 char *fn = "ndrx_atmi_tls_get";
0068 if (NULL!=tls)
0069 {
0070
0071
0072
0073 if (tls->is_auto)
0074 {
0075 pthread_setspecific( M_atmi_tls_key, NULL );
0076 }
0077
0078
0079 #ifdef NDRX_OAPI_DEBUG
0080
0081 NDRX_LOG(log_debug, "%s: G_atmi_xa_curtx.txinfo: %p",
0082 __func__, tls->G_atmi_xa_curtx.txinfo);
0083 #endif
0084
0085
0086
0087
0088 if (priv_flags & CTXT_PRIV_TRAN &&
0089 !(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOAPISUSP))
0090 {
0091 tls->global_tx_suspended = EXFALSE;
0092
0093 if (tls->G_atmi_xa_curtx.txinfo)
0094 {
0095 atmi_error_t aerr;
0096 int aerr_loaded=EXFALSE;
0097
0098
0099 if (tls->M_atmi_error)
0100 {
0101 aerr_loaded=EXTRUE;
0102 ndrx_TPsave_error(&aerr);
0103 }
0104
0105 tls->M_atmi_error = 0;
0106 if (EXSUCCEED!=ndrx_tpsuspend(&tls->tranid, 0, EXTRUE))
0107 {
0108
0109
0110
0111
0112 userlog("ndrx_atmi_tls_get: Failed to suspend transaction: [%s]",
0113 tpstrerror(tperrno));
0114 }
0115 else
0116 {
0117 tls->global_tx_suspended = EXTRUE;
0118 }
0119
0120 if (aerr_loaded)
0121 {
0122 ndrx_TPrestore_error(&aerr);
0123 }
0124
0125 }
0126 }
0127
0128
0129 G_atmi_tls = NULL;
0130
0131
0132 MUTEX_UNLOCK_V(tls->mutex);
0133 }
0134 out:
0135 return (void *)tls;
0136 }
0137
0138
0139
0140
0141
0142 expublic int ndrx_atmi_tls_set(void *data, int flags, long priv_flags)
0143 {
0144 int ret = EXSUCCEED;
0145 atmi_tls_t *tls = (atmi_tls_t *)data;
0146 char *fn = "ndrx_atmi_tls_set";
0147
0148 if (NULL!=tls)
0149 {
0150
0151 if (ATMI_TLS_MAGIG!=tls->magic)
0152 {
0153 userlog("atmi_tls_set: invalid magic! expected: %x got %x",
0154 ATMI_TLS_MAGIG, tls->magic);
0155 }
0156
0157
0158
0159
0160
0161
0162 MUTEX_LOCK_V(tls->mutex);
0163
0164
0165 tls->G_last_call.sysflags |= flags;
0166
0167 #ifdef NDRX_OAPI_DEBUG
0168 NDRX_LOG(log_debug, "%s: G_atmi_xa_curtx.txinfo: %p",
0169 __func__, tls->G_atmi_xa_curtx.txinfo);
0170 #endif
0171 G_atmi_tls = tls;
0172
0173
0174
0175
0176
0177 if (priv_flags & CTXT_PRIV_TRAN &&
0178 !(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOAPISUSP))
0179 {
0180 if(tls->global_tx_suspended)
0181 {
0182
0183 tls->M_atmi_error = 0;
0184 if (EXSUCCEED!=ndrx_tpresume(&tls->tranid, 0))
0185 {
0186 userlog("Failed to resume transaction: [%s]", tpstrerror(tperrno));
0187 }
0188 else
0189 {
0190 tls->global_tx_suspended = EXFALSE;
0191 }
0192 }
0193 }
0194
0195
0196
0197
0198 if (tls->is_auto)
0199 {
0200 pthread_setspecific( M_atmi_tls_key, (void *)tls );
0201 }
0202 }
0203 else
0204 {
0205 G_atmi_tls = NULL;
0206 }
0207
0208 out:
0209 return ret;
0210 }
0211
0212
0213
0214
0215
0216
0217 expublic void ndrx_atmi_tls_free(void *data)
0218 {
0219 atmi_tls_t *tls = (atmi_tls_t *)data;
0220 tpmemq_t *el, *elt;
0221 if (NULL!=data)
0222 {
0223 if (data == G_atmi_tls)
0224 {
0225 if (G_atmi_tls->is_auto)
0226 {
0227 pthread_setspecific( M_atmi_tls_key, NULL );
0228 }
0229 G_atmi_tls = NULL;
0230 }
0231
0232
0233
0234 MUTEX_DESTROY_V(tls->mutex);
0235
0236
0237
0238 DL_FOREACH_SAFE(tls->memq, el, elt)
0239 {
0240 if (NULL!=(el->buf))
0241 {
0242 NDRX_SYSBUF_FREE(el->buf);
0243 }
0244
0245 NDRX_FPFREE(el);
0246 }
0247
0248 if (NULL!=tls->qdisk_tls)
0249 {
0250 NDRX_FPFREE(tls->qdisk_tls);
0251 }
0252
0253 NDRX_FREE((char*)data);
0254 }
0255 }
0256
0257
0258
0259
0260
0261
0262 expublic void * ndrx_atmi_tls_new(void *tls_in, int auto_destroy, int auto_set)
0263 {
0264 int ret = EXSUCCEED;
0265 atmi_tls_t *tls = NULL;
0266
0267
0268 if (M_first)
0269 {
0270 MUTEX_LOCK_V(M_thdata_init);
0271 if (M_first)
0272 {
0273 pthread_key_create( &M_atmi_tls_key,
0274 &ndrx_atmi_tls_free );
0275
0276
0277 ndrx_tpcall_init_once();
0278 M_first = EXFALSE;
0279 }
0280 MUTEX_UNLOCK_V(M_thdata_init);
0281 }
0282
0283 if (NULL!=tls_in)
0284 {
0285 tls = (atmi_tls_t *)tls_in;
0286 NDRX_LOG(log_debug, "%s: Reusing TLS storage", __func__);
0287 }
0288 else
0289 {
0290 if (NULL==(tls = (atmi_tls_t *)NDRX_MALLOC(sizeof(atmi_tls_t))))
0291 {
0292 userlog ("%s: failed to malloc", __func__);
0293 EXFAIL_OUT(ret);
0294 }
0295 }
0296
0297
0298 tls->magic = ATMI_TLS_MAGIG;
0299
0300
0301
0302 tls->conv_cd=0;
0303
0304
0305 memset(&tls->client_init_data, 0, sizeof(tls->client_init_data));
0306
0307
0308 tls->G_atmi_is_init= 0;
0309 memset (tls->G_call_state, 0, sizeof(tls->G_call_state));
0310 tls->tpcall_get_cd=MAX_ASYNC_CALLS-2;
0311 tls->memq = NULL;
0312
0313
0314
0315 memset (tls->G_tp_conversation_status, 0, sizeof(tls->G_tp_conversation_status));
0316
0317
0318 tls->M_svc_return_code = 0;
0319 tls->tpcall_first = EXTRUE;
0320
0321
0322 tls->M_atmi_error_msg_buf[0] = EXEOS;
0323 tls->M_atmi_error = TPMINVAL;
0324 tls->M_atmi_reason = NDRX_XA_ERSN_NONE;
0325 tls->errbuf[0] = EXEOS;
0326 tls->is_associated_with_thread = EXFALSE;
0327
0328 tls->M_is_curtx_init = EXFALSE;
0329 tls->global_tx_suspended = EXFALSE;
0330 memset(&tls->G_atmi_conf, 0, sizeof(tls->G_atmi_conf));
0331 memset(&tls->G_atmi_xa_curtx, 0, sizeof(tls->G_atmi_xa_curtx));
0332
0333
0334 tls->p_unsol_handler = NULL;
0335
0336
0337 tls->tx_commit_return = TX_COMMIT_COMPLETED;
0338 tls->tx_transaction_control = TX_UNCHAINED;
0339 tls->tx_transaction_timeout = 0;
0340
0341 tls->nullbuf.autoalloc = EXFALSE;
0342 tls->nullbuf.size=0;
0343 tls->nullbuf.subtype[0]=EXEOS;
0344 tls->nullbuf.type_id=BUF_TYPE_NULL;
0345 tls->nullbuf.callinfobuf=NULL;
0346 tls->nullbuf.callinfobuf_len=0;
0347 memset(&tls->nullbuf.hh, 0, sizeof(tls->nullbuf.hh));
0348
0349 memset(&tls->integpriv, 0, sizeof(tls->integpriv));
0350
0351 MUTEX_VAR_INIT(tls->mutex);
0352
0353
0354 tls->pf_tpacall_noservice_hook = NULL;
0355
0356
0357 tls->prio = 0;
0358 tls->prio_flags=0;
0359 tls->prio_last = NDRX_MSGPRIO_DEFAULT;
0360 tls->tmnull_is_open=EXFALSE;
0361 tls->tmnull_rmid=EXFAIL;
0362
0363 tls->tout = EXFAIL;
0364 tls->tout_next = EXFAIL;
0365 tls->tout_next_eff = EXFAIL;
0366
0367 tls->qdisk_is_open=EXFALSE;
0368 tls->qdisk_rmid=EXFAIL;
0369 tls->qdisk_tls=NULL;
0370
0371 tls->atmisrv_reply_type=0;
0372
0373
0374
0375
0376 if (auto_destroy)
0377 {
0378 tls->is_auto = EXTRUE;
0379 pthread_setspecific( M_atmi_tls_key, (void *)tls );
0380 }
0381 else
0382 {
0383 tls->is_auto = EXFALSE;
0384 }
0385
0386 if (auto_set)
0387 {
0388 ndrx_atmi_tls_set(tls, 0, 0);
0389 }
0390
0391 out:
0392
0393 if (EXSUCCEED!=ret && NULL!=tls)
0394 {
0395 ndrx_atmi_tls_free((char *)tls);
0396 tls = NULL;
0397 }
0398
0399 return (void *)tls;
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409 expublic void ndrx_tpfreectxt(TPCONTEXT_T context)
0410 {
0411 atmi_tls_t * ctx = (atmi_tls_t *)context;
0412
0413 if (NULL!=ctx)
0414 {
0415
0416 if (G_atmi_tls && G_atmi_tls==context)
0417 {
0418 tplogclosereqfile();
0419 tplogclosethread();
0420 tpterm();
0421 }
0422
0423 if (NULL!=ctx->p_nstd_tls)
0424 {
0425 ndrx_nstd_tls_free(ctx->p_nstd_tls);
0426 }
0427
0428 if (NULL!=ctx->p_ubf_tls)
0429 {
0430 ndrx_ubf_tls_free(ctx->p_ubf_tls);
0431 }
0432
0433 ndrx_atmi_tls_free(ctx);
0434 }
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444 expublic int ndrx_tpsetctxt(TPCONTEXT_T context, long flags, long priv_flags)
0445 {
0446 int ret = EXSUCCEED;
0447 atmi_tls_t * ctx;
0448
0449 #ifdef NDRX_OAPI_DEBUG
0450 NDRX_LOG(log_debug, "ENTRY: %s enter, context: %p, current: %p", __func__,
0451 context, G_atmi_tls);
0452
0453 if (NULL!=context)
0454 {
0455 NDRX_LOG(log_debug, "ENTRY: is_associated_with_thread = %d",
0456 ((atmi_tls_t *)context)->is_associated_with_thread);
0457 }
0458
0459 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_NSTD = %d",
0460 (priv_flags) & CTXT_PRIV_NSTD );
0461
0462 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_UBF = %d",
0463 (priv_flags) & CTXT_PRIV_UBF );
0464
0465 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_ATMI = %d",
0466 (priv_flags) & CTXT_PRIV_ATMI );
0467
0468 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_TRAN = %d",
0469 (priv_flags) & CTXT_PRIV_TRAN );
0470
0471 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_NOCHK = %d",
0472 (priv_flags) & CTXT_PRIV_NOCHK );
0473
0474 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_IGN = %d",
0475 (priv_flags) & CTXT_PRIV_IGN );
0476 #endif
0477
0478
0479 if (context == TPNULLCONTEXT)
0480 {
0481 TPCONTEXT_T tmp;
0482 int dealloc = EXFALSE;
0483
0484
0485
0486 if (NULL!=G_atmi_tls && G_atmi_tls->is_auto)
0487 {
0488 dealloc = EXTRUE;
0489 }
0490
0491
0492 ndrx_tpgetctxt(&tmp, 0L, priv_flags);
0493
0494 if (dealloc)
0495 {
0496
0497 ndrx_tpfreectxt((TPCONTEXT_T)tmp);
0498 }
0499
0500
0501 goto out;
0502 }
0503
0504 ctx = (atmi_tls_t *)context;
0505
0506 if (!(priv_flags & CTXT_PRIV_NOCHK))
0507 {
0508
0509 if (priv_flags & CTXT_PRIV_ATMI && ATMI_TLS_MAGIG!=ctx->magic)
0510 {
0511 ndrx_TPset_error_fmt(TPENOENT, "_tpsetctxt: invalid atmi magic: "
0512 "expected: %x got %x!", ATMI_TLS_MAGIG, ctx->magic);
0513 EXFAIL_OUT(ret);
0514 }
0515
0516 if (priv_flags & CTXT_PRIV_NSTD && NULL!=ctx->p_nstd_tls
0517 && NSTD_TLS_MAGIG!=ctx->p_nstd_tls->magic)
0518 {
0519 ndrx_TPset_error_fmt(TPENOENT, "_tpsetctxt: invalid nstd magic: "
0520 "expected: %x got %x!", NSTD_TLS_MAGIG, ctx->p_nstd_tls->magic);
0521 EXFAIL_OUT(ret);
0522 }
0523
0524 if (priv_flags & CTXT_PRIV_UBF && NULL!=ctx->p_ubf_tls
0525 && UBF_TLS_MAGIG!=ctx->p_ubf_tls->magic)
0526 {
0527 ndrx_TPset_error_fmt(TPENOENT, "_tpsetctxt: invalid ubf magic: "
0528 "expected: %x got %x!", UBF_TLS_MAGIG, ctx->p_ubf_tls->magic);
0529 EXFAIL_OUT(ret);
0530 }
0531 }
0532
0533
0534
0535
0536 if (!(priv_flags & CTXT_PRIV_IGN) && G_atmi_tls!=ctx && NULL!=G_atmi_tls)
0537 {
0538 NDRX_LOG(log_warn, "Free up context %p", G_atmi_tls);
0539 tpterm();
0540 tpfreectxt((TPCONTEXT_T)G_atmi_tls);
0541 }
0542
0543
0544 if (priv_flags & CTXT_PRIV_NSTD && NULL!=ctx->p_nstd_tls &&
0545 EXSUCCEED!=ndrx_nstd_tls_set((void *)ctx->p_nstd_tls))
0546 {
0547 ndrx_TPset_error_fmt(TPESYSTEM, "_tpsetctxt: failed to restore libnstd context");
0548 EXFAIL_OUT(ret);
0549 }
0550
0551 if (priv_flags & CTXT_PRIV_UBF && NULL!=ctx->p_ubf_tls &&
0552 EXSUCCEED!=ndrx_ubf_tls_set((void *)ctx->p_ubf_tls))
0553 {
0554 ndrx_TPset_error_fmt(TPESYSTEM, "_tpsetctxt: failed to restore libubf context");
0555 EXFAIL_OUT(ret);
0556 }
0557
0558 if (priv_flags & CTXT_PRIV_ATMI)
0559 {
0560 if (EXSUCCEED!=ndrx_atmi_tls_set((void *)ctx, flags, priv_flags))
0561 {
0562 ndrx_TPset_error_fmt(TPESYSTEM, "_tpsetctxt: failed to restore libatmi context");
0563 EXFAIL_OUT(ret);
0564 }
0565
0566 ctx->is_associated_with_thread = EXTRUE;
0567 }
0568
0569 out:
0570
0571 #ifdef NDRX_OAPI_DEBUG
0572 NDRX_LOG(log_debug, "RETURN: %s returns %d, context: %p, current: %p", __func__,
0573 ret, context, G_atmi_tls);
0574 #endif
0575 return ret;
0576 }
0577
0578
0579
0580
0581
0582
0583 expublic ndrx_ctx_priv_t* ndrx_ctx_priv_get(void)
0584 {
0585 if (NULL==G_atmi_tls)
0586 {
0587 return NULL;
0588 }
0589 else
0590 {
0591 return &G_atmi_tls->integpriv;
0592 }
0593 }
0594
0595
0596
0597
0598
0599
0600
0601 expublic int ndrx_tpgetctxt(TPCONTEXT_T *context, long flags, long priv_flags)
0602 {
0603 int ret = TPMULTICONTEXTS;
0604 atmi_tls_t * ctx;
0605 char *fn="_tpgetctxt";
0606
0607 #ifdef NDRX_OAPI_DEBUG
0608 NDRX_LOG(log_debug, "ENTRY: %s enter, context: %p, current: %p",
0609 __func__, *context, G_atmi_tls);
0610
0611 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_NSTD = %d",
0612 (priv_flags) & CTXT_PRIV_NSTD );
0613
0614 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_UBF = %d",
0615 (priv_flags) & CTXT_PRIV_UBF );
0616
0617 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_ATMI = %d",
0618 (priv_flags) & CTXT_PRIV_ATMI );
0619
0620 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_TRAN = %d",
0621 (priv_flags) & CTXT_PRIV_TRAN );
0622
0623 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_NOCHK = %d",
0624 (priv_flags) & CTXT_PRIV_NOCHK );
0625
0626 NDRX_LOG(log_debug, "ENTRY: CTXT_PRIV_IGN = %d",
0627 (priv_flags) & CTXT_PRIV_IGN );
0628 #endif
0629 if (NULL==context)
0630 {
0631 ndrx_TPset_error_msg(TPEINVAL, "_tpgetctxt: context must not be NULL!");
0632 EXFAIL_OUT(ret);
0633 }
0634
0635 if (0!=flags)
0636 {
0637 ndrx_TPset_error_msg(TPEINVAL, "_tpgetctxt: flags must be 0!");
0638 EXFAIL_OUT(ret);
0639 }
0640
0641
0642 if (priv_flags & CTXT_PRIV_ATMI)
0643 {
0644 ctx = (atmi_tls_t *)ndrx_atmi_tls_get(priv_flags);
0645 }
0646 else
0647 {
0648 ctx = (TPCONTEXT_T)*context;
0649 }
0650
0651 if (NULL!=ctx)
0652 {
0653
0654 ctx->is_associated_with_thread = EXFALSE;
0655
0656 if (priv_flags & CTXT_PRIV_NSTD)
0657 {
0658 ctx->p_nstd_tls = ndrx_nstd_tls_get();
0659 }
0660
0661 if (priv_flags & CTXT_PRIV_UBF)
0662 {
0663 ctx->p_ubf_tls = ndrx_ubf_tls_get();
0664 }
0665 }
0666
0667 if (priv_flags & CTXT_PRIV_ATMI)
0668 {
0669 *context = (TPCONTEXT_T)ctx;
0670 }
0671
0672 if (NULL==ctx)
0673 {
0674 ret = TPNULLCONTEXT;
0675 }
0676 out:
0677
0678 #ifdef NDRX_OAPI_DEBUG
0679 NDRX_LOG(log_debug, "RETURN: %s returns %d, context: %p, current: %p", __func__,
0680 ret, *context, G_atmi_tls);
0681 #endif
0682
0683 return ret;
0684 }
0685
0686
0687
0688
0689
0690
0691 expublic void ndrx_ctx_auto(int is_auto)
0692 {
0693 G_atmi_tls->is_auto = is_auto;
0694 }
0695
0696