Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief List persistent queues
0003  *
0004  * @file cmd_mqlq.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 #include <qcommon.h>
0053 /*---------------------------Externs------------------------------------*/
0054 /*---------------------------Macros-------------------------------------*/
0055 /*---------------------------Enums--------------------------------------*/
0056 /*---------------------------Typedefs-----------------------------------*/
0057 /*---------------------------Globals------------------------------------*/
0058 /*---------------------------Statics------------------------------------*/
0059 /*---------------------------Prototypes---------------------------------*/
0060 
0061 /**
0062  * Print header
0063  * @return
0064  */
0065 exprivate void print_hdr(void)
0066 {
0067     fprintf(stderr, "Nd SRVID QSPACE    QNAME     #QUEU #LOCK  #ENQ #DEQ  #SUCC #FAIL\n");
0068     fprintf(stderr, "-- ----- --------- --------- ----- ----- ----- ----- ----- -----\n");
0069 }
0070 
0071 
0072 /**
0073  * List transactions in progress
0074  * We will run in conversation mode.
0075  * @param svcnm
0076  * @return SUCCEED/FAIL
0077  */
0078 exprivate int print_buffer(UBFH *p_ub, char *svcnm)
0079 {
0080     int ret = EXSUCCEED;
0081     
0082     short nodeid;
0083     short srvid;
0084     char qspace[XATMI_SERVICE_NAME_LENGTH+1];
0085     char qname[TMQNAMELEN+1];
0086     long msgs;
0087     long locked;
0088     long succ;
0089     long fail;
0090     
0091     long numenq;
0092     long numdeq;
0093             
0094     if (
0095             EXSUCCEED!=Bget(p_ub, EX_QSPACE, 0, qspace, 0L) ||
0096             EXSUCCEED!=Bget(p_ub, EX_QNAME, 0, qname, 0L) ||
0097             EXSUCCEED!=Bget(p_ub, TMNODEID, 0, (char *)&nodeid, 0L) ||
0098             EXSUCCEED!=Bget(p_ub, TMSRVID, 0, (char *)&srvid, 0L) ||
0099             EXSUCCEED!=Bget(p_ub, EX_QNUMMSG, 0, (char *)&msgs, 0L) ||
0100             EXSUCCEED!=Bget(p_ub, EX_QNUMLOCKED, 0, (char *)&locked, 0L) ||
0101             EXSUCCEED!=Bget(p_ub, EX_QNUMSUCCEED, 0, (char *)&succ, 0L) ||
0102             EXSUCCEED!=Bget(p_ub, EX_QNUMFAIL, 0, (char *)&fail, 0L) ||
0103             EXSUCCEED!=Bget(p_ub, EX_QNUMENQ, 0, (char *)&numenq, 0L) ||
0104             EXSUCCEED!=Bget(p_ub, EX_QNUMDEQ, 0, (char *)&numdeq, 0L)
0105             
0106         )
0107     {
0108         fprintf(stderr, "Protocol error - TMQ did not return data, see logs!\n");
0109         NDRX_LOG(log_error, "Failed to read fields: [%s]", 
0110                 Bstrerror(Berror));
0111         EXFAIL_OUT(ret);
0112     }    
0113     
0114     FIX_SVC_NM_DIRECT(qspace, 9);
0115     FIX_SVC_NM_DIRECT(qname, 9);
0116     
0117     fprintf(stdout, "%2d %5d %-9.9s %-9.9s %5.5s %5.5s %5.5s %5.5s %5.5s %5.5s",
0118             nodeid, 
0119             srvid, 
0120             qspace, 
0121             qname,
0122             ndrx_decode_num(msgs, 0, 0, 1), 
0123             ndrx_decode_num(locked, 1, 0, 1),
0124             
0125             ndrx_decode_num(numenq, 2, 0, 2),
0126             ndrx_decode_num(numdeq, 3, 0, 2),
0127             
0128             ndrx_decode_num(succ, 4, 0, 2),
0129             ndrx_decode_num(fail, 5, 0, 2)
0130             );
0131     
0132     printf("\n");
0133     
0134 out:
0135     return ret;
0136 }
0137 
0138 /**
0139  * This basically tests the normal case when all have been finished OK!
0140  * @return
0141  */
0142 exprivate int call_tmq(char *svcnm)
0143 {
0144     UBFH *p_ub = (UBFH *)tpalloc("UBF", "", 1024);
0145     int ret=EXSUCCEED;
0146     int cd;
0147     long revent;
0148     int recv_continue = 1;
0149     int tp_errno;
0150     int rcv_count = 0;
0151     char cmd = TMQ_CMD_MQLQ;
0152     
0153     /* Setup the call buffer... */
0154     if (NULL==p_ub)
0155     {
0156         NDRX_LOG(log_error, "Failed to alloc FB!");        
0157         EXFAIL_OUT(ret);
0158     }
0159     
0160     if (EXSUCCEED!=Bchg(p_ub, EX_QCMD, 0, &cmd, 0L))
0161     {
0162         NDRX_LOG(log_error, "Failed to install command code");
0163         EXFAIL_OUT(ret);
0164     }
0165     
0166     if (EXFAIL == (cd = tpconnect(svcnm,
0167                                     (char *)p_ub,
0168                                     0,
0169                                     TPNOTRAN |
0170                                     TPRECVONLY)))
0171     {
0172         NDRX_LOG(log_error, "Connect error [%s]", tpstrerror(tperrno) );
0173         ret = EXFAIL;
0174         goto out;
0175     }
0176     NDRX_LOG(log_debug, "Connected OK, cd = %d", cd );
0177 
0178     while (recv_continue)
0179     {
0180         recv_continue=0;
0181         if (EXFAIL == tprecv(cd,
0182                             (char **)&p_ub,
0183                             0L,
0184                             0L,
0185                             &revent))
0186         {
0187             ret = EXFAIL;
0188             tp_errno = tperrno;
0189             if (TPEEVENT == tp_errno)
0190             {
0191                     if (TPEV_SVCSUCC == revent)
0192                             ret = EXSUCCEED;
0193                     else
0194                     {
0195                         NDRX_LOG(log_error,
0196                                  "Unexpected conv event %lx", revent );
0197                         EXFAIL_OUT(ret);
0198                     }
0199             }
0200             else
0201             {
0202                 NDRX_LOG(log_error, "recv error %d", tp_errno  );
0203                 EXFAIL_OUT(ret);
0204             }
0205         }
0206         else
0207         {
0208             if (EXSUCCEED!=print_buffer(p_ub, svcnm))
0209             {
0210                 EXFAIL_OUT(ret);
0211             }
0212             rcv_count++;
0213             recv_continue=1;
0214         }
0215     }
0216 
0217 out:
0218 
0219     if (NULL!=p_ub)
0220     {
0221         tpfree((char *)p_ub);
0222     }
0223 
0224     return ret;
0225 }
0226 
0227 /**
0228  * Filter the service names, return TRUE for those which matches individual TMs
0229  * @param svcnm
0230  * @return TRUE/FALSE
0231  */
0232 expublic int mqfilter(char *svcnm)
0233 {
0234     int i, len;
0235     int cnt = 0;
0236     
0237     if (0==strncmp(svcnm, "@TMQ", 4))
0238     {
0239         /* Now it should have 3x dashes inside */
0240         len = strlen(svcnm);
0241         for (i=0; i<len; i++)
0242         {
0243             if ('-'==svcnm[i])
0244             {
0245                 cnt++;
0246             }
0247         }
0248     }
0249     
0250     if (2==cnt)
0251         return EXTRUE;
0252     else
0253         return EXFALSE;
0254 }
0255 
0256 /**
0257  * List queues
0258  * @param p_cmd_map
0259  * @param argc
0260  * @param argv
0261  * @return SUCCEED
0262  */
0263 expublic int cmd_mqlq(cmd_mapping_t *p_cmd_map, int argc, char **argv, int *p_have_next)
0264 {
0265     int ret = EXSUCCEED;
0266     atmi_svc_list_t *el, *tmp, *list;
0267     
0268     /* we need to init TP subsystem... */
0269     if (EXSUCCEED!=tpinit(NULL))
0270     {
0271         fprintf(stderr, "Failed to tpinit(): %s\n", tpstrerror(tperrno));
0272         EXFAIL_OUT(ret);
0273     }
0274     
0275     print_hdr();
0276     
0277     list = ndrx_get_svc_list(mqfilter);
0278     
0279     LL_FOREACH_SAFE(list,el,tmp)
0280     {
0281         
0282         NDRX_LOG(log_info, "About to call service: [%s]\n", el->svcnm);
0283 
0284         call_tmq(el->svcnm);
0285         /* Have some housekeep. */
0286         LL_DELETE(list,el);
0287         NDRX_FREE(el);
0288     }
0289     
0290 out:
0291     return ret;
0292 }
0293 
0294 /* vim: set ts=4 sw=4 et smartindent: */