Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief `printtrans' aka `pt' command implementation
0003  *
0004  * @file cmd_pt.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 <string.h>
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <memory.h>
0038 #include <sys/param.h>
0039 
0040 #include <ndrstandard.h>
0041 #include <ndebug.h>
0042 #include <nstdutil.h>
0043 
0044 #include <ndrxdcmn.h>
0045 #include <atmi_int.h>
0046 #include <gencall.h>
0047 #include <utlist.h>
0048 #include <Exfields.h>
0049 
0050 #include "xa_cmn.h"
0051 #include <ndrx.h>
0052 /*---------------------------Externs------------------------------------*/
0053 /*---------------------------Macros-------------------------------------*/
0054 /*---------------------------Enums--------------------------------------*/
0055 /*---------------------------Typedefs-----------------------------------*/
0056 /*---------------------------Globals------------------------------------*/
0057 /*---------------------------Statics------------------------------------*/
0058 
0059 /**
0060  * Mapping for transaction stages messages
0061  */
0062 expublic longstrmap_t M_txstatemap[] =
0063 {
0064     {XA_TX_STAGE_ACTIVE,    "ACTIVE"},
0065     {XA_TX_STAGE_PREPARING, "PREPARING"},
0066     {XA_TX_STAGE_ABORTING,  "ABORTING"},
0067     {XA_TX_STAGE_ABORTED,   "ABORTED"},
0068     {XA_TX_STAGE_COMMITTING,"COMMITTING"},
0069     {XA_TX_STAGE_COMMITTED ,"COMMITTED"},
0070     {XA_RM_STATUS_COMMIT_HEURIS , "COMMITTED, HEURISTIC"},
0071     {EXFAIL,                "?"}
0072 };
0073 
0074 /**
0075  * String mappings for RM statuses
0076  */
0077 expublic longstrmap_t M_rmstatus[] =
0078 {
0079     {XA_RM_STATUS_ACTIVE,       "JOINED"},
0080     {XA_RM_STATUS_PREP,         "PREPARED"},
0081     {XA_RM_STATUS_ABORTED,      "ABORTED"},
0082     {XA_RM_STATUS_COMMITTED,    "COMMITTED"},
0083     {XA_RM_STATUS_COMMITTED_RO, "COMMITTED_RO"},
0084     {0,                         "?"}
0085 };
0086 
0087 /*---------------------------Prototypes---------------------------------*/
0088 
0089 /**
0090  * List transactions in progress
0091  * We will run in conversation mode.
0092  * @param svcnm
0093  * @return SUCCEED/FAIL
0094  */
0095 exprivate int print_buffer(UBFH *p_ub, char *svcnm)
0096 {
0097     int ret = EXSUCCEED;
0098     char tmxid[NDRX_XID_SERIAL_BUFSIZE+1];
0099     short tmrmid;
0100     short tmnodeid;
0101     short tmsrvid;
0102 
0103     long tmtxtout;
0104     long tmtxtout_left;
0105     short tmtxstage;
0106 
0107     /* Process in loop: */
0108     short tmtxrmid;
0109     char tmtxrmstatus;
0110     long tmtxrmerrcode;
0111     short tmtxrmreason;
0112     long tmtxrmbtid;
0113     int i;
0114     int occ;
0115     long trycount, max_tries;
0116     
0117     if (
0118             EXSUCCEED!=Bget(p_ub, TMXID, 0, (char *)tmxid, 0L) ||
0119             EXSUCCEED!=Bget(p_ub, TMRMID, 0, (char *)&tmrmid, 0L) ||
0120             EXSUCCEED!=Bget(p_ub, TMNODEID, 0, (char *)&tmnodeid, 0L) ||
0121             EXSUCCEED!=Bget(p_ub, TMSRVID, 0, (char *)&tmsrvid, 0L) ||
0122             EXSUCCEED!=Bget(p_ub, TMTXTOUT, 0, (char *)&tmtxtout, 0L) ||
0123             EXSUCCEED!=Bget(p_ub, TMTXTOUT_LEFT, 0, (char *)&tmtxtout_left, 0L) ||
0124             EXSUCCEED!=Bget(p_ub, TMTXSTAGE, 0, (char *)&tmtxstage, 0L) ||
0125             EXSUCCEED!=Bget(p_ub, TMTXTRYCNT, 0, (char *)&trycount, 0L) ||
0126             EXSUCCEED!=Bget(p_ub, TMTXTRYMAXCNT, 0, (char *)&max_tries, 0L)
0127         )
0128     {
0129         fprintf(stderr, "Protocol error - TM did not return data, see logs!\n");
0130         NDRX_LOG(log_error, "Failed to read fields: [%s]", 
0131                 Bstrerror(Berror));
0132         EXFAIL_OUT(ret);
0133     }
0134 
0135     occ = Boccur(p_ub, TMTXRMSTATUS);
0136     
0137     /* TODO: need tx status human-readable version */
0138     printf("xid=[%s]\n"
0139             "TM: Node Id: %hd, grpno: %hd, srvid: %hd, Transaction stage: %hd-%s\n"
0140             "(TM ref: -t%s -x%s)\n"
0141             "Group count: %d, timeout: %ld, time left: %ld, tries: %ld of %ld\n"
0142             "Known participants:\n",
0143             tmxid, tmnodeid, tmrmid, tmsrvid, tmtxstage, 
0144             ndrx_dolongstrgmap(M_txstatemap, tmtxstage, EXFAIL),
0145             svcnm, tmxid,
0146             occ, tmtxtout, tmtxtout_left, trycount, max_tries);
0147     
0148     for (i=0; i<occ; i++)
0149     {
0150         if (
0151                 EXSUCCEED!=Bget(p_ub, TMTXRMID, i, (char *)&tmtxrmid, 0L) ||
0152                 EXSUCCEED!=Bget(p_ub, TMTXRMSTATUS, i, (char *)&tmtxrmstatus, 0L) ||
0153                 EXSUCCEED!=Bget(p_ub, TMTXRMERRCODE, i, (char *)&tmtxrmerrcode, 0L) ||
0154                 EXSUCCEED!=Bget(p_ub, TMTXRMREASON, i, (char *)&tmtxrmreason, 0L) ||
0155                 EXSUCCEED!=Bget(p_ub, TMTXBTID, i, (char *)&tmtxrmbtid, 0L)
0156                 )
0157         {
0158             /* TODO: need RM status human-readable version */
0159             fprintf(stderr, "Protocol error - TM did not return data, see logs!\n");
0160             NDRX_LOG(log_error, "Failed to return fields: [%s]", 
0161                         Bstrerror(Berror));
0162             EXFAIL_OUT(ret);
0163         }
0164         else
0165         {
0166             printf("\tgrpno: %hd, btid: %ld status: %c-%s, errorcode: %ld, reason: %hd\n",
0167                     tmtxrmid, tmtxrmbtid, tmtxrmstatus, 
0168                     ndrx_docharstrgmap(M_rmstatus, tmtxrmstatus, 0), 
0169                     tmtxrmerrcode, tmtxrmreason);
0170         }
0171     }
0172     
0173     printf("\n");
0174     
0175 out:
0176     return ret;
0177 }
0178 
0179 /**
0180  * This basically tests the normal case when all have been finished OK!
0181  * @return
0182  */
0183 exprivate int call_tm(char *svcnm)
0184 {
0185   UBFH *p_ub = atmi_xa_alloc_tm_call(ATMI_XA_PRINTTRANS);
0186     int ret=EXSUCCEED;
0187     int cd;
0188     long revent;
0189     int recv_continue = 1;
0190     int tp_errno;
0191     int rcv_count = 0;
0192     
0193     /* Setup the call buffer... */
0194     if (NULL==p_ub)
0195     {
0196         NDRX_LOG(log_error, "Failed to alloc FB!");        
0197         EXFAIL_OUT(ret);
0198     }
0199     
0200     if (EXFAIL == (cd = tpconnect(svcnm,
0201                                     (char *)p_ub,
0202                                     0,
0203                                     TPNOTRAN |
0204                                     TPRECVONLY)))
0205     {
0206         NDRX_LOG(log_error, "Connect error [%s]", tpstrerror(tperrno) );
0207         ret = EXFAIL;
0208         goto out;
0209     }
0210     NDRX_LOG(log_debug, "Connected OK, cd = %d", cd );
0211 
0212     while (recv_continue)
0213     {
0214         recv_continue=0;
0215         if (EXFAIL == tprecv(cd,
0216                             (char **)&p_ub,
0217                             0L,
0218                             0L,
0219                             &revent))
0220         {
0221             ret = EXFAIL;
0222             tp_errno = tperrno;
0223             if (TPEEVENT == tp_errno)
0224             {
0225                     if (TPEV_SVCSUCC == revent)
0226                             ret = EXSUCCEED;
0227                     else
0228                     {
0229                         NDRX_LOG(log_error,
0230                                  "Unexpected conv event %lx", revent );
0231                         EXFAIL_OUT(ret);
0232                     }
0233             }
0234             else
0235             {
0236                 NDRX_LOG(log_error, "recv error %d", tp_errno  );
0237                 EXFAIL_OUT(ret);
0238             }
0239         }
0240         else
0241         {
0242             /*fprintf(stderr, "Response: \n");
0243             Bfprint(p_ub, stderr);*/
0244             if (EXSUCCEED!=print_buffer(p_ub, svcnm))
0245             {
0246                 EXFAIL_OUT(ret);
0247             }
0248             rcv_count++;
0249             recv_continue=1;
0250         }
0251     }
0252 
0253 out:
0254 
0255     if (NULL!=p_ub)
0256     {
0257         tpfree((char *)p_ub);
0258     }
0259 /*
0260     tpdiscon(cd);
0261 */
0262     return ret;
0263 }
0264 
0265 /**
0266  * Print XA transactions
0267  * @param p_cmd_map
0268  * @param argc
0269  * @param argv
0270  * @return SUCCEED
0271  */
0272 expublic int cmd_pt(cmd_mapping_t *p_cmd_map, int argc, char **argv, int *p_have_next)
0273 {
0274     int ret = EXSUCCEED;
0275     atmi_svc_list_t *el, *tmp, *list;
0276     
0277     /* we need to init TP subsystem... */
0278     if (EXSUCCEED!=tpinit(NULL))
0279     {
0280         fprintf(stderr, "Failed to tpinit(): %s\n", tpstrerror(tperrno));
0281         EXFAIL_OUT(ret);
0282     }
0283     
0284     list = ndrx_get_svc_list(ndrx_tmfilter_srv);
0285     
0286     LL_FOREACH_SAFE(list,el,tmp)
0287     {
0288         
0289         NDRX_LOG(log_info, "About to call service: [%s]\n", el->svcnm);
0290 
0291         call_tm(el->svcnm);
0292         /* Have some housekeep. */
0293         LL_DELETE(list,el);
0294         NDRX_FREE(el);
0295     }
0296     
0297 out:
0298     return ret;
0299 }
0300 
0301 /* vim: set ts=4 sw=4 et smartindent: */