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 
0037 
0038 
0039 
0040 
0041 
0042 
0043 #include <string.h>
0044 #include <stdio.h>
0045 #include <stdlib.h>
0046 #include <memory.h>
0047 #include <errno.h>
0048 #include <dlfcn.h>
0049 
0050 #include <atmi.h>
0051 #include <atmi_shm.h>
0052 #include <ndrstandard.h>
0053 #include <ndebug.h>
0054 #include <nstdutil.h>
0055 #include <ndrxdcmn.h>
0056 #include <userlog.h>
0057 
0058 
0059 #include <sys/mman.h>
0060 #include <sys/types.h>
0061 
0062 #include <unistd.h>
0063 #include <fcntl.h>
0064 #include <sys/stat.h>
0065 #include <sys/ipc.h>
0066 #include <xa_cmn.h>
0067 #include <tperror.h>
0068 #include <atmi_tls.h>
0069 #include "Exfields.h"
0070 #include "sys_test.h"
0071 
0072 
0073 
0074 #define XA_API_ENTRY(X) {\
0075     ATMI_TLS_ENTRY;\
0076     if (!M_is_xa_init) { \
0077         if (EXSUCCEED!=(ret = atmi_xa_init()))\
0078         {\
0079             goto out;\
0080         }\
0081     }\
0082     if (!G_atmi_tls->M_is_curtx_init)\
0083     {\
0084         if (EXSUCCEED!=(ret=atmi_xa_init_thread(X)))\
0085         {\
0086             goto out;\
0087         }\
0088     }\
0089 }\
0090 
0091 
0092 
0093 
0094 
0095 
0096 
0097 
0098 
0099 
0100 
0101 
0102 
0103 #define GENERIC_RETRY_CORE(call, retry_condition, bad_status, do_primary) do {\
0104         \
0105         if (G_atmi_env.xa_recon_times && (retry_condition))\
0106         {\
0107             if (do_primary)\
0108             {\
0109                 NDRX_LOG(log_warn, "RECON: Entry of %s() failed with %d", __func__, ret);\
0110             }\
0111             while (tries<G_atmi_env.xa_recon_times)\
0112             {\
0113                 tries++;\
0114                 NDRX_LOG(log_warn, "RECON: >>> Attempt %d type=%s. Sleeping %ld micro-sec", \
0115                         tries, (do_primary?__func__:"conn-only"), G_atmi_env.xa_recon_usleep);\
0116                 usleep(G_atmi_env.xa_recon_usleep);\
0117                 NDRX_LOG(log_warn, "RECON: Retrying...");\
0118                 \
0119                 NDRX_LOG(log_warn, "RECON: atmi_xa_close_entry()");\
0120                 atmi_xa_close_entry(EXTRUE);\
0121                 NDRX_LOG(log_warn, "RECON: atmi_xa_open_entry()");\
0122                 \
0123                 ndrx_TPunset_error();\
0124                 if (XA_OK==(ret=atmi_xa_open_entry()))\
0125                 {\
0126                     \
0127                     NDRX_LOG(log_warn, "RECON: %s() call of atmi_xa_open_entry() OK", __func__);\
0128                     if (do_primary)\
0129                     {\
0130                         NDRX_LOG(log_warn, "RECON: Retry of %s()", __func__);\
0131                         \
0132                         ndrx_TPunset_error();\
0133                         ret = (call);\
0134                         if (!(bad_status))\
0135                         {\
0136                             NDRX_LOG(log_warn, "RECON: <<< Succeed (%s)", __func__);\
0137                             break;\
0138                         }\
0139                         else\
0140                         {\
0141                             if ((retry_condition))\
0142                             {\
0143                                 NDRX_LOG(log_warn, "RECON: <<< Attempt %d. %s() failed %d", \
0144                                     tries, __func__, ret);\
0145                             }\
0146                             else\
0147                             { \
0148                                 NDRX_LOG(log_warn, "RECON: <<< Attempt %d. %s() failed %d, no continue", \
0149                                     tries, __func__, ret);\
0150                                 break;\
0151                             }\
0152                         }\
0153                     }\
0154                     else\
0155                     {\
0156                         NDRX_LOG(log_warn, "RECON: <<< Succeed (connection)");\
0157                         break;\
0158                     }\
0159                 }\
0160                 else\
0161                 {\
0162                     NDRX_LOG(log_error, "RECON: <<< Attempt %d. atmi_xa_open_entry() - "\
0163                        "fail: %d [%s]", tries, ret, atmi_xa_geterrstr(ret));\
0164                 }\
0165             } \
0166             \
0167             if (XAER_RMFAIL==ret)\
0168             {\
0169                 atmi_xa_close_entry(EXTRUE);\
0170             }\
0171         } \
0172     } while (0)
0173 
0174 
0175 
0176 
0177 
0178 
0179 #define GENERIC_RETRY(call, retry_condition, bad_status) do {\
0180         GENERIC_RETRY_CORE((call), (retry_condition), (bad_status), EXTRUE);\
0181         if (bad_status)\
0182         {\
0183             NDRX_LOG(log_error, "finally %s - fail: %d [%s]", \
0184                     __func__, ret, atmi_xa_geterrstr(ret));\
0185             ndrx_TPset_error_fmt_rsn(TPERMERR,  \
0186                     ret, "finally %s - fail: %d [%s]", \
0187                     __func__, ret, atmi_xa_geterrstr(ret));\
0188             goto out;\
0189         }\
0190     } while (0)
0191 
0192 
0193 
0194 
0195 
0196 #define GENERIC_RETRY_ENTRY(do_rollback) \
0197         \
0198         GENERIC_RETRY_CORE(0, G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error, 0, EXFALSE);\
0199         do\
0200         {\
0201             if (XA_OK!=ret)\
0202             {\
0203                 if (do_rollback)\
0204                 {\
0205                     ndrx_xa_join_fail(NULL, EXFALSE);\
0206                     atmi_xa_reset_curtx();\
0207                 }\
0208                 NDRX_LOG(log_error, "finally %s - fail: %d [%s]", \
0209                         __func__, ret, atmi_xa_geterrstr(ret));\
0210                 ndrx_TPset_error_fmt_rsn(TPERMERR,  \
0211                         ret, "finally %s - fail: %d [%s]", \
0212                         __func__, ret, atmi_xa_geterrstr(ret));\
0213                 goto out;\
0214             }\
0215         } while (0)
0216 
0217 
0218 
0219 
0220 
0221 #define GENERIC_RETRY_DEF \
0222     int tries = 0
0223 
0224 
0225 
0226 
0227 
0228 
0229 
0230 exprivate int volatile M_is_xa_init = EXFALSE;
0231 
0232 
0233 exprivate MUTEX_LOCKDECL(M_is_xa_init_lock);
0234 
0235 
0236 exprivate int atmi_xa_init_thread(int do_open);
0237 exprivate int ndrx_xa_join_fail(int *did_abort, int force_abort);
0238 
0239 
0240 
0241 
0242 
0243 
0244 
0245 
0246 
0247 
0248 exprivate struct xa_switch_t *ndrx_aix_fix(void)
0249 {
0250     return &tmnull_switch;
0251 }
0252 
0253 
0254 
0255 
0256 exprivate int atmi_xa_init_thread(int do_open)
0257 {
0258     int ret = EXSUCCEED;
0259     
0260     
0261     
0262     memset(&G_atmi_tls->G_atmi_xa_curtx, 0, sizeof(G_atmi_tls->G_atmi_xa_curtx));
0263     G_atmi_tls->M_is_curtx_init = EXTRUE;
0264     
0265 out:
0266     return ret;
0267 }
0268 
0269 
0270 
0271 
0272 expublic void atmi_xa_uninit(void)
0273 {
0274     ATMI_TLS_ENTRY;
0275     
0276     if (G_atmi_tls->M_is_curtx_init)
0277     {
0278         if (G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0279         {
0280             atmi_xa_close_entry(EXFALSE);
0281             G_atmi_tls->G_atmi_xa_curtx.is_xa_open = EXFALSE;
0282         }
0283         G_atmi_tls->M_is_curtx_init = EXFALSE;
0284     }
0285 }
0286 
0287 
0288 
0289 
0290 
0291 
0292 
0293 
0294 expublic int atmi_xa_init(void)
0295 {
0296     int ret=EXSUCCEED;
0297     void *handle; 
0298     ndrx_get_xa_switch_loader func;
0299     char *error;
0300     char *xa_flags = NULL; 
0301     int has_lock = EXFALSE;
0302     
0303     
0304     if (!M_is_xa_init)
0305     {   
0306         MUTEX_LOCK_V(M_is_xa_init_lock);
0307         has_lock=EXTRUE;
0308         
0309         
0310         if (M_is_xa_init)
0311         {
0312             goto out;
0313         }
0314     }
0315     
0316     
0317     NDRX_LOG(log_info, "Loading XA driver: [%s]", G_atmi_env.xa_driverlib);
0318     handle = dlopen (G_atmi_env.xa_driverlib, RTLD_NOW);
0319     if (!handle)
0320     {
0321         error = dlerror();
0322         NDRX_LOG(log_error, "Failed to load XA lib [%s]: %s", 
0323                 G_atmi_env.xa_driverlib, error?error:"no dlerror provided");
0324 
0325         ndrx_TPset_error_fmt(TPEOS, "Failed to load XA lib [%s]: %s", 
0326                 G_atmi_env.xa_driverlib, error?error:"no dlerror provided");
0327         EXFAIL_OUT(ret);
0328     }
0329 
0330     func = (ndrx_get_xa_switch_loader)dlsym(handle, "ndrx_get_xa_switch");
0331 
0332 
0333 
0334 
0335 
0336 
0337 #ifdef EX_OS_AIX
0338     if (ndrx_str_ends_with(G_atmi_env.xa_driverlib, "libndrxxanulls.so"))
0339     {
0340         func = ndrx_aix_fix;
0341     }
0342 #endif
0343 
0344     if (!func) 
0345     {
0346 
0347         error = dlerror();
0348         NDRX_LOG(log_error, "Failed to get symbol `ndrx_get_xa_switch' [%s]: %s", 
0349             G_atmi_env.xa_driverlib, error?error:"no dlerror provided");
0350 
0351         ndrx_TPset_error_fmt(TPESYSTEM, "Failed to get symbol `ndrx_get_xa_switch' [%s]: %s", 
0352             G_atmi_env.xa_driverlib, error?error:"no dlerror provided");
0353         EXFAIL_OUT(ret);
0354     }
0355 
0356     NDRX_LOG(log_info, "About to call ndrx_get_xa_switch()");
0357 
0358     
0359     if (NULL==(G_atmi_env.xa_sw = func()))
0360     {
0361         NDRX_LOG(log_error, "Cannot get XA switch handler - "
0362                         "`ndrx_get_xa_switch()' - returns NULL");
0363 
0364         ndrx_TPset_error_fmt(TPESYSTEM,  "Cannot get XA switch handler - "
0365                         "`ndrx_get_xa_switch()' - returns NULL");
0366         EXFAIL_OUT(ret);
0367     }
0368 
0369     NDRX_LOG(log_info, "Using XA %s", 
0370             (G_atmi_env.xa_sw->flags&TMREGISTER)?"dynamic registration":"static registration");
0371 
0372     
0373 
0374 
0375 
0376 
0377 
0378 
0379 
0380 
0381     
0382 
0383 
0384 
0385 
0386 
0387     NDRX_LOG(log_debug, "xa_flags = [%s]", G_atmi_env.xa_flags);
0388     G_atmi_env.xa_fsync_flags=0;
0389     
0390     
0391     NDRX_STRCPY_SAFE(G_atmi_env.xa_recon_retcodes_other, ",-7,");
0392     if (EXEOS!=G_atmi_env.xa_flags[0])
0393     {
0394         char *tag_ptr;
0395         
0396         char *tag_first;
0397         char *tag_token;
0398         int token_nr = 0;
0399 
0400         char *value_ptr, *value_first, *value_token;
0401 
0402         if (NULL==(xa_flags = NDRX_STRDUP(G_atmi_env.xa_flags)))
0403         {
0404             int err = errno;
0405             ndrx_TPset_error_fmt(TPEOS,  "Failed to allocate xa_flags temp buffer: %s", 
0406                     strerror(err));
0407 
0408             userlog("Failed to allocate xa_flags temp buffer: %s", strerror(err));
0409 
0410             EXFAIL_OUT(ret);
0411         }
0412 
0413         tag_first = xa_flags;
0414         NDRX_LOG(log_debug, "About token: [%s]", tag_first);
0415         while ((tag_token = strtok_r(tag_first, ";", &tag_ptr)))
0416         {
0417             if (NULL!=tag_first)
0418             {
0419                 tag_first = NULL; 
0420             }
0421 
0422             NDRX_LOG(log_debug, "Got tag [%s]", tag_token);
0423 
0424             
0425 
0426 
0427 
0428 
0429 
0430 
0431             if (0==strncmp(tag_token, NDRX_XA_FLAG_RECON_TEST, strlen(NDRX_XA_FLAG_RECON_TEST)))
0432             {
0433                 value_first = tag_token;
0434                 G_atmi_env.xa_recon_usleep = EXFAIL;
0435                 NDRX_LOG(log_warn, "Parsing RECON tag... [%s]", value_first);
0436 
0437                 while ((value_token = strtok_r(value_first, ":", &value_ptr)))
0438                 {
0439                     token_nr++;
0440                     if (NULL!=value_first)
0441                     {
0442                         value_first = NULL; 
0443                     }
0444 
0445                     switch (token_nr)
0446                     {
0447                         case 1:
0448                             
0449                             NDRX_LOG(log_debug, "RECON: 1: [%s]", value_token);
0450                             break;
0451                         case 2:
0452                             
0453                             NDRX_LOG(log_debug, "RECON: 2: [%s]", value_token);
0454                             snprintf(G_atmi_env.xa_recon_retcodes, 
0455                                     sizeof(G_atmi_env.xa_recon_retcodes),
0456                                     ",%s,", value_token);
0457 
0458                             
0459                             ndrx_str_strip(G_atmi_env.xa_recon_retcodes, "\t ");
0460 
0461                             break;
0462 
0463                         case 3:
0464                             NDRX_LOG(log_debug, "RECON: 3: [%s]", value_token);
0465                             G_atmi_env.xa_recon_times = atoi(value_token);
0466                             break;
0467                         case 4:
0468                             
0469                             NDRX_LOG(log_debug, "RECON: 4: [%s]", value_token);
0470                             G_atmi_env.xa_recon_usleep = atol(value_token)*1000;
0471                             break;
0472                         case 5:
0473                             
0474                             NDRX_LOG(log_debug, "RECON: 5: [%s]", value_token);
0475                             snprintf(G_atmi_env.xa_recon_retcodes_other, 
0476                                     sizeof(G_atmi_env.xa_recon_retcodes_other),
0477                                     ",%s,", value_token);
0478 
0479                             
0480                             ndrx_str_strip(G_atmi_env.xa_recon_retcodes_other, "\t ");
0481 
0482                             break;
0483                     }
0484                 }
0485 
0486                 if (G_atmi_env.xa_recon_usleep < 0)
0487                 {
0488                     NDRX_LOG(log_error, "Invalid [%s] settings in "
0489                             "XA_FLAGS [%s] (usleep not set)", 
0490                             NDRX_XA_FLAG_RECON, G_atmi_env.xa_flags);
0491 
0492                     ndrx_TPset_error_fmt(TPEINVAL, "Invalid [%s] settings in "
0493                             "XA_FLAGS [%s] (usleep not set)", 
0494                             NDRX_XA_FLAG_RECON, G_atmi_env.xa_flags);
0495 
0496                     EXFAIL_OUT(ret);
0497                 }
0498 
0499                 NDRX_LOG(log_error, "XA flag: [%s]: on xa_start ret codes: [%s],"
0500                         " recon number of %d times, sleep %ld "
0501                         "microseconds between attempts",
0502                         NDRX_XA_FLAG_RECON, 
0503                         G_atmi_env.xa_recon_retcodes, 
0504                         G_atmi_env.xa_recon_times, 
0505                         G_atmi_env.xa_recon_usleep);
0506             } 
0507             else if (0==strcmp(tag_token, NDRX_XA_FLAG_NOJOIN))
0508             {
0509                 ndrx_xa_nojoin(EXTRUE);
0510             }
0511             else if (0==strcmp(tag_token, NDRX_XA_FLAG_NOSTARTXID))
0512             {
0513                 ndrx_xa_nostartxid(EXTRUE);
0514             }
0515             else if (0==strcmp(tag_token, NDRX_XA_FLAG_NOSUSPEND))
0516             {
0517                 ndrx_xa_nosuspend(EXTRUE);
0518             }
0519             else if (0==strcmp(tag_token, NDRX_XA_FLAG_FSYNC))
0520             {
0521                 NDRX_LOG(log_warn, "XA FSYNC flag found");
0522                 G_atmi_env.xa_fsync_flags|=NDRX_FSYNC_FSYNC;
0523             }
0524             else if (0==strcmp(tag_token, NDRX_XA_FLAG_FDATASYNC))
0525             {
0526                 NDRX_LOG(log_warn, "XA FDATASYNC flag found");
0527                 G_atmi_env.xa_fsync_flags|=NDRX_FSYNC_FDATASYNC;
0528             }
0529             else if (0==strcmp(tag_token, NDRX_XA_FLAG_DSYNC))
0530             {
0531                 NDRX_LOG(log_warn, "XA DSYNC flag found");
0532                 G_atmi_env.xa_fsync_flags|=NDRX_FSYNC_DSYNC;
0533             }
0534             else if (0==strcmp(tag_token, NDRX_XA_FLAG_BTIGHT))
0535             {
0536                 ndrx_xa_btight(EXTRUE);
0537             }
0538 
0539         } 
0540     } 
0541         
0542     M_is_xa_init = EXTRUE;
0543     
0544     if (EXSUCCEED==ret)
0545     {
0546         NDRX_LOG(log_info, "XA lib initialized.");
0547         
0548     }
0549     
0550 out:
0551      
0552     if (has_lock)
0553     {
0554         MUTEX_UNLOCK_V(M_is_xa_init_lock);
0555     }
0556 
0557     if (NULL!=xa_flags)
0558     {
0559         NDRX_FREE(xa_flags);
0560     }
0561 
0562     if (EXSUCCEED!=ret && NULL!=handle)
0563     {
0564         
0565         dlclose(handle);
0566     }
0567 
0568     return ret;
0569 }
0570 
0571 
0572 
0573 
0574 
0575 
0576 
0577 
0578 
0579 expublic int atmi_xa_open_entry(void)
0580 {
0581     int ret = EXSUCCEED;
0582     XA_API_ENTRY(EXFALSE); 
0583     
0584     NDRX_LOG(log_debug, "atmi_xa_open_entry RMID=%hd", G_atmi_env.xa_rmid);
0585     
0586     if (G_atmi_tls->G_atmi_xa_curtx.is_xa_open 
0587             && !G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error)
0588     {
0589         NDRX_LOG(log_warn, "xa_open_entry already called for context!");
0590         goto out;
0591     }
0592     
0593     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_open_entry(G_atmi_env.xa_open_str, 
0594                                     G_atmi_env.xa_rmid, 0)))
0595     {
0596         
0597         if (XAER_RMERR==ret)
0598         {
0599             ret = XAER_RMFAIL;
0600             NDRX_LOG(log_error, "atmi_xa_open_entry ret XAER_RMERR remapping to XAER_RMFAIL");
0601         }
0602 
0603         NDRX_LOG(log_error, "atmi_xa_open_entry - fail: %d [%s]", 
0604                 ret, atmi_xa_geterrstr(ret));
0605         
0606         
0607         ndrx_TPset_error_fmt_rsn(TPERMERR,  ret, "atmi_xa_open_entry - fail: %d [%s]", 
0608                 ret, atmi_xa_geterrstr(ret));
0609         
0610         goto out;
0611     }
0612     
0613     G_atmi_tls->G_atmi_xa_curtx.is_xa_open = EXTRUE;
0614     
0615     
0616     if (G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error)
0617     {
0618         NDRX_LOG(log_warn, "RECON: Marking resource connection as OK");
0619         G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error = EXFALSE;
0620     }
0621     
0622     NDRX_LOG(log_info, "XA interface open");
0623     
0624 out:
0625     return ret;
0626 }
0627 
0628 
0629 
0630 
0631 
0632 
0633 
0634 expublic int atmi_xa_close_entry(int for_retry)
0635 {
0636     int ret = EXSUCCEED;
0637     XA_API_ENTRY(EXTRUE); 
0638     
0639     NDRX_LOG(log_debug, "atmi_xa_close_entry");
0640     
0641     if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0642     {
0643         NDRX_LOG(log_warn, "xa_close_entry already called for context!");
0644         goto out;
0645     }
0646     
0647     
0648     if (for_retry)
0649     {
0650         NDRX_LOG(log_warn, "RECON: Marking resource connection as ERROR");
0651         G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error = EXTRUE;
0652     }
0653     else
0654     {
0655         G_atmi_tls->G_atmi_xa_curtx.is_xa_open = EXFALSE;
0656     
0657     if (G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error)
0658     {
0659             NDRX_LOG(log_warn, "RECON: Resource connection was marked as ERROR. "
0660                     "Normal close, clearing flag");
0661             G_atmi_tls->G_atmi_xa_curtx.is_xa_conn_error = EXFALSE;
0662     }
0663     }
0664     
0665     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_close_entry(G_atmi_env.xa_close_str, 
0666                                     G_atmi_env.xa_rmid, 0)))
0667     {
0668         NDRX_LOG(log_error, "atmi_xa_close_entry - fail: %d [%s]", 
0669                 ret, atmi_xa_geterrstr(ret));
0670         
0671         if (!for_retry)
0672         {
0673             
0674             ndrx_TPset_error_fmt_rsn(TPERMERR,  ret, "atmi_xa_close_entry - fail: %d [%s]", 
0675                     ret, atmi_xa_geterrstr(ret));
0676         }
0677         goto out;
0678     }
0679     
0680 out:
0681     return ret;
0682 }
0683 
0684 
0685 
0686 
0687 
0688 
0689 
0690 exprivate int is_error_in_recon_list(char *list, int retcode)
0691 {
0692     char scanstr[16];
0693     char scanstr2[4] = ",*,";
0694     int ret = EXFALSE;
0695     
0696     snprintf(scanstr, sizeof(scanstr), ",%d,", retcode);
0697     
0698     NDRX_LOG(log_warn, "%s testing return code [%s] in recon list [%s]", 
0699             __func__, scanstr, list);
0700     
0701     if (NULL!=strstr(list, scanstr))
0702     {
0703         NDRX_LOG(log_warn, "matched by code - DO RETRY");
0704         ret = EXTRUE;
0705         goto out;
0706     }
0707     else if (NULL!=strstr(list, scanstr2))
0708     {
0709         NDRX_LOG(log_warn, "matched by wildcard - DO RETRY");
0710         ret = EXTRUE;
0711         goto out;
0712     }
0713     
0714 out:
0715     return ret;
0716     
0717 }
0718 
0719 
0720 
0721 
0722 
0723 
0724 
0725 expublic int atmi_xa_start_entry(XID *xid, long flags, int silent_err)
0726 {
0727     int ret = EXSUCCEED;
0728     int need_retry;
0729     GENERIC_RETRY_DEF;
0730     XA_API_ENTRY(EXTRUE);
0731     
0732     NDRX_LOG(log_debug, "%s", __func__);
0733     
0734     
0735     GENERIC_RETRY_ENTRY(EXFALSE);
0736     
0737     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_start_entry(xid, 
0738                                     G_atmi_env.xa_rmid, flags)))
0739     {
0740         if ((flags & TMJOIN || flags & TMRESUME) && XAER_NOTA==ret)
0741         {
0742             need_retry = EXFALSE;
0743         }
0744         else
0745         {
0746             need_retry = EXTRUE;
0747         }
0748         
0749         if (!silent_err || need_retry)
0750         {
0751             NDRX_LOG(log_error, "%s - fail: %d [%s]", 
0752                     __func__, ret, atmi_xa_geterrstr(ret));
0753         }
0754 
0755         
0756         GENERIC_RETRY_CORE(
0757             (G_atmi_env.xa_sw->xa_start_entry(xid, G_atmi_env.xa_rmid, flags))
0758             , (need_retry && is_error_in_recon_list(G_atmi_env.xa_recon_retcodes, ret))
0759             , (XA_OK!=ret)
0760             , EXTRUE);
0761 
0762         if (XA_OK!=ret)
0763         {
0764             if (silent_err && (XAER_NOTA==ret || XAER_DUPID==ret))
0765             {
0766                 
0767                 ndrx_TPset_error_fmt_rsn_silent(TPERMERR,  
0768                         ret, "finally %s - fail: %d [%s]", 
0769                         __func__, ret, atmi_xa_geterrstr(ret));
0770             }
0771             else
0772             {
0773                 NDRX_LOG(log_error, "finally %s - fail: %d [%s]", 
0774                         __func__, ret, atmi_xa_geterrstr(ret));
0775 
0776                 ndrx_TPset_error_fmt_rsn(TPERMERR,  
0777                         ret, "finally %s - fail: %d [%s]", 
0778                         __func__, ret, atmi_xa_geterrstr(ret));
0779             }
0780             goto out;
0781         }
0782     }
0783     
0784 out:
0785     return ret;
0786 }
0787 
0788 
0789 
0790 
0791 
0792 
0793 
0794 
0795 
0796 
0797 
0798 expublic int atmi_xa_end_entry(XID *xid, long flags, int aborting)
0799 {
0800     int ret = EXSUCCEED;
0801     char stat;
0802     UBFH *p_ub = NULL;
0803     int local_rb = EXFALSE;
0804     GENERIC_RETRY_DEF;
0805     
0806     XA_API_ENTRY(EXTRUE);
0807     
0808     NDRX_LOG(log_debug, "atmi_xa_end_entry flags %ld", flags);
0809     
0810     GENERIC_RETRY_ENTRY(EXFALSE);
0811     
0812     
0813     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_end_entry(xid, 
0814                                     G_atmi_env.xa_rmid, flags)))
0815     {
0816         
0817         GENERIC_RETRY(
0818             (G_atmi_env.xa_sw->xa_end_entry(xid, G_atmi_env.xa_rmid, flags))
0819             , (is_error_in_recon_list(G_atmi_env.xa_recon_retcodes_other, ret))
0820             , (XA_OK!=ret)
0821             );
0822     }
0823     
0824     
0825 
0826     if (G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOSTARTXID)
0827     {
0828         NDRX_LOG(log_debug, "NOSTARTXID - preparing at end!");
0829         if (aborting && G_atmi_env.pf_xa_loctxabort)
0830         {
0831             NDRX_LOG(log_info, "Aborting using local rollback func");
0832             local_rb = EXTRUE;
0833             ret = G_atmi_env.pf_xa_loctxabort(xid, TMNOFLAGS);
0834             
0835             if (XA_OK!=ret)
0836             {
0837                 NDRX_LOG(log_error, "Failed to disconnect from transaction: %d", ret);
0838                 userlog("Failed to disconnect from transaction: %d", ret);
0839             }
0840         }
0841         
0842 
0843 
0844 
0845 
0846         else if (XA_OK!=(ret=atmi_xa_prepare_entry(xid, TMNOFLAGS)) && XA_RDONLY!=ret)
0847         {
0848             NDRX_LOG(log_error, "Failed to prepare transaction at NOSTARTXID end");
0849             goto out;
0850         }
0851         
0852         
0853         if ((XA_OK==ret || XA_RDONLY == ret) &&
0854                 NDRX_SYSTEST_ENBLD && ndrx_systest_case(NDRX_SYSTEST_ENDPREPFAIL))
0855         {
0856             NDRX_LOG(log_error, "SYSTEST! Generating end-fail error");
0857             atmi_xa_rollback_entry(xid, 0L);
0858             ret = XAER_RMERR;
0859         }
0860         
0861         
0862 
0863 
0864 
0865         if (local_rb)
0866         {
0867             stat = XA_RM_STATUS_ABORTED;
0868         }
0869         else if (XA_OK==ret)
0870         {
0871             stat = XA_RM_STATUS_PREP;
0872         }
0873         else if (XA_RDONLY==ret)
0874         {
0875             stat = XA_RM_STATUS_COMMITTED_RO;
0876         }
0877         else
0878         {
0879             
0880             stat = XA_RM_STATUS_ABORTED;
0881         }
0882         
0883         
0884         
0885         
0886 
0887 
0888 
0889         
0890         NDRX_LOG(log_debug, "Reporting branch transaction status: %c", stat);
0891         p_ub = atmi_xa_call_tm_rmstatus(G_atmi_tls->G_atmi_xa_curtx.txinfo, stat);
0892         
0893         
0894         if (TPEMATCH==tperrno)
0895         {
0896             NDRX_LOG(log_error, "Got matching error! Abort transaction");
0897             atmi_xa_rollback_entry(xid, 0L);
0898         }
0899         
0900     }
0901     
0902     
0903 out:
0904     if (NULL!=p_ub)
0905     {
0906         tpfree((char *)p_ub);
0907     }
0908                                 
0909     return ret;
0910 }
0911 
0912 
0913 
0914 
0915 
0916 
0917 
0918 expublic int atmi_xa_rollback_entry(XID *xid, long flags)
0919 {
0920     int ret = EXSUCCEED;
0921     GENERIC_RETRY_DEF;
0922     XA_API_ENTRY(EXTRUE);
0923     
0924     NDRX_LOG(log_debug, "atmi_xa_rollback_entry");
0925     
0926     GENERIC_RETRY_ENTRY(EXFALSE);
0927     
0928     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_rollback_entry(xid, 
0929                                     G_atmi_env.xa_rmid, flags)))
0930     {
0931         
0932 
0933 
0934         GENERIC_RETRY(
0935             (G_atmi_env.xa_sw->xa_rollback_entry(xid, G_atmi_env.xa_rmid, flags))
0936             , (is_error_in_recon_list(G_atmi_env.xa_recon_retcodes_other, ret))
0937             , (XA_OK!=ret)
0938             );
0939     }
0940     
0941 out:
0942     return ret;
0943 }
0944 
0945 
0946 
0947 
0948 
0949 
0950 
0951 expublic int atmi_xa_prepare_entry(XID *xid, long flags)
0952 {
0953     int ret = EXSUCCEED;
0954     GENERIC_RETRY_DEF;
0955     XA_API_ENTRY(EXTRUE);
0956     
0957     NDRX_LOG(log_debug, "atmi_xa_prepare_entry");
0958     
0959     GENERIC_RETRY_ENTRY(EXFALSE);
0960      
0961     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_prepare_entry(xid, 
0962                                     G_atmi_env.xa_rmid, flags)))
0963     {
0964         
0965         if (XA_RDONLY==ret)
0966         {
0967             NDRX_LOG(log_debug, "xa_prepare_entry - fail: %d [%s]", 
0968                 ret, atmi_xa_geterrstr(ret));
0969             ndrx_TPset_error_fmt_rsn(TPERMERR,  ret, "xa_prepare_entry - fail: %d [%s]", 
0970                 ret, atmi_xa_geterrstr(ret));
0971         }
0972         else
0973         {
0974             GENERIC_RETRY(
0975                 (G_atmi_env.xa_sw->xa_prepare_entry(xid, G_atmi_env.xa_rmid, flags))
0976                 , (is_error_in_recon_list(G_atmi_env.xa_recon_retcodes_other, ret))
0977                 , (XA_OK!=ret)
0978                  );
0979 
0980         }
0981         
0982         
0983         goto out;
0984     }
0985     
0986 out:
0987     return ret;
0988 }
0989 
0990 
0991 
0992 
0993 
0994 
0995 
0996 expublic int atmi_xa_forget_entry(XID *xid, long flags)
0997 {
0998     int ret = EXSUCCEED;
0999     GENERIC_RETRY_DEF;
1000     XA_API_ENTRY(EXTRUE);
1001     
1002     NDRX_LOG(log_debug, "atmi_xa_forget_entry");
1003      
1004     GENERIC_RETRY_ENTRY(EXFALSE);
1005     
1006     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_forget_entry(xid, 
1007                                     G_atmi_env.xa_rmid, flags)))
1008     {
1009         
1010 
1011 
1012         GENERIC_RETRY(
1013                (G_atmi_env.xa_sw->xa_forget_entry(xid, G_atmi_env.xa_rmid, flags))
1014                , (is_error_in_recon_list(G_atmi_env.xa_recon_retcodes_other, ret))
1015                , (XA_OK!=ret)
1016                 );
1017     }
1018     
1019 out:
1020     return ret;
1021 }
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029 
1030 expublic int atmi_xa_commit_entry(XID *xid, long flags)
1031 {
1032     int ret = EXSUCCEED;
1033     GENERIC_RETRY_DEF;
1034     XA_API_ENTRY(EXTRUE);
1035     
1036     GENERIC_RETRY_ENTRY(EXFALSE);
1037     NDRX_LOG(log_debug, "atmi_xa_commit_entry");
1038     if (XA_OK!=(ret = G_atmi_env.xa_sw->xa_commit_entry(xid, 
1039                                     G_atmi_env.xa_rmid, flags)))
1040     {
1041         GENERIC_RETRY(
1042                 (G_atmi_env.xa_sw->xa_commit_entry(xid,G_atmi_env.xa_rmid, flags))
1043                 , (XAER_RMFAIL==ret)
1044                 , (XA_OK!=ret));
1045     }
1046     
1047 out:
1048     return ret;
1049 }
1050 
1051 
1052 
1053 
1054 
1055 
1056 
1057 
1058 
1059 expublic int atmi_xa_recover_entry(XID *xids, long count, int rmid, long flags)
1060 {
1061     int ret = EXSUCCEED;
1062     GENERIC_RETRY_DEF;
1063     XA_API_ENTRY(EXTRUE);
1064     
1065     NDRX_LOG(log_debug, "%s", __func__);
1066     
1067     GENERIC_RETRY_ENTRY(EXFALSE);
1068     
1069     if (0 > (ret = G_atmi_env.xa_sw->xa_recover_entry(xids, count,
1070                                     G_atmi_env.xa_rmid, flags)))
1071     {
1072         GENERIC_RETRY(
1073             (G_atmi_env.xa_sw->xa_recover_entry(xids, count, G_atmi_env.xa_rmid, flags))
1074             , (is_error_in_recon_list(G_atmi_env.xa_recon_retcodes_other, ret))
1075             , (0 > ret)
1076             );
1077     }
1078     
1079 out:
1080     return ret;
1081 }
1082 
1083 
1084 
1085 
1086 
1087 
1088 
1089 
1090 
1091 
1092 
1093 
1094 
1095 
1096 
1097 expublic int ndrx_tpbegin(unsigned long timeout, long flags)
1098 {
1099     int ret=EXSUCCEED;
1100     UBFH *p_ub = atmi_xa_alloc_tm_call(ATMI_XA_TPBEGIN);
1101     atmi_xa_tx_info_t xai;
1102     long tmflags = 0;
1103     GENERIC_RETRY_DEF;
1104     XA_API_ENTRY(EXTRUE); 
1105     
1106     NDRX_LOG(log_debug, "%s enter", __func__);
1107     
1108     memset(&xai, 0, sizeof(atmi_xa_tx_info_t));
1109     
1110     
1111     if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
1112     {
1113         NDRX_LOG(log_error, "tpbegin: - tpopen() was not called!");
1114         ndrx_TPset_error_msg(TPEPROTO,  "tpbegin - tpopen() was not called!");
1115         EXFAIL_OUT(ret);
1116     }
1117 
1118     if (0!=flags)
1119     {
1120         NDRX_LOG(log_error, "tpbegin: flags != 0");
1121         ndrx_TPset_error_msg(TPEINVAL,  "tpbegin: flags != 0");
1122         EXFAIL_OUT(ret);
1123     }
1124     
1125     
1126     if (G_atmi_tls->G_atmi_xa_curtx.txinfo)
1127     {
1128         NDRX_LOG(log_error, "tpbegin: - already in transaction mode XID: [%s]", 
1129                 G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1130         ndrx_TPset_error_fmt(TPEPROTO,  "tpbegin: - already in transaction mode XID: [%s]", 
1131                 G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1132         EXFAIL_OUT(ret);
1133     }
1134     
1135     NDRX_LOG(log_debug, "About to call TM");
1136     
1137     if (EXSUCCEED!=Bchg(p_ub, TMTXTOUT, 0, (char *)&timeout, 0L))
1138     {
1139         ndrx_TPset_error_fmt(TPESYSTEM,  "tpbegin: - failed to fill FB - set TMTXTOUT!");
1140         EXFAIL_OUT(ret);
1141     }
1142     
1143     if (XA_IS_DYNAMIC_REG)
1144     {
1145         
1146 
1147 
1148         tmflags|=TMFLAGS_DYNAMIC_REG;
1149     }
1150     
1151     if (G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOSTARTXID)
1152     {
1153         tmflags|=TMFLAGS_TPNOSTARTXID;
1154     }
1155     
1156     if (EXSUCCEED!=Bchg(p_ub, TMTXFLAGS, 0, (char *)&tmflags, 0L))
1157     {
1158         ndrx_TPset_error_fmt(TPESYSTEM,  "tpbegin: - failed to fill FB - set TMTXFLAGS!");
1159         EXFAIL_OUT(ret);
1160     }
1161     
1162     
1163     if (NULL==(p_ub=atmi_xa_call_tm_generic_fb(ATMI_XA_TPBEGIN, NULL, EXTRUE, EXFAIL, 
1164             NULL, p_ub)))
1165     {
1166         NDRX_LOG(log_error, "Failed to execute TM command [%c]", 
1167                     ATMI_XA_TPBEGIN);
1168         
1169         EXFAIL_OUT(ret);
1170     }
1171     
1172 
1173 
1174     
1175     if (EXSUCCEED!=atmi_xa_read_tx_info(p_ub, &xai, 0))
1176     {
1177         NDRX_LOG(log_error, "tpbegin: - failed to read TM response");
1178         ndrx_TPset_error_msg(TPEPROTO,  "tpbegin: - failed to read TM response");
1179         EXFAIL_OUT(ret);
1180     }
1181     
1182     NDRX_LOG(log_debug, "About to load tx info");
1183     
1184     
1185     if (EXSUCCEED!= atmi_xa_set_curtx_from_xai(&xai))
1186     {
1187         NDRX_LOG(log_error, "tpbegin: - failed to set curren tx");
1188         ndrx_TPset_error_msg(TPEPROTO,  "tpbegin: - failed to set curren tx");
1189         EXFAIL_OUT(ret);
1190     }
1191     
1192     G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags |= XA_TXINFO_INITIATOR;
1193     
1194     
1195     if (!XA_IS_DYNAMIC_REG)
1196     {
1197         if (EXSUCCEED!=atmi_xa_start_entry(atmi_xa_get_branch_xid(&xai, xai.btid), 
1198                 TMNOFLAGS, EXFALSE))
1199         {
1200             
1201             NDRX_LOG(log_error, "Failed to join transaction!");
1202             ndrx_xa_join_fail(NULL, EXFALSE);
1203             atmi_xa_reset_curtx();
1204             EXFAIL_OUT(ret);
1205         }
1206         
1207         
1208 
1209 
1210     }
1211     else
1212     {
1213         NDRX_LOG(log_debug, "Working in dynamic mode...");
1214         
1215         GENERIC_RETRY_ENTRY(EXTRUE);
1216     }
1217 
1218     NDRX_LOG(log_debug, "Process joined to transaction [%s] OK",
1219                         G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1220     
1221 out:
1222 
1223     
1224     if (NULL!=p_ub)
1225     {
1226         
1227         atmi_error_t err;
1228         
1229         
1230         ndrx_TPsave_error(&err);
1231         tpfree((char *)p_ub);  
1232         ndrx_TPrestore_error(&err);
1233     }
1234     return ret;
1235 }
1236 
1237 
1238 
1239 
1240 
1241 
1242 
1243 
1244 
1245 
1246 expublic int ndrx_tpscmt(long flags)
1247 {
1248     int ret = EXSUCCEED;
1249     
1250     if (TP_CMT_LOGGED!=flags &&
1251             TP_CMT_COMPLETE!=flags)
1252     {
1253         NDRX_LOG(log_error, "Invalid value: commit return %ld", (long)flags);
1254         ndrx_TPset_error_fmt(TPEINVAL,  "Invalid value: commit return %ld", 
1255                 (long)flags);
1256         EXFAIL_OUT(ret);
1257     }
1258     
1259     if (TX_COMMIT_COMPLETED==G_atmi_tls->tx_commit_return)
1260     {
1261         ret = TP_CMT_COMPLETE;
1262     }
1263     else
1264     {
1265         ret = TP_CMT_LOGGED;
1266     }
1267     
1268     if (TP_CMT_COMPLETE==flags)
1269     {
1270         G_atmi_tls->tx_commit_return = TX_COMMIT_COMPLETED;
1271     }
1272     
1273     if (TP_CMT_LOGGED==flags)
1274     {
1275         G_atmi_tls->tx_commit_return = TX_COMMIT_DECISION_LOGGED;
1276     }
1277     
1278     NDRX_LOG(log_info, "Commit return set to %ld (TX) ret %d", 
1279             (long)G_atmi_tls->tx_commit_return, ret);
1280     
1281 out:
1282     return ret;
1283 }
1284 
1285 
1286 
1287 
1288 
1289 
1290 
1291 
1292 expublic int ndrx_tpcommit(long flags)
1293 {
1294     int ret=EXSUCCEED;
1295     UBFH *p_ub = NULL;
1296     int do_abort = EXFALSE;
1297     XA_API_ENTRY(EXTRUE); 
1298     
1299     NDRX_LOG(log_debug, "%s enter", __func__);
1300     
1301     if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
1302     {
1303         NDRX_LOG(log_error, "tpcommit: - tpopen() was not called!");
1304         ndrx_TPset_error_msg(TPEPROTO,  "tpcommit - tpopen() was not called!");
1305         ret=EXFAIL;
1306         goto out_no_reset;
1307     }
1308 
1309     if (0!=flags && !(flags & TPTXCOMMITDLOG))
1310     {
1311         NDRX_LOG(log_error, "tpcommit: flags != 0 && !TPTXCOMMITDLOG");
1312         ndrx_TPset_error_msg(TPEINVAL,  "tpcommit: flags != 0 && !TPTXCOMMITDLOG");
1313         ret=EXFAIL;
1314         goto out_no_reset;
1315     }
1316     
1317     if (!G_atmi_tls->G_atmi_xa_curtx.txinfo)
1318     {
1319         NDRX_LOG(log_error, "tpcommit: Not in global TX");
1320         ndrx_TPset_error_msg(TPEPROTO,  "tpcommit: Not in global TX");
1321         ret=EXFAIL;
1322         goto out_no_reset;
1323         
1324     }
1325             
1326     
1327 
1328 
1329     if (!G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags)
1330     {
1331         NDRX_LOG(log_error, "tpcommit: Not not initiator");
1332         ndrx_TPset_error_msg(TPEPROTO,  "tpcommit: Not not initiator");
1333         ret=EXFAIL;
1334         goto out_no_reset;
1335     }
1336     
1337     
1338     if (TX_COMMIT_DECISION_LOGGED == G_atmi_tls->tx_commit_return)
1339     {
1340         flags|=TPTXCOMMITDLOG;
1341     }
1342     
1343     
1344     if (atmi_xa_cd_isanyreg(&(G_atmi_tls->G_atmi_xa_curtx.txinfo->call_cds)))
1345     {
1346         NDRX_LOG(log_error, "tpcommit: Open call descriptors found - abort!");
1347         do_abort = EXTRUE;
1348     }
1349     
1350     if (atmi_xa_cd_isanyreg(&(G_atmi_tls->G_atmi_xa_curtx.txinfo->conv_cds)))
1351     {
1352         NDRX_LOG(log_error, "tpcommit: Open conversation descriptors found - abort!");
1353         do_abort = EXTRUE;
1354     }
1355     
1356     if (G_atmi_tls->G_atmi_xa_curtx.txinfo->tmtxflags & TMTXFLAGS_IS_ABORT_ONLY)
1357     {
1358         NDRX_LOG(log_error, "tpcommit: Transaction marked as abort only!");
1359         do_abort = EXTRUE;
1360     }
1361     
1362     
1363     
1364     
1365 
1366 
1367     if (!XA_IS_DYNAMIC_REG || 
1368             (XA_TXINFO_AXREG_CLD & G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags))
1369     {
1370         if (EXSUCCEED!= (ret=atmi_xa_end_entry(atmi_xa_get_branch_xid(G_atmi_tls->G_atmi_xa_curtx.txinfo, 
1371                 G_atmi_tls->G_atmi_xa_curtx.txinfo->btid), TMSUCCESS, EXFALSE)))
1372         {
1373             NDRX_LOG(log_error, "Failed to end XA api: %d [%s] - aborting", 
1374                     ret, atmi_xa_geterrstr(ret));
1375             userlog("Failed to end XA api: %d [%s] - aborting", 
1376                     ret, atmi_xa_geterrstr(ret));
1377             
1378             do_abort = EXTRUE;
1379         }
1380     }
1381     
1382     if (do_abort)
1383     {
1384         
1385         ret = ndrx_tpabort(0, EXFALSE);
1386         
1387         
1388 
1389 
1390         if (EXSUCCEED==ret || TPEPROTO==tperrno)
1391         {
1392             
1393             ndrx_TPunset_error();
1394             ndrx_TPset_error_msg(TPEABORT,  "tpcommit: Transaction was marked for "
1395                     "abort and aborted now!");
1396             ret=EXFAIL;
1397         }
1398         
1399         return ret; 
1400     }
1401     
1402     NDRX_LOG(log_debug, "About to call TM flags=%ld", flags);
1403     
1404     
1405     
1406     if (NULL==(p_ub=atmi_xa_call_tm_generic(ATMI_XA_TPCOMMIT, EXFALSE, EXFAIL, 
1407             G_atmi_tls->G_atmi_xa_curtx.txinfo, flags, EXFAIL)))
1408     {
1409         NDRX_LOG(log_error, "Failed to execute TM command [%c]", 
1410                     ATMI_XA_TPCOMMIT);
1411         
1412         
1413         
1414         EXFAIL_OUT(ret);
1415     }
1416 
1417     NDRX_LOG(log_debug, "Transaction [%s] commit OK",
1418                         G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1419         
1420 out:
1421                             
1422     
1423     atmi_xa_reset_curtx();
1424 
1425 out_no_reset:
1426 
1427     if (NULL!=p_ub)
1428     {
1429         
1430         atmi_error_t err;
1431         
1432         
1433         ndrx_TPsave_error(&err);
1434         tpfree((char *)p_ub);  
1435         ndrx_TPrestore_error(&err);
1436     }
1437 
1438 
1439     return ret;
1440 }
1441 
1442 
1443 
1444 
1445 
1446 
1447 
1448 
1449 
1450 expublic int ndrx_tpabort(long flags, int call_xa_end)
1451 {
1452     int ret=EXSUCCEED;
1453     UBFH *p_ub = NULL;
1454     XA_API_ENTRY(EXTRUE); 
1455     
1456     NDRX_LOG(log_debug, "_tpabort enter");
1457     
1458     if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
1459     {
1460         NDRX_LOG(log_error, "tpabort: - tpopen() was not called!");
1461         ndrx_TPset_error_msg(TPEPROTO,  "tpabort - tpopen() was not called!");
1462         ret=EXFAIL;
1463         goto out_no_reset;
1464     }
1465 
1466     if (0!=flags)
1467     {
1468         NDRX_LOG(log_error, "tpabort: flags != 0");
1469         ndrx_TPset_error_msg(TPEINVAL,  "tpabort: flags != 0");
1470         ret=EXFAIL;
1471         goto out_no_reset;
1472     }
1473     
1474     if (!G_atmi_tls->G_atmi_xa_curtx.txinfo)
1475     {
1476         NDRX_LOG(log_error, "tpabort: Not in global TX");
1477         ndrx_TPset_error_msg(TPEPROTO,  "tpabort: Not in global TX");
1478         ret=EXFAIL;
1479         goto out_no_reset;
1480     }
1481             
1482     if (!(XA_TXINFO_INITIATOR & G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags))
1483     {
1484         NDRX_LOG(log_error, "tpabort: Not not initiator");
1485         ndrx_TPset_error_msg(TPEPROTO,  "tpabort: Not not initiator");
1486         ret=EXFAIL;
1487         goto out_no_reset;
1488     }
1489     
1490     
1491     if (call_xa_end)
1492     {
1493         if (!XA_IS_DYNAMIC_REG || 
1494                 (XA_TXINFO_AXREG_CLD & G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags))
1495         {
1496             
1497             if (EXSUCCEED!= atmi_xa_end_entry(
1498                     atmi_xa_get_branch_xid(G_atmi_tls->G_atmi_xa_curtx.txinfo,
1499                     G_atmi_tls->G_atmi_xa_curtx.txinfo->btid), TMSUCCESS, EXTRUE))
1500             {
1501                 NDRX_LOG(log_error, "Failed to end XA api: %d [%s]", 
1502                         ret, atmi_xa_geterrstr(ret));
1503                 userlog("Failed to end XA api: %d [%s]", 
1504                         ret, atmi_xa_geterrstr(ret));
1505             }
1506         }
1507     }
1508     
1509     NDRX_LOG(log_debug, "About to call TM");
1510     
1511     if (NULL==(p_ub=atmi_xa_call_tm_generic(ATMI_XA_TPABORT, EXFALSE, EXFAIL, 
1512             G_atmi_tls->G_atmi_xa_curtx.txinfo, 0L, EXFAIL)))
1513     {
1514         NDRX_LOG(log_error, "Failed to execute TM command [%c]", 
1515                     ATMI_XA_TPBEGIN);
1516         
1517         
1518         
1519         EXFAIL_OUT(ret);
1520     }
1521 
1522     NDRX_LOG(log_debug, "Transaction [%s] abort OK",
1523                         G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1524 out:
1525     
1526     atmi_xa_reset_curtx();
1527 
1528 out_no_reset:
1529 
1530     if (NULL!=p_ub)
1531     {
1532         
1533         atmi_error_t err;
1534         
1535         
1536         ndrx_TPsave_error(&err);
1537         tpfree((char *)p_ub);  
1538         ndrx_TPrestore_error(&err);
1539     }
1540 
1541     return ret;
1542 }
1543 
1544 
1545 
1546 
1547 
1548 expublic int ndrx_tpopen(void)
1549 {
1550     int ret=EXSUCCEED;
1551     XA_API_ENTRY(EXTRUE);
1552    
1553     ret = atmi_xa_open_entry();
1554     
1555 out:
1556     return ret;
1557 }
1558 
1559 
1560 
1561 
1562 
1563 expublic int ndrx_tpclose(void)
1564 {
1565     int ret=EXSUCCEED;
1566     
1567     XA_API_ENTRY(EXTRUE);
1568 
1569     if (G_atmi_tls->G_atmi_xa_curtx.txinfo)
1570     {
1571         NDRX_LOG(log_error, "tpclose: - cannot close as process in TX: [%s]", 
1572                 G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1573         ndrx_TPset_error_fmt(TPEPROTO, "tpclose: - cannot close as process in TX: [%s]", 
1574                 G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid);
1575         EXFAIL_OUT(ret);
1576     }
1577    
1578     ret = atmi_xa_close_entry(EXFALSE);
1579     
1580 out:
1581     return ret;
1582 }
1583  
1584 
1585 
1586 
1587 
1588 
1589 
1590 
1591 
1592 
1593 
1594 
1595 
1596 
1597 
1598 expublic int ndrx_tpsuspend (TPTRANID *tranid, long flags, int is_contexting)
1599 {
1600     int ret=EXSUCCEED;
1601     long xa_flags = TMSUCCESS;
1602     
1603     XA_API_ENTRY(EXTRUE); 
1604     NDRX_LOG(log_info, "Suspending global transaction: atmi flags %lx", flags);
1605     if (NULL==tranid)
1606     {
1607         ndrx_TPset_error_msg(TPEINVAL,  "_tpsuspend: trandid = NULL!");
1608         EXFAIL_OUT(ret);
1609     }
1610     
1611     if (0!= (flags & ~TPTXTMSUSPEND) )
1612     {
1613         ndrx_TPset_error_msg(TPEINVAL,  "_tpsuspend: flags is not 0, nor TPTXTMSUSPEND");
1614         EXFAIL_OUT(ret);
1615     }
1616     
1617     if (!G_atmi_tls->G_atmi_xa_curtx.txinfo)
1618     {
1619         NDRX_LOG(log_error, "_tpsuspend: Not in global TX");
1620         ndrx_TPset_error_msg(TPEPROTO,  "_tpsuspend: Not in global TX");
1621         EXFAIL_OUT(ret);
1622     }
1623     
1624     
1625 
1626 
1627 
1628     if ( (flags & TPTXTMSUSPEND) && !(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOJOIN))
1629     {
1630         xa_flags = TMSUSPEND;
1631     }
1632     
1633 #if 0
1634     - I guess this is not a problem. Must be able to suspend abort only transaction
1635     because of object-api
1636     if (G_atmi_tls->G_atmi_xa_curtx.txinfo->tmtxflags & TMTXFLAGS_IS_ABORT_ONLY)
1637     {
1638         NDRX_LOG(log_error, "_tpsuspend: Abort only transaction!");
1639         ndrx_TPset_error_msg(TPEPROTO,  "_tpsuspend: Abort only transaction!");
1640         EXFAIL_OUT(ret);
1641     }
1642 #endif
1643     
1644     
1645     if (!is_contexting  
1646             && atmi_xa_cd_isanyreg(&(G_atmi_tls->G_atmi_xa_curtx.txinfo->call_cds)))
1647     {
1648         NDRX_LOG(log_error, "_tpsuspend: Call descriptors still open!");
1649         ndrx_TPset_error_msg(TPEPROTO,  "_tpsuspend: Call descriptors still open!");
1650         EXFAIL_OUT(ret);
1651     }
1652     
1653     if (!is_contexting 
1654             && atmi_xa_cd_isanyreg(&(G_atmi_tls->G_atmi_xa_curtx.txinfo->conv_cds)))
1655     {
1656         NDRX_LOG(log_error, "_tpsuspend: Conversation descriptors still open!");
1657         ndrx_TPset_error_msg(TPEPROTO,  "_tpsuspend: Conversation descriptors still open!");
1658         EXFAIL_OUT(ret);
1659     }
1660     
1661     
1662     
1663     XA_TX_COPY(tranid, G_atmi_tls->G_atmi_xa_curtx.txinfo);
1664     tranid->is_tx_initiator = G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags;
1665     
1666     
1667 
1668 
1669 
1670 
1671     
1672     
1673     if (!XA_IS_DYNAMIC_REG || 
1674             (XA_TXINFO_AXREG_CLD & G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags))
1675     {
1676         
1677 
1678 
1679 
1680 
1681 
1682 
1683 
1684 
1685 
1686         
1687         if (EXSUCCEED!= (ret=atmi_xa_end_entry(
1688                 atmi_xa_get_branch_xid(G_atmi_tls->G_atmi_xa_curtx.txinfo,
1689                 G_atmi_tls->G_atmi_xa_curtx.txinfo->btid), xa_flags, EXFALSE)))
1690         {
1691             int did_abort = EXFALSE;
1692             NDRX_LOG(log_error, "Failed to end XA api: %d [%s] flags: %lx", 
1693                     ret, atmi_xa_geterrstr(ret), xa_flags);
1694             userlog("Failed to end XA api: %d [%s] flags: %lx", 
1695                     ret, atmi_xa_geterrstr(ret), xa_flags);
1696             
1697             
1698             ndrx_xa_join_fail(&did_abort, EXFALSE);
1699             
1700             if (did_abort)
1701             {
1702                 ndrx_TPoverride_code(TPEABORT);
1703             }
1704             else
1705             {
1706                 ndrx_TPoverride_code(TPESYSTEM);
1707             }
1708             
1709             goto out;
1710         }
1711     }
1712 
1713     atmi_xa_reset_curtx();
1714     
1715     NDRX_LOG(log_debug, "Suspend ok xid: [%s] xa flags: %lx", 
1716             tranid->tmxid, xa_flags);
1717 out:
1718 
1719     return ret;
1720 }
1721 
1722 
1723 
1724 
1725 
1726 
1727 
1728 expublic int  ndrx_tpresume (TPTRANID *tranid, long flags)
1729 {
1730     int ret=EXSUCCEED;
1731     int was_join = EXFALSE;
1732     long join_flag = TMJOIN;
1733     atmi_xa_tx_info_t xai;
1734     
1735     XA_API_ENTRY(EXTRUE); 
1736     NDRX_LOG(log_info, "Resuming global transaction...");
1737     
1738     if (NULL==tranid)
1739     {
1740         ndrx_TPset_error_msg(TPEINVAL,  "_tpresume: trandid = NULL!");
1741         EXFAIL_OUT(ret);
1742     }
1743        
1744     if (0!= (flags & ~ (TPTXNOOPTIM | TPTXTMSUSPEND)) )
1745     {
1746         ndrx_TPset_error_msg(TPEINVAL,  "_tpresume: flags is not 0, "
1747                 "nor TPTXNOOPTIM, nor TPTXTMSUSPEND");
1748         EXFAIL_OUT(ret);
1749     }
1750     
1751     
1752 
1753 
1754 
1755 
1756     if ( (flags & TPTXTMSUSPEND)
1757             && !(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOJOIN))
1758     {
1759         join_flag = TMRESUME;
1760     }
1761     
1762     
1763     if (G_atmi_tls->G_atmi_xa_curtx.txinfo)
1764     {
1765         ndrx_TPset_error_msg(TPEPROTO,  "_tpresume: Already in global TX!");
1766         EXFAIL_OUT(ret);
1767     }
1768     
1769     
1770     XA_TX_COPY((&xai), tranid);
1771     
1772     
1773     if (flags & TPTXNOOPTIM)
1774     {
1775         xai.tmknownrms[0]=EXEOS;
1776     }
1777     
1778     if (EXSUCCEED!=_tp_srv_join_or_new(&xai, EXFALSE, &was_join, join_flag,
1779             tranid->is_tx_initiator))
1780     {
1781         ndrx_TPset_error_msg(TPESYSTEM,  "_tpresume: Failed to enter in global TX!");
1782         EXFAIL_OUT(ret);
1783     }
1784     
1785     NDRX_LOG(log_debug, "Resume ok xid: [%s] is_tx_initiator: %d abort_only: %d", 
1786             tranid->tmxid, tranid->is_tx_initiator, 
1787             G_atmi_tls->G_atmi_xa_curtx.txinfo->tmtxflags & TMTXFLAGS_IS_ABORT_ONLY);
1788     
1789 out:
1790     return ret;
1791 }
1792 
1793 
1794 
1795 
1796 
1797 
1798 
1799 
1800 expublic int ax_reg(int rmid, XID *xid, long flags)
1801 {
1802     int ret = TM_OK;
1803     int was_join = EXFALSE;
1804     ATMI_TLS_ENTRY;
1805     
1806     NDRX_LOG(log_info, "ax_reg called");
1807     if (NULL==G_atmi_tls->G_atmi_xa_curtx.txinfo)
1808     {
1809         NDRX_LOG(log_error, "ERROR: No global transaction registered "
1810                 "with process/thread!");
1811         userlog("ERROR: No global transaction registered with process/thread!");
1812         memset(xid, 0, sizeof(XID));
1813         ret = TMER_TMERR;
1814         goto out;
1815     }
1816     
1817     if (EXSUCCEED!=_tp_srv_join_or_new(G_atmi_tls->G_atmi_xa_curtx.txinfo, 
1818             EXTRUE, &was_join, TMJOIN, G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags))
1819     {
1820         ret = TMER_TMERR;
1821         goto out;
1822     }
1823     
1824     if (was_join)
1825     {
1826         ret = TM_JOIN;
1827     }
1828     
1829     memcpy(xid, atmi_xa_get_branch_xid(G_atmi_tls->G_atmi_xa_curtx.txinfo, 
1830             G_atmi_tls->G_atmi_xa_curtx.txinfo->btid), sizeof(*xid));
1831     
1832     
1833 
1834 
1835   
1836 out:
1837     NDRX_LOG(log_info, "ax_reg returns: %d", ret);
1838     return ret;
1839 }
1840  
1841 
1842 
1843 
1844 
1845 
1846 
1847 int ax_unreg(int rmid, long flags)
1848 {
1849     NDRX_LOG(log_info, "ax_unreg called");
1850     return EXSUCCEED;
1851 }
1852 
1853 
1854 
1855 
1856 
1857 
1858 expublic int _tp_srv_join_or_new_from_call(tp_command_call_t *call,
1859         int is_ax_reg_callback)
1860 {
1861     int is_known = EXFALSE;
1862     atmi_xa_tx_info_t xai;
1863     memset(&xai, 0, sizeof(xai));
1864     
1865     
1866 
1867 
1868     XA_TX_COPY((&xai), call)
1869     
1870     return _tp_srv_join_or_new(&xai, is_ax_reg_callback, &is_known, TMJOIN, 
1871             XA_TXINFO_NOFLAGS);
1872 }
1873 
1874 
1875 
1876 
1877 
1878 
1879 
1880 
1881 
1882 
1883 
1884 
1885 exprivate int ndrx_xa_join_fail(int *did_abort, int force_abort)
1886 {
1887     UBFH *p_ub = NULL;
1888     int ret = EXSUCCEED;
1889     
1890     atmi_error_t err;
1891     
1892     
1893 
1894 
1895     if (!(G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags & XA_TXINFO_INITIATOR) &&
1896             !force_abort)
1897     {
1898         return EXSUCCEED;
1899     }
1900         
1901     
1902     ndrx_TPsave_error(&err);
1903         
1904     NDRX_LOG(log_error, "xa_start() or xa_end() failed, aborting to TMSRV");
1905     
1906     if (NULL==(p_ub=atmi_xa_call_tm_generic(ATMI_XA_TPABORT, EXFALSE, EXFAIL, 
1907             G_atmi_tls->G_atmi_xa_curtx.txinfo, 0L, EXFAIL)))
1908     {
1909         NDRX_LOG(log_error, "Failed to execute TM command [%c]", 
1910                     ATMI_XA_TPABORT);
1911         
1912         
1913         
1914         EXFAIL_OUT(ret);
1915     }
1916     
1917     if (NULL!=did_abort)
1918     {
1919         *did_abort = EXTRUE;
1920     }
1921     
1922 out:
1923     if (NULL!=p_ub)
1924     {
1925         tpfree((char *)p_ub);  
1926         
1927     }
1928     ndrx_TPrestore_error(&err);
1929     
1930     return ret;
1931 }
1932 
1933 
1934 
1935 
1936 
1937 
1938 
1939 
1940 
1941 expublic int _tp_srv_join_or_new(atmi_xa_tx_info_t *p_xai,
1942         int is_ax_reg_callback, int *p_is_known, long join_flag, int tranid_flags)
1943 {
1944     int ret = EXSUCCEED;
1945     UBFH *p_ub = NULL;
1946     short reason;
1947     int new_rm = EXFALSE;
1948     char src_tmknownrms[2];
1949     long tmflags = 0;
1950     GENERIC_RETRY_DEF;
1951 
1952     XA_API_ENTRY(EXTRUE); 
1953     
1954     
1955 
1956 
1957 
1958     if (!(XA_IS_DYNAMIC_REG) || (tranid_flags & XA_TXINFO_AXREG_CLD))
1959     {
1960         
1961         if (EXSUCCEED!=atmi_xa_set_curtx_from_xai(p_xai))
1962         {
1963             EXFAIL_OUT(ret);
1964         }
1965         
1966         
1967         G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags = tranid_flags;
1968     }
1969     else
1970     {
1971         
1972 
1973 
1974 
1975 
1976         if (!is_ax_reg_callback)
1977         {
1978             NDRX_LOG(log_debug, "Dynamic reg + process start "
1979                                 "just remember the transaction");
1980             
1981             
1982             GENERIC_RETRY_ENTRY(EXTRUE);
1983 
1984             
1985 
1986 
1987             if (EXSUCCEED!=atmi_xa_set_curtx_from_xai(p_xai))
1988             {
1989                 EXFAIL_OUT(ret);
1990             }
1991 
1992             
1993             G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags = tranid_flags;
1994 
1995             
1996             GENERIC_RETRY_ENTRY(EXTRUE);
1997 
1998             
1999             goto out;
2000         }
2001         else
2002         {
2003             
2004 
2005 
2006 
2007 
2008 
2009             NDRX_LOG(log_debug, "Dynamic reg work started");
2010             p_xai->tranid_flags|=XA_TXINFO_AXREG_CLD;
2011         }
2012     }
2013     
2014     if (!(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOJOIN) &&
2015             atmi_xa_is_current_rm_known(p_xai->tmknownrms))
2016     {    
2017         *p_is_known=EXTRUE;
2018         
2019         
2020         G_atmi_tls->G_atmi_xa_curtx.txinfo->btid = 0;
2021         
2022         
2023         if (XA_IS_DYNAMIC_REG && !(join_flag & TMRESUME))
2024         {
2025             NDRX_LOG(log_debug, "Dynamic reg - no start/join!");
2026         }
2027         
2028         else if (EXSUCCEED!=atmi_xa_start_entry(atmi_xa_get_branch_xid(p_xai, 
2029                 G_atmi_tls->G_atmi_xa_curtx.txinfo->btid), 
2030                 join_flag, EXFALSE))
2031         {
2032             NDRX_LOG(log_error, "Failed to join transaction!");
2033         ndrx_xa_join_fail(NULL, EXFALSE);
2034             EXFAIL_OUT(ret);
2035         }
2036         else
2037         {
2038             NDRX_LOG(log_debug, "tx join ok!");
2039         }
2040     }
2041     else
2042     {
2043         long btid = EXFAIL;
2044         NDRX_LOG(log_info, "RM not aware of this transaction");
2045         
2046         
2047 
2048 
2049         if (!(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOJOIN))
2050         {
2051             btid = 0;
2052         }
2053         
2054         if (G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOSTARTXID)
2055         {
2056             tmflags|=TMFLAGS_TPNOSTARTXID;
2057         }
2058 
2059         
2060         
2061         if (NULL==(p_ub=atmi_xa_call_tm_generic(ATMI_XA_TMREGISTER, 
2062                 EXFALSE, EXFAIL, p_xai, tmflags, btid)))
2063         {
2064             NDRX_LOG(log_error, "Failed to execute TM command [%c]", 
2065                         ATMI_XA_TMREGISTER);   
2066             EXFAIL_OUT(ret);
2067         }
2068 
2069         if (EXSUCCEED!=Bget(p_ub, TMTXFLAGS, 0, (char *)&tmflags, 0L))
2070         {
2071             NDRX_LOG(log_error, "Failed to read TMTXFLAGS!");   
2072 
2073             EXFAIL_OUT(ret);
2074         }
2075         
2076         if (tmflags & TMFLAGS_RMIDKNOWN)
2077         {
2078             *p_is_known = EXTRUE;
2079         }
2080         else
2081         {
2082             if (EXSUCCEED!=Bget(p_ub, TMTXBTID, 0, (char *)&btid, 0L))
2083             {
2084                 NDRX_LOG(log_error, "Failed to read TMTXBTID!");   
2085 
2086                 EXFAIL_OUT(ret);
2087             }
2088         }
2089         
2090         G_atmi_tls->G_atmi_xa_curtx.txinfo->btid = btid;
2091 
2092         if (XA_IS_DYNAMIC_REG)
2093         {
2094             
2095             NDRX_LOG(log_debug, "Dynamic reg - no new tx start!");
2096         }
2097         
2098         else if (*p_is_known)
2099         {
2100             if (EXSUCCEED!=atmi_xa_start_entry(atmi_xa_get_branch_xid(p_xai, btid), 
2101                     join_flag, EXFALSE))
2102             {
2103                 NDRX_LOG(log_error, "Failed to join transaction!");
2104         ndrx_xa_join_fail(NULL, EXFALSE);
2105                 EXFAIL_OUT(ret);
2106             }
2107             else
2108             {
2109                 NDRX_LOG(log_debug, "tx join ok!");
2110             }
2111         }
2112         
2113         else if (EXSUCCEED!=atmi_xa_start_entry(atmi_xa_get_branch_xid(p_xai, btid), 
2114                 TMNOFLAGS, EXTRUE)) 
2115         {
2116             reason=atmi_xa_get_reason();
2117             NDRX_LOG(log_error, "Failed to create new tx under local RM (reason: %hd): %s!", 
2118                     reason, atmi_xa_geterrstr(reason));
2119             if (XAER_DUPID == (reason=atmi_xa_get_reason()))
2120             {
2121                 
2122                 *p_is_known=EXTRUE;
2123                 
2124                 if (EXSUCCEED!=atmi_xa_start_entry(atmi_xa_get_branch_xid(p_xai, btid), 
2125                         join_flag, EXFALSE))
2126                 {
2127                     NDRX_LOG(log_error, "Failed to join transaction!");
2128             ndrx_xa_join_fail(NULL, EXFALSE);
2129                     EXFAIL_OUT(ret);
2130                 }
2131                 else
2132                 {
2133                     NDRX_LOG(log_debug, "tx join ok!");
2134                 }
2135             }
2136             else
2137             {
2138                 NDRX_LOG(log_error, "Failed to start transaction!");
2139                 ndrx_xa_join_fail(NULL, EXFALSE);
2140                 EXFAIL_OUT(ret);
2141             }
2142         }
2143         new_rm = EXTRUE;
2144     }
2145         
2146     
2147     if (!(G_atmi_env.xa_flags_sys & NDRX_XA_FLAG_SYS_NOJOIN) && new_rm)
2148     {
2149         src_tmknownrms[0] = G_atmi_env.xa_rmid;
2150         src_tmknownrms[1] = EXEOS;
2151         
2152         if (EXSUCCEED!=atmi_xa_update_known_rms(
2153                 G_atmi_tls->G_atmi_xa_curtx.txinfo->tmknownrms, 
2154                 src_tmknownrms))
2155         {
2156             EXFAIL_OUT(ret);
2157         }
2158     }
2159     
2160 out:
2161 
2162     if (EXSUCCEED!=ret)
2163     {
2164         
2165         atmi_xa_reset_curtx();
2166     }
2167 
2168     if (NULL!=p_ub)
2169     {
2170         tpfree((char *)p_ub);
2171     }
2172 
2173     return ret;
2174 }
2175 
2176 
2177 
2178 
2179 
2180 
2181 
2182 
2183 expublic int _tp_srv_disassoc_tx(int force_rollback, int *end_fail)
2184 {
2185     int ret = EXSUCCEED;
2186     ATMI_TLS_ENTRY;
2187     
2188     
2189     NDRX_LOG(log_debug, "into %s() force_rollback=%d", __func__, force_rollback);
2190     if (NULL==G_atmi_tls->G_atmi_xa_curtx.txinfo)
2191     {
2192         NDRX_LOG(log_warn, "Not in global tx!");
2193         goto out;
2194     }
2195     
2196     
2197     if ( !XA_IS_DYNAMIC_REG || 
2198             (XA_TXINFO_AXREG_CLD & G_atmi_tls->G_atmi_xa_curtx.txinfo->tranid_flags))
2199     {
2200         if (EXSUCCEED!= (ret=atmi_xa_end_entry(
2201                 atmi_xa_get_branch_xid(G_atmi_tls->G_atmi_xa_curtx.txinfo,
2202                 G_atmi_tls->G_atmi_xa_curtx.txinfo->btid), TMSUCCESS, EXFALSE)))
2203         {
2204             NDRX_LOG(log_error, "Failed to end XA api: %d [%s]", 
2205                     ret, atmi_xa_geterrstr(ret));
2206             userlog("Failed to end XA api: %d [%s]", 
2207                     ret, atmi_xa_geterrstr(ret));
2208             
2209             *end_fail = EXTRUE;
2210         }
2211     }
2212     
2213     
2214     if (force_rollback)
2215     {
2216         ndrx_xa_join_fail(NULL, EXTRUE);
2217     }
2218 
2219     
2220     atmi_xa_curtx_del(G_atmi_tls->G_atmi_xa_curtx.txinfo);    
2221     G_atmi_tls->G_atmi_xa_curtx.txinfo = NULL;
2222     
2223 out:
2224     return ret;
2225 }
2226 
2227 
2228 
2229 
2230 
2231 
2232 expublic int _tp_srv_tell_tx_fail(void)
2233 {
2234     int ret = EXSUCCEED;
2235     
2236     
2237     
2238 out:
2239     return ret;
2240 }
2241 
2242 
2243 
2244 
2245 
2246 expublic void ndrx_xa_noapisusp(int val)
2247 {
2248     if (val)
2249     {
2250         NDRX_LOG(log_debug, "No Context tran suspend");
2251         G_atmi_env.xa_flags_sys|=NDRX_XA_FLAG_SYS_NOAPISUSP;
2252     }
2253     else
2254     {
2255         G_atmi_env.xa_flags_sys=G_atmi_env.xa_flags_sys & ~NDRX_XA_FLAG_SYS_NOAPISUSP;
2256     }
2257 }
2258 
2259 
2260 
2261 
2262 
2263 
2264 expublic void ndrx_xa_nojoin(int val)
2265 {
2266     if (val)
2267     {
2268         NDRX_LOG(log_debug, "XA No JOIN");
2269         G_atmi_env.xa_flags_sys|=NDRX_XA_FLAG_SYS_NOJOIN;
2270     }
2271     else
2272     {
2273         G_atmi_env.xa_flags_sys=G_atmi_env.xa_flags_sys & ~NDRX_XA_FLAG_SYS_NOJOIN;
2274     }
2275 }
2276 
2277 
2278 
2279 
2280 
2281 
2282 
2283 expublic void ndrx_xa_nosuspend(int val)
2284 {
2285     if (val)
2286     {
2287         NDRX_LOG(log_debug, "XA No Automatic suspend");
2288         G_atmi_env.xa_flags_sys|=NDRX_XA_FLAG_SYS_NOSUSPEND;
2289     }
2290     else
2291     {
2292         G_atmi_env.xa_flags_sys=G_atmi_env.xa_flags_sys & ~NDRX_XA_FLAG_SYS_NOSUSPEND;
2293     }
2294 }
2295 
2296 
2297 
2298 
2299 
2300 
2301 
2302 
2303 expublic void ndrx_xa_nostartxid(int val)
2304 {
2305     if (val)
2306     {
2307         NDRX_LOG(log_debug, "XA No STAR XID");
2308         G_atmi_env.xa_flags_sys|=NDRX_XA_FLAG_SYS_NOSTARTXID;
2309     }
2310     else
2311     {
2312         G_atmi_env.xa_flags_sys=G_atmi_env.xa_flags_sys & ~NDRX_XA_FLAG_SYS_NOSTARTXID;
2313     }
2314 }
2315 
2316 
2317 
2318 
2319 
2320 
2321 expublic void ndrx_xa_setloctxabort(int (*pf_xa_loctxabort)(XID *xid, long flags))
2322 {
2323     G_atmi_env.pf_xa_loctxabort = pf_xa_loctxabort;
2324     NDRX_LOG(log_debug, "xa_loctxabort set to %p", G_atmi_env.pf_xa_loctxabort);
2325 }
2326 
2327 
2328 
2329 
2330 
2331 
2332 
2333 expublic void ndrx_xa_setgetconnn(void *(*pf_xa_getconn)(void))
2334 {
2335     G_atmi_env.pf_getconn= pf_xa_getconn;
2336     NDRX_LOG(log_debug, "pf_getconn set to %p", G_atmi_env.pf_getconn);
2337 }
2338 
2339 
2340 
2341 
2342 
2343 expublic void ndrx_xa_btight(int val)
2344 {
2345     if (val)
2346     {
2347         NDRX_LOG(log_debug, "XA BTIGHT");
2348         G_atmi_env.xa_flags_sys|=NDRX_XA_FLAG_SYS_BTIGHT;
2349     }
2350     else
2351     {
2352         G_atmi_env.xa_flags_sys=G_atmi_env.xa_flags_sys & ~NDRX_XA_FLAG_SYS_BTIGHT;
2353     }
2354 }
2355 
2356 
2357 
2358 
2359 
2360 expublic struct xa_switch_t* ndrx_xa_sw_get(void)
2361 {
2362     return G_atmi_env.xa_sw;
2363 }
2364 
2365