Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Routines related with local RM management.
0003  *
0004  * @file local.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 #include <stdio.h>
0035 #include <stdlib.h>
0036 #include <string.h>
0037 #include <errno.h>
0038 #include <regex.h>
0039 #include <utlist.h>
0040 
0041 #include <ndebug.h>
0042 #include <atmi.h>
0043 #include <atmi_int.h>
0044 #include <typed_buf.h>
0045 #include <ndrstandard.h>
0046 #include <ubf.h>
0047 #include <Exfields.h>
0048 #include <tperror.h>
0049 #include <exnet.h>
0050 #include <ndrxdcmn.h>
0051 
0052 #include "tmsrv.h"
0053 #include "../libatmisrv/srv_int.h"
0054 #include <xa_cmn.h>
0055 #include <atmi_int.h>
0056 /*---------------------------Externs------------------------------------*/
0057 /*---------------------------Macros-------------------------------------*/
0058 /*---------------------------Enums--------------------------------------*/
0059 /*---------------------------Typedefs-----------------------------------*/
0060 /*---------------------------Globals------------------------------------*/
0061 /*---------------------------Statics------------------------------------*/
0062 /*---------------------------Prototypes---------------------------------*/
0063 
0064 /******************************************************************************/
0065 /*                         PREPARE SECTION                                    */
0066 /******************************************************************************/
0067 /**
0068  * Prepare local transaction.
0069  * @param p_xai
0070  * @return 
0071  */
0072 expublic int tm_prepare_local(UBFH *p_ub, atmi_xa_tx_info_t *p_xai, long btid)
0073 {
0074     int ret = EXSUCCEED;
0075     int lev = log_error;
0076     
0077     /* we should start new transaction... */
0078     if (EXSUCCEED!=(ret = atmi_xa_prepare_entry(atmi_xa_get_branch_xid(p_xai, btid),
0079             0)))
0080     {
0081         /* get the reason, if XA_RDONLY, then just debug only... */
0082         if (XA_RDONLY==atmi_xa_get_reason())
0083         {
0084             lev=log_debug;
0085         }
0086         
0087         NDRX_LOG(lev, "Failed to prepare local transaction btid=%ld!", btid);
0088         if (NULL!=p_ub)
0089         {
0090             atmi_xa_set_error_fmt(p_ub, tperrno, atmi_xa_get_reason(), 
0091                     "Failed to prepare local transaction, "
0092                     "btid %ld, xa error: %d [%s]", btid, ret, atmi_xa_geterrstr(ret));
0093         }
0094         /* ATMI error already set by lib */
0095         goto out;
0096     }
0097     
0098 out:
0099     return ret;
0100 }
0101 
0102 /**
0103  * Do remote prepare call
0104  * @param p_xai
0105  * @param[in] btid Branch TID
0106  * @return SUCCEED/FAIL
0107  */
0108 expublic int tm_prepare_remote_call(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0109 {
0110     UBFH* p_ub;
0111             
0112     /* Call the remote TM.
0113      * TODO: How about error handling? 
0114      * - In case of TPNOENT for some reason we do not abort the transaction!
0115      */
0116     p_ub=atmi_xa_call_tm_generic(ATMI_XA_TMPREPARE, EXTRUE, rmid, p_xai, 0L, btid);
0117 
0118     if (NULL==p_ub)    
0119         return EXFAIL;
0120     else
0121     {
0122         tpfree((char *)p_ub);
0123         return EXSUCCEED;
0124     }
0125 }
0126 
0127 /**
0128  * Combined prepare of to commit. Selects automatically do the local prepare or
0129  * remote depending on RMID.
0130  */
0131 expublic int tm_prepare_combined(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0132 {
0133     int ret = EXSUCCEED;
0134     
0135     /* Check is this local */
0136     if (rmid == G_atmi_env.xa_rmid)
0137     {
0138         ret  = tm_prepare_local(NULL, p_xai, btid);
0139     }
0140     else
0141     {
0142         ret = tm_prepare_remote_call(p_xai, rmid, btid);
0143     }
0144     
0145 out:
0146     return ret;
0147 }
0148 
0149 /******************************************************************************/
0150 /*                         ROLLBACK SECTION                                   */
0151 /******************************************************************************/
0152 /**
0153  * Abort current RM transaction
0154  * @param p_xai
0155  * @param[in] btid branch tid
0156  * @return XA error code.
0157  */
0158 expublic int tm_rollback_local(UBFH *p_ub, atmi_xa_tx_info_t *p_xai, long btid)
0159 {
0160     int ret = EXSUCCEED;
0161     
0162     /* we should start new transaction... */
0163     if (EXSUCCEED!=(ret = atmi_xa_rollback_entry(atmi_xa_get_branch_xid(p_xai, btid), 
0164             0)))
0165     {
0166         NDRX_LOG(log_error, "Failed to abort transaction, btid: %ld!", btid);
0167         if (NULL!=p_ub)
0168         {
0169             atmi_xa_set_error_fmt(p_ub, tperrno, atmi_xa_get_reason(), 
0170                     "Failed to abort transaction, "
0171                     "btid %ld, xa error: %d [%s]", btid, ret, atmi_xa_geterrstr(ret));
0172         }
0173         /* ATMI error already set by lib */
0174         goto out;
0175     }
0176     
0177 out:
0178     return ret;
0179 }
0180 
0181 /**
0182  * Do remote rollback call
0183  * @param p_xai
0184  * @return SUCCEED/FAIL
0185  */
0186 expublic int tm_rollback_remote_call(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0187 {
0188     UBFH* p_ub;
0189             
0190     /* Call the remote TM.
0191      * TODO: How about error handling? 
0192      */
0193     p_ub=atmi_xa_call_tm_generic(ATMI_XA_TMABORT, EXTRUE, rmid, p_xai, 0L, btid);
0194 
0195     if (NULL==p_ub)    
0196         return EXFAIL;
0197     else
0198     {
0199         tpfree((char *)p_ub);
0200         return EXSUCCEED;
0201     }
0202 }
0203 
0204 /**
0205  * Combined rollback of to commit. Selects automatically do the local rollback or
0206  * remote depending on RMID.
0207  */
0208 expublic int tm_rollback_combined(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0209 {
0210     int ret = EXSUCCEED;
0211     
0212     /* Check is this local */
0213     if (rmid == G_atmi_env.xa_rmid)
0214     {
0215         ret  = tm_rollback_local(NULL, p_xai, btid);
0216     }
0217     else
0218     {
0219         ret = tm_rollback_remote_call(p_xai, rmid, btid);
0220     }
0221     
0222 out:
0223     return ret;
0224 }
0225 /******************************************************************************/
0226 /*                         FORGET SECTION                                     */
0227 /******************************************************************************/
0228 /**
0229  * Forget current RM transaction
0230  * @param p_xai
0231  * @param[in] btid branch tid
0232  * @return XA error code.
0233  */
0234 expublic int tm_forget_local(UBFH *p_ub, atmi_xa_tx_info_t *p_xai, long btid)
0235 {
0236     int ret = EXSUCCEED;
0237     
0238     /* we should start new transaction... */
0239     if (EXSUCCEED!=(ret = atmi_xa_forget_entry(atmi_xa_get_branch_xid(p_xai, btid), 
0240             0)))
0241     {
0242         NDRX_LOG(log_error, "Failed to abort transaction, btid: %ld!", btid);
0243         if (NULL!=p_ub)
0244         {
0245             atmi_xa_set_error_fmt(p_ub, tperrno, atmi_xa_get_reason(), 
0246                     "Failed to abort transaction, "
0247                     "btid %ld, xa error: %d [%s]", btid, ret, atmi_xa_geterrstr(ret));
0248         }
0249         /* ATMI error already set by lib */
0250         goto out;
0251     }
0252     
0253 out:
0254     return ret;
0255 }
0256 
0257 /**
0258  * Do remote forget call
0259  * @param p_xai
0260  * @return SUCCEED/FAIL
0261  */
0262 expublic int tm_forget_remote_call(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0263 {
0264     UBFH* p_ub;
0265             
0266     /* 
0267      * Call the remote TM.
0268      */
0269     p_ub=atmi_xa_call_tm_generic(ATMI_XA_TMFORGET, EXTRUE, rmid, p_xai, 0L, btid);
0270 
0271     if (NULL==p_ub)    
0272         return EXFAIL;
0273     else
0274     {
0275         tpfree((char *)p_ub);
0276         return EXSUCCEED;
0277     }
0278 }
0279 
0280 /**
0281  * Combined forget of to forget. Selects automatically do the local forget or
0282  * remote depending on RMID.
0283  */
0284 expublic int tm_forget_combined(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0285 {
0286     int ret = EXSUCCEED;
0287     
0288     /* Check is this local */
0289     if (rmid == G_atmi_env.xa_rmid)
0290     {
0291         ret  = tm_forget_local(NULL, p_xai, btid);
0292     }
0293     else
0294     {
0295         ret = tm_forget_remote_call(p_xai, rmid, btid);
0296     }
0297     
0298 out:
0299     return ret;
0300 }
0301 
0302 /******************************************************************************/
0303 /*                         COMMIT SECTION                                   */
0304 /******************************************************************************/
0305 /**
0306  * Abort current RM transaction
0307  * @param p_xai
0308  * @return XA error code.
0309  */
0310 expublic int tm_commit_local(UBFH *p_ub, atmi_xa_tx_info_t *p_xai, long btid)
0311 {
0312     int ret = EXSUCCEED;
0313     
0314     /* we should start new transaction... */
0315     if (EXSUCCEED!=(ret = atmi_xa_commit_entry(atmi_xa_get_branch_xid(p_xai, btid), 0)))
0316     {
0317         NDRX_LOG(log_error, "Failed to commit transaction btid %ld!", btid);
0318         
0319         if (NULL!=p_ub)
0320         {
0321             atmi_xa_set_error_fmt(p_ub, tperrno, atmi_xa_get_reason(), 
0322                     "Failed to commit transaction, "
0323                     "btid %ld, xa error: %d [%s]", btid, ret, atmi_xa_geterrstr(ret));
0324         }
0325         /* ATMI error already set by lib */
0326         goto out;
0327     }
0328     
0329 out:
0330     return ret;
0331 }
0332 
0333 /**
0334  * Do remote commit call
0335  * @param p_xai
0336  * @return SUCCEED/FAIL
0337  */
0338 expublic int tm_commit_remote_call(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0339 {
0340     UBFH* p_ub;
0341             
0342     /* Call the remote TM.
0343      * TODO: How about error handling? 
0344      */
0345     p_ub=atmi_xa_call_tm_generic(ATMI_XA_TMCOMMIT, EXTRUE, rmid, p_xai, 0L, btid);
0346 
0347     if (NULL==p_ub)    
0348         return EXFAIL;
0349     else
0350     {
0351         tpfree((char *)p_ub);
0352         return EXSUCCEED;
0353     }
0354 }
0355 
0356 /**
0357  * Combined commit of to commit. Selects automatically do the local commit or
0358  * remote depending on RMID.
0359  */
0360 expublic int tm_commit_combined(atmi_xa_tx_info_t *p_xai, short rmid, long btid)
0361 {
0362     int ret = EXSUCCEED;
0363     
0364     /* Check is this local */
0365     if (rmid == G_atmi_env.xa_rmid)
0366     {
0367         ret  = tm_commit_local(NULL, p_xai, btid);
0368     }
0369     else
0370     {
0371         ret = tm_commit_remote_call(p_xai, rmid, btid);
0372     }
0373     
0374 out:
0375     return ret;
0376 }
0377 /* vim: set ts=4 sw=4 et smartindent: */