Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief XA testing backend
0003  *   Comments:
0004  *   - Will assume that our resource is file system.
0005  *   - The file names shall match the transaction XID.
0006  *   - Content will be custom one.
0007  *   - Transaction will travel via folders in this order:
0008  *   - active - active transactions
0009  *   - prepared - prepared
0010  *   - committed - committed txns
0011  *   - aborted - transactions killed
0012  *   TODO: Might want testing with RETRY
0013  *
0014  * @file xabackend.c
0015  */
0016 /* -----------------------------------------------------------------------------
0017  * Enduro/X Middleware Platform for Distributed Transaction Processing
0018  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0019  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0020  * This software is released under one of the following licenses:
0021  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0022  * See LICENSE file for full text.
0023  * -----------------------------------------------------------------------------
0024  * AGPL license:
0025  *
0026  * This program is free software; you can redistribute it and/or modify it under
0027  * the terms of the GNU Affero General Public License, version 3 as published
0028  * by the Free Software Foundation;
0029  *
0030  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0031  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0032  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0033  * for more details.
0034  *
0035  * You should have received a copy of the GNU Affero General Public License along 
0036  * with this program; if not, write to the Free Software Foundation, Inc.,
0037  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0038  *
0039  * -----------------------------------------------------------------------------
0040  * A commercial use license is available from Mavimax, Ltd
0041  * contact@mavimax.com
0042  * -----------------------------------------------------------------------------
0043  */
0044 #include <string.h>
0045 #include <stdio.h>
0046 #include <stdlib.h>
0047 #include <memory.h>
0048 #include <math.h>
0049 #include <errno.h>
0050 
0051 #include <atmi.h>
0052 #include <ubf.h>
0053 #include <ndebug.h>
0054 #include <test.fd.h>
0055 #include <ndrstandard.h>
0056 #include <nstopwatch.h>
0057 
0058 #include <xa.h>
0059 #include <atmi_int.h>
0060 #include <xa_cmn.h>  
0061 /*---------------------------Externs------------------------------------*/
0062 /*---------------------------Macros-------------------------------------*/
0063 /*---------------------------Enums--------------------------------------*/
0064 /*---------------------------Typedefs-----------------------------------*/
0065 /*---------------------------Globals------------------------------------*/
0066 /*---------------------------Statics------------------------------------*/
0067 __thread int M_is_open = EXFALSE;
0068 __thread int M_is_reg = EXFALSE; /* Dynamic registration done? */
0069 __thread int M_rmid = EXFAIL;
0070 __thread FILE *M_f = NULL;
0071 /*---------------------------Prototypes---------------------------------*/
0072 
0073 expublic int xa_open_entry_stat(char *xa_info, int rmid, long flags);
0074 expublic int xa_close_entry_stat(char *xa_info, int rmid, long flags);
0075 expublic int xa_start_entry_stat(XID *xid, int rmid, long flags);
0076 expublic int xa_start_entry_statstartfail(XID *xid, int rmid, long flags);
0077 expublic int xa_end_entry_stat(XID *xid, int rmid, long flags);
0078 expublic int xa_rollback_entry_stat(XID *xid, int rmid, long flags);
0079 expublic int xa_prepare_entry_stat(XID *xid, int rmid, long flags);
0080 expublic int xa_prepare_entry_stat105(XID *xid, int rmid, long flags);
0081 expublic int xa_commit_entry_stat(XID *xid, int rmid, long flags);
0082 expublic int xa_commit_entry_stat_tryok(XID *xid, int rmid, long flags);
0083 expublic int xa_commit_entry_stat_tryfail(XID *xid, int rmid, long flags);
0084 expublic int xa_recover_entry_stat(XID *xid, long count, int rmid, long flags);
0085 expublic int xa_forget_entry_stat(XID *xid, int rmid, long flags);
0086 expublic int xa_complete_entry_stat(int *handle, int *retval, int rmid, long flags);
0087 
0088 expublic int xa_open_entry_dyn(char *xa_info, int rmid, long flags);
0089 expublic int xa_close_entry_dyn(char *xa_info, int rmid, long flags);
0090 expublic int xa_start_entry_dyn(XID *xid, int rmid, long flags);
0091 expublic int xa_end_entry_dyn(XID *xid, int rmid, long flags);
0092 expublic int xa_rollback_entry_dyn(XID *xid, int rmid, long flags);
0093 expublic int xa_prepare_entry_dyn(XID *xid, int rmid, long flags);
0094 expublic int xa_commit_entry_dyn(XID *xid, int rmid, long flags);
0095 expublic int xa_recover_entry_dyn(XID *xid, long count, int rmid, long flags);
0096 expublic int xa_forget_entry_dyn(XID *xid, int rmid, long flags);
0097 expublic int xa_complete_entry_dyn(int *handle, int *retval, int rmid, long flags);
0098 
0099 expublic int xa_open_entry(struct xa_switch_t *sw, char *xa_info, int rmid, long flags);
0100 expublic int xa_close_entry(struct xa_switch_t *sw, char *xa_info, int rmid, long flags);
0101 expublic int xa_start_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags);
0102 expublic int xa_end_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags);
0103 expublic int xa_rollback_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags);
0104 expublic int xa_prepare_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags);
0105 expublic int xa_commit_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags);
0106 expublic int xa_recover_entry(struct xa_switch_t *sw, XID *xid, long count, int rmid, long flags);
0107 expublic int xa_forget_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags);
0108 expublic int xa_complete_entry(struct xa_switch_t *sw, int *handle, int *retval, int rmid, long flags);
0109 
0110 struct xa_switch_t ndrxstatsw_startfail = 
0111 { 
0112     .name = "ndrxstatsw_startfail",
0113     .flags = TMNOFLAGS,
0114     .version = 0,
0115     .xa_open_entry = xa_open_entry_stat,
0116     .xa_close_entry = xa_close_entry_stat,
0117     .xa_start_entry = xa_start_entry_statstartfail,
0118     .xa_end_entry = xa_end_entry_stat,
0119     .xa_rollback_entry = xa_rollback_entry_stat,
0120     .xa_prepare_entry = xa_prepare_entry_stat,
0121     .xa_commit_entry = xa_commit_entry_stat,
0122     .xa_recover_entry = xa_recover_entry_stat,
0123     .xa_forget_entry = xa_forget_entry_stat,
0124     .xa_complete_entry = xa_complete_entry_stat
0125 };
0126 
0127 struct xa_switch_t ndrxstatswtryfail = 
0128 { 
0129     .name = "ndrxstatswtryok",
0130     .flags = TMNOFLAGS,
0131     .version = 0,
0132     .xa_open_entry = xa_open_entry_stat,
0133     .xa_close_entry = xa_close_entry_stat,
0134     .xa_start_entry = xa_start_entry_stat,
0135     .xa_end_entry = xa_end_entry_stat,
0136     .xa_rollback_entry = xa_rollback_entry_stat,
0137     .xa_prepare_entry = xa_prepare_entry_stat,
0138     .xa_commit_entry = xa_commit_entry_stat_tryfail,
0139     .xa_recover_entry = xa_recover_entry_stat,
0140     .xa_forget_entry = xa_forget_entry_stat,
0141     .xa_complete_entry = xa_complete_entry_stat
0142 };
0143 
0144 struct xa_switch_t ndrxstatswtryok = 
0145 { 
0146     .name = "ndrxstatswtryok",
0147     .flags = TMNOFLAGS,
0148     .version = 0,
0149     .xa_open_entry = xa_open_entry_stat,
0150     .xa_close_entry = xa_close_entry_stat,
0151     .xa_start_entry = xa_start_entry_stat,
0152     .xa_end_entry = xa_end_entry_stat,
0153     .xa_rollback_entry = xa_rollback_entry_stat,
0154     .xa_prepare_entry = xa_prepare_entry_stat,
0155     .xa_commit_entry = xa_commit_entry_stat_tryok,
0156     .xa_recover_entry = xa_recover_entry_stat,
0157     .xa_forget_entry = xa_forget_entry_stat,
0158     .xa_complete_entry = xa_complete_entry_stat
0159 };
0160 
0161 
0162 struct xa_switch_t ndrxstatsw105 = 
0163 { 
0164     .name = "ndrxstatsw105",
0165     .flags = TMNOFLAGS,
0166     .version = 0,
0167     .xa_open_entry = xa_open_entry_stat,
0168     .xa_close_entry = xa_close_entry_stat,
0169     .xa_start_entry = xa_start_entry_stat,
0170     .xa_end_entry = xa_end_entry_stat,
0171     .xa_rollback_entry = xa_rollback_entry_stat,
0172     .xa_prepare_entry = xa_prepare_entry_stat105,
0173     .xa_commit_entry = xa_commit_entry_stat,
0174     .xa_recover_entry = xa_recover_entry_stat,
0175     .xa_forget_entry = xa_forget_entry_stat,
0176     .xa_complete_entry = xa_complete_entry_stat
0177 };
0178 
0179 struct xa_switch_t ndrxstatsw = 
0180 { 
0181     .name = "ndrxstatsw",
0182     .flags = TMNOFLAGS,
0183     .version = 0,
0184     .xa_open_entry = xa_open_entry_stat,
0185     .xa_close_entry = xa_close_entry_stat,
0186     .xa_start_entry = xa_start_entry_stat,
0187     .xa_end_entry = xa_end_entry_stat,
0188     .xa_rollback_entry = xa_rollback_entry_stat,
0189     .xa_prepare_entry = xa_prepare_entry_stat,
0190     .xa_commit_entry = xa_commit_entry_stat,
0191     .xa_recover_entry = xa_recover_entry_stat,
0192     .xa_forget_entry = xa_forget_entry_stat,
0193     .xa_complete_entry = xa_complete_entry_stat
0194 };
0195 
0196 struct xa_switch_t ndrxdynsw = 
0197 { 
0198     .name = "ndrxdynsw",
0199     .flags = TMREGISTER,
0200     .version = 0,
0201     .xa_open_entry = xa_open_entry_dyn,
0202     .xa_close_entry = xa_close_entry_dyn,
0203     .xa_start_entry = xa_start_entry_dyn,
0204     .xa_end_entry = xa_end_entry_dyn,
0205     .xa_rollback_entry = xa_rollback_entry_dyn,
0206     .xa_prepare_entry = xa_prepare_entry_dyn,
0207     .xa_commit_entry = xa_commit_entry_dyn,
0208     .xa_recover_entry = xa_recover_entry_dyn,
0209     .xa_forget_entry = xa_forget_entry_dyn,
0210     .xa_complete_entry = xa_complete_entry_dyn
0211 };
0212 
0213 /**
0214  * will use NDRX_TEST_RM_DIR env variable...
0215  */
0216 exprivate char *get_file_name(XID *xid, int rmid, char *folder)
0217 {
0218     static __thread char buf[2048]; /**< this must be per thread! */
0219     char xid_str[128];
0220     static int first = EXTRUE;
0221     static char test_root[FILENAME_MAX+1] = {EXEOS};
0222     
0223     if (first)
0224     {
0225         NDRX_STRCPY_SAFE(test_root, getenv("NDRX_TEST_RM_DIR"));
0226         first = EXFALSE;
0227     }
0228     
0229     atmi_xa_serialize_xid(xid, xid_str);
0230     
0231     snprintf(buf, sizeof(buf), "%s/%s/%s", test_root, folder, xid_str);
0232     NDRX_LOG(log_debug, "Folder built: %s", buf);
0233     
0234     return buf;
0235 }
0236 
0237 /**
0238  * Rename file from one folder to another...
0239  * @param xid
0240  * @param rmid
0241  * @param from_folder
0242  * @param to_folder
0243  * @return 
0244  */
0245 exprivate int file_move(XID *xid, int rmid, char *from_folder, char *to_folder)
0246 {
0247     int ret = EXSUCCEED;
0248     
0249     char from_file[FILENAME_MAX+1] = {EXEOS};
0250     char to_file[FILENAME_MAX+1] = {EXEOS};
0251     
0252     NDRX_STRCPY_SAFE(from_file, get_file_name(xid, rmid, from_folder));
0253     NDRX_STRCPY_SAFE(to_file, get_file_name(xid, rmid, to_folder));
0254     
0255     
0256     if (EXSUCCEED!=rename(from_file, to_file))
0257     {
0258         NDRX_LOG(log_error, "Failed to rename: %s", strerror(errno));
0259         ret=EXFAIL;
0260         goto out;
0261     }
0262     
0263 out:
0264     return ret;
0265 }
0266 /**
0267  * Open API
0268  * @param sw
0269  * @param xa_info
0270  * @param rmid
0271  * @param flags
0272  * @return 
0273  */
0274 expublic int xa_open_entry(struct xa_switch_t *sw, char *xa_info, int rmid, long flags)
0275 {
0276     if (M_is_open)
0277     {
0278         NDRX_LOG(log_error, "TESTERROR!!! xa_open_entry() - already open!");
0279         return XAER_RMERR;
0280     }
0281     M_is_open = EXTRUE;
0282     M_rmid = rmid;
0283              
0284     return XA_OK;
0285 }
0286 /**
0287  * Close entry
0288  * @param sw
0289  * @param xa_info
0290  * @param rmid
0291  * @param flags
0292  * @return 
0293  */
0294 expublic int xa_close_entry(struct xa_switch_t *sw, char *xa_info, int rmid, long flags)
0295 {
0296     NDRX_LOG(log_error, "xa_close_entry() called");
0297     
0298     if (!M_is_open)
0299     {
0300         /* Ignore this error...
0301         NDRX_LOG(log_error, "TESTERROR!!! xa_close_entry() - already closed!");
0302          */
0303         return XAER_RMERR;
0304     }
0305     
0306     M_is_open = EXFALSE;
0307     return XA_OK;
0308 }
0309 
0310 /**
0311  * Open text file in RMID folder. Create file by TXID.
0312  * Check for file existance. If start & not exists - ok .
0313  * If exists and join - ok. Otherwise fail.
0314  * @param xa_info
0315  * @param rmid
0316  * @param flags
0317  * @return 
0318  */
0319 expublic int xa_start_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags)
0320 {
0321     char *file = get_file_name(xid, rmid, "active");
0322     
0323     if (!M_is_open)
0324     {
0325         /* do not generate  */
0326         if (&ndrxstatsw_startfail != sw)
0327         {
0328             NDRX_LOG(log_error, "TESTERROR!!! xa_start_entry() - XA not open!");
0329         }
0330         return XAER_RMERR;
0331     }
0332     
0333     if ((flags & TMJOIN) || (flags & TMRESUME))
0334     {
0335         if (!ndrx_file_exists(file))
0336         {
0337             NDRX_LOG(log_error, "TMJOIN or TMRESUME but transaction does not exits (file: [%s])!",
0338             file);
0339             return XAER_NOTA;
0340         }
0341     }
0342     
0343     /* Open file for write... */
0344     if (NULL==(M_f = NDRX_FOPEN(file, "a")))
0345     {
0346         NDRX_LOG(log_error, "TESTERROR!!! xa_start_entry() - failed to open file: %s!", 
0347                 strerror(errno));
0348         return XAER_RMERR;
0349     }
0350     
0351     return XA_OK;
0352 }
0353 
0354 expublic int xa_end_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags)
0355 {
0356     
0357     if (!M_is_open)
0358     {
0359         NDRX_LOG(log_error, "TESTERROR!!! xa_end_entry() - XA not open!");
0360         return XAER_RMERR;
0361     }
0362     
0363     if (NULL==M_f)
0364     {
0365         NDRX_LOG(log_error, "TESTERROR!!! xa_end_entry() - "
0366                 "transaction already closed: %s!", 
0367                 strerror(errno));
0368         return XAER_RMERR;
0369     }
0370     
0371     if (M_is_reg)
0372     {
0373         if (EXSUCCEED!=ax_unreg(rmid, 0))
0374         {
0375             NDRX_LOG(log_error, "TESTERROR!!! xa_end_entry() - "
0376                     "ax_unreg() fail!");
0377             return XAER_RMERR;
0378         }
0379         
0380         M_is_reg = EXFALSE;
0381     }
0382     
0383 out:
0384     if (M_f)
0385     {
0386         NDRX_FCLOSE(M_f);
0387         M_f = NULL;
0388     }
0389     return XA_OK;
0390 }
0391 
0392 expublic int xa_rollback_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags)
0393 {
0394     if (!M_is_open)
0395     {
0396         NDRX_LOG(log_error, "TESTERROR!!! xa_rollback_entry() - XA not open!");
0397         return XAER_RMERR;
0398     }
0399     
0400     if (EXSUCCEED!=file_move(xid, rmid, "active", "aborted") &&
0401             EXSUCCEED!=file_move(xid, rmid, "prepared", "aborted"))
0402     {
0403         return XAER_NOTA;
0404     }
0405     
0406     return XA_OK;
0407 }
0408 
0409 expublic int xa_prepare_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags)
0410 {
0411     if (!M_is_open)
0412     {
0413         NDRX_LOG(log_error, "TESTERROR!!! xa_prepare_entry() - XA not open!");
0414         return XAER_RMERR;
0415     }
0416     
0417     if (EXSUCCEED!=file_move(xid, rmid, "active", "prepared"))
0418     {
0419         return XAER_RMERR;
0420     }
0421     
0422     return XA_OK;
0423     
0424 }
0425 
0426 expublic int xa_commit_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags)
0427 {
0428     if (!M_is_open)
0429     {
0430         NDRX_LOG(log_error, "TESTERROR!!! xa_commit_entry() - XA not open!");
0431         return XAER_RMERR;
0432     }
0433     
0434     
0435     if (EXSUCCEED!=file_move(xid, rmid, "prepared", "committed"))
0436     {
0437         return XAER_RMERR;
0438     }
0439     
0440     return XA_OK;
0441 }
0442 
0443 /**
0444  * Write some stuff to transaction!!!
0445  * @param buf
0446  * @return 
0447  */
0448 expublic int __write_to_tx_file(char *buf)
0449 {
0450     int ret = EXSUCCEED;
0451     XID xid;
0452     int len = strlen(buf);
0453     
0454     if (G_atmi_env.xa_sw->flags & TMREGISTER && !M_is_reg)
0455     {
0456         if (EXSUCCEED!=ax_reg(M_rmid, &xid, 0))
0457         {
0458             NDRX_LOG(log_error, "TESTERROR!!! xa_reg() failed!");
0459             ret=EXFAIL;
0460             goto out;
0461         }
0462         
0463         if (XA_OK!=xa_start_entry(G_atmi_env.xa_sw, &xid, M_rmid, 0))
0464         {
0465             NDRX_LOG(log_error, "TESTERROR!!! xa_start_entry() failed!");
0466             ret=EXFAIL;
0467             goto out;
0468         }
0469         
0470         M_is_reg = EXTRUE;
0471     }
0472     
0473     if (NULL==M_f)
0474     {
0475         NDRX_LOG(log_error, "TESTERROR!!! write with no tx file!!!");
0476         ret=EXFAIL;
0477         goto out;
0478     }
0479     
0480     if (fprintf(M_f, "%s", buf) < len)
0481     {
0482         NDRX_LOG(log_error, "TESTERROR!!! Failed to write to transaction!");
0483         ret=EXFAIL;
0484         goto out;
0485     }
0486     
0487 out:
0488     return ret;
0489 }
0490 
0491 /**
0492  * CURRENTLY NOT USED!!!
0493  * @param sw
0494  * @param xid
0495  * @param count
0496  * @param rmid
0497  * @param flags
0498  * @return 
0499  */
0500 expublic int xa_recover_entry(struct xa_switch_t *sw, XID *xid, long count, int rmid, long flags)
0501 {
0502     if (!M_is_open)
0503     {
0504         NDRX_LOG(log_error, "TESTERROR!!! xa_recover_entry() - XA not open!");
0505         return XAER_RMERR;
0506     }
0507     
0508     NDRX_LOG(log_error, "WARNING!!! xa_recover_entry() - STUB!!");
0509     return 0; /* 0 transactions found... */
0510 }
0511 
0512 /**
0513  * CURRENTLY NOT USED!!!
0514  * @param sw
0515  * @param xid
0516  * @param rmid
0517  * @param flags
0518  * @return 
0519  */
0520 expublic int xa_forget_entry(struct xa_switch_t *sw, XID *xid, int rmid, long flags)
0521 {
0522    if (!M_is_open)
0523     {
0524         NDRX_LOG(log_error, "TESTERROR!!! xa_forget_entry() - XA not open!");
0525         return XAER_RMERR;
0526     }
0527     
0528     NDRX_LOG(log_error, "TESTERROR!!! xa_forget_entry() - not implemented!!");
0529     return XAER_RMERR;
0530 }
0531 
0532 /**
0533  * CURRENTLY NOT USED!!!
0534  * @param sw
0535  * @param handle
0536  * @param retval
0537  * @param rmid
0538  * @param flags
0539  * @return 
0540  */
0541 expublic int xa_complete_entry(struct xa_switch_t *sw, int *handle, int *retval, int rmid, long flags)
0542 {
0543     if (!M_is_open)
0544     {
0545         NDRX_LOG(log_error, "TESTERROR!!! xa_complete_entry() - XA not open!");
0546         return XAER_RMERR;
0547     }
0548     
0549     NDRX_LOG(log_error, "TESTERROR!!! xa_complete_entry() - not using!!");
0550     return XAER_RMERR;
0551 }
0552 
0553 
0554 /* Static entries */
0555 expublic int xa_open_entry_stat( char *xa_info, int rmid, long flags)
0556 {
0557     return xa_open_entry(&ndrxstatsw, xa_info, rmid, flags);
0558 }
0559 expublic int xa_close_entry_stat(char *xa_info, int rmid, long flags)
0560 {
0561     return xa_close_entry(&ndrxstatsw, xa_info, rmid, flags);
0562 }
0563 expublic int xa_start_entry_stat(XID *xid, int rmid, long flags)
0564 {
0565     return xa_start_entry(&ndrxstatsw, xid, rmid, flags);
0566 }
0567 
0568 /**
0569  * For test case #160, retry to reconnect...
0570  * So on every 3 start we return SUCCEED;
0571  * @param xid
0572  * @param rmid
0573  * @param flags
0574  * @return 
0575  */
0576 expublic int xa_start_entry_statstartfail(XID *xid, int rmid, long flags)
0577 {
0578     static __thread int cntr = 0;
0579     cntr++;
0580     
0581     if (0!=cntr%3)
0582     {
0583         NDRX_LOG(log_error, "start FAIL (%d) - close connection too...", cntr);
0584         M_is_open = EXFALSE;
0585         return XAER_RMERR;
0586     }
0587     else
0588     {
0589         return xa_start_entry(&ndrxstatsw, xid, rmid, flags);
0590     }
0591     
0592 }
0593 
0594 expublic int xa_end_entry_stat(XID *xid, int rmid, long flags)
0595 {
0596     return xa_end_entry(&ndrxstatsw, xid, rmid, flags);
0597 }
0598 expublic int xa_rollback_entry_stat(XID *xid, int rmid, long flags)
0599 {
0600     return xa_rollback_entry(&ndrxstatsw, xid, rmid, flags);
0601 }
0602 expublic int xa_prepare_entry_stat(XID *xid, int rmid, long flags)
0603 {
0604     return xa_prepare_entry(&ndrxstatsw, xid, rmid, flags);
0605 }
0606 
0607 /**
0608  * Test case for bug 105 - abort after transaction is prepared...
0609  * @param xid
0610  * @param rmid
0611  * @param flags
0612  * @return 
0613  */
0614 expublic int xa_prepare_entry_stat105(XID *xid, int rmid, long flags)
0615 {
0616     int ret =  xa_prepare_entry(&ndrxstatsw, xid, rmid, flags);
0617     
0618     /* seems have issues with freebsd ... abort();*/
0619     NDRX_LOG(log_error, "105 - simulating failure at prepare!");
0620     exit(EXFAIL);
0621 }
0622 
0623 expublic int xa_commit_entry_stat(XID *xid, int rmid, long flags)
0624 {
0625     return xa_commit_entry(&ndrxstatsw, xid, rmid, flags);
0626 }
0627 
0628 /**
0629  * Bug #123 - test try counter
0630  * @param xid
0631  * @param rmid
0632  * @param flags
0633  * @return 
0634  */
0635 expublic int xa_commit_entry_stat_tryok(XID *xid, int rmid, long flags)
0636 {
0637     static int try=0;
0638     char *fn = "xa_commit_entry_stat_tryok";
0639     
0640     try++;
0641     
0642     if (try > 10 || 2==rmid)
0643     {
0644         NDRX_LOG(log_error, "%s: try %d - continue,", fn, try);
0645         return xa_commit_entry(&ndrxstatsw, xid, rmid, flags);
0646     }
0647     else
0648     {
0649         NDRX_LOG(log_error, "%s: try %d - ret err", fn, try);
0650         return XA_RETRY;
0651     }
0652     
0653 }
0654 
0655 /**
0656  * Bug #123 - test try counter
0657  * @param xid
0658  * @param rmid
0659  * @param flags
0660  * @return 
0661  */
0662 expublic int xa_commit_entry_stat_tryfail(XID *xid, int rmid, long flags)
0663 {
0664     static int try=0;
0665     char *fn = "xa_commit_entry_stat_tryfail";
0666     try++;
0667 
0668     if (try > 30 || 2==rmid)
0669     {
0670         NDRX_LOG(log_error, "%s: try %d - continue", fn, try);
0671         return xa_commit_entry(&ndrxstatsw, xid, rmid, flags);
0672     }
0673     else
0674     {
0675         NDRX_LOG(log_error, "%s: try %d - ret err", fn, try);
0676         return XA_RETRY;
0677     }
0678 }
0679 
0680 expublic int xa_recover_entry_stat(XID *xid, long count, int rmid, long flags)
0681 {
0682     return xa_recover_entry(&ndrxstatsw, xid, count, rmid, flags);
0683 }
0684 expublic int xa_forget_entry_stat(XID *xid, int rmid, long flags)
0685 {
0686     return xa_forget_entry(&ndrxstatsw, xid, rmid, flags);
0687 }
0688 expublic int xa_complete_entry_stat(int *handle, int *retval, int rmid, long flags)
0689 {
0690     return xa_complete_entry(&ndrxstatsw, handle, retval, rmid, flags);
0691 }
0692 
0693 /* Dynamic entries */
0694 expublic int xa_open_entry_dyn( char *xa_info, int rmid, long flags)
0695 {
0696     return xa_open_entry(&ndrxdynsw, xa_info, rmid, flags);
0697 }
0698 expublic int xa_close_entry_dyn(char *xa_info, int rmid, long flags)
0699 {
0700     return xa_close_entry(&ndrxdynsw, xa_info, rmid, flags);
0701 }
0702 expublic int xa_start_entry_dyn(XID *xid, int rmid, long flags)
0703 {
0704     return xa_start_entry(&ndrxdynsw, xid, rmid, flags);
0705 }
0706 expublic int xa_end_entry_dyn(XID *xid, int rmid, long flags)
0707 {
0708     return xa_end_entry(&ndrxdynsw, xid, rmid, flags);
0709 }
0710 expublic int xa_rollback_entry_dyn(XID *xid, int rmid, long flags)
0711 {
0712     return xa_rollback_entry(&ndrxdynsw, xid, rmid, flags);
0713 }
0714 expublic int xa_prepare_entry_dyn(XID *xid, int rmid, long flags)
0715 {
0716     return xa_prepare_entry(&ndrxdynsw, xid, rmid, flags);
0717 }
0718 expublic int xa_commit_entry_dyn(XID *xid, int rmid, long flags)
0719 {
0720     return xa_commit_entry(&ndrxdynsw, xid, rmid, flags);
0721 }
0722 expublic int xa_recover_entry_dyn(XID *xid, long count, int rmid, long flags)
0723 {
0724     return xa_recover_entry(&ndrxdynsw, xid, count, rmid, flags);
0725 }
0726 expublic int xa_forget_entry_dyn(XID *xid, int rmid, long flags)
0727 {
0728     return xa_forget_entry(&ndrxdynsw, xid, rmid, flags);
0729 }
0730 expublic int xa_complete_entry_dyn(int *handle, int *retval, int rmid, long flags)
0731 {
0732     return xa_complete_entry(&ndrxdynsw, handle, retval, rmid, flags);
0733 }
0734 /* vim: set ts=4 sw=4 et smartindent: */