Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief `pc' (print clients) command implementation
0003  *
0004  * @file cmd_pc.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 #include <string.h>
0040 
0041 #include <ndrstandard.h>
0042 #include <ndebug.h>
0043 #include <nstdutil.h>
0044 
0045 #include <ndrxdcmn.h>
0046 #include <atmi_int.h>
0047 #include <gencall.h>
0048 #include <utlist.h>
0049 #include <Exfields.h>
0050 
0051 #include "xa_cmn.h"
0052 #include <ndrx.h>
0053 #include <cpm.h>
0054 #include <nclopt.h>
0055 /*---------------------------Externs------------------------------------*/
0056 /*---------------------------Macros-------------------------------------*/
0057 #define SUBSECT_SEP     "/"
0058 /*---------------------------Enums--------------------------------------*/
0059 /*---------------------------Typedefs-----------------------------------*/
0060 /*---------------------------Globals------------------------------------*/
0061 /*---------------------------Statics------------------------------------*/
0062 /*---------------------------Prototypes---------------------------------*/
0063 
0064 /**
0065  * Print the processes
0066  * We will run in conversation mode.
0067  * @param svcnm
0068  * @return SUCCEED/FAIL
0069  */
0070 exprivate int print_buffer(UBFH *p_ub, char *svcnm)
0071 {
0072     int ret = EXSUCCEED;
0073     char output[CPM_OUTPUT_SIZE];
0074     
0075     if (EXSUCCEED!=Bget(p_ub, EX_CPMOUTPUT, 0, (char *)output, 0L))
0076     {
0077         NDRX_LOG(log_error, "Failed to read fields: [%s]", 
0078                 Bstrerror(Berror));
0079         EXFAIL_OUT(ret);
0080     }
0081 
0082     printf("%s\n", output);
0083     
0084 out:
0085     return ret;
0086 }
0087 
0088 /**
0089  * This basically tests the normal case when all have been finished OK!
0090  * @param procgrp process group top operate with
0091  * @return
0092  */
0093 exprivate int call_cpm(char *svcnm, char *cmd, char *tag, char *subsect, char *procgrp, long twait)
0094 {
0095     UBFH *p_ub = (UBFH *)tpalloc("UBF", NULL, CPM_DEF_BUFFER_SZ);
0096     int ret=EXSUCCEED;
0097     int cd;
0098     long revent;
0099     int recv_continue = 1;
0100     int tp_errno;
0101     int rcv_count = 0;
0102     long flags = TPNOTRAN | TPRECVONLY;
0103     
0104     /* Setup the call buffer... */
0105     if (NULL==p_ub)
0106     {
0107         NDRX_LOG(log_error, "Failed to alloc FB!");        
0108         EXFAIL_OUT(ret);
0109     }
0110     
0111     if (twait > 0)
0112     {
0113         if (EXSUCCEED!=Bchg(p_ub, EX_CPMWAIT, 0, (char *)&twait, 0L))
0114         {
0115             NDRX_LOG(log_error, "Failed to set EX_CPMWAIT: %s!", Bstrerror(Berror));
0116             EXFAIL_OUT(ret);
0117         }
0118     }
0119     
0120     if (EXSUCCEED!=Bchg(p_ub, EX_CPMCOMMAND, 0, cmd, 0L))
0121     {
0122         NDRX_LOG(log_error, "Failed to set EX_CPMCOMMAND to %s!", EX_CPMCOMMAND);        
0123         EXFAIL_OUT(ret);
0124     }
0125     
0126     if (0!=strcmp(CPM_CMD_PC, cmd))
0127     {
0128         if (tag[0] && procgrp[0])
0129         {
0130             NDRX_LOG(log_error, "-t and -g cannot be combined");
0131             EXFAIL_OUT(ret);
0132         }
0133 
0134         /* - is basically empty value for tag */
0135         if (subsect[0] && procgrp[0] && subsect[0]!='-')
0136         {
0137             NDRX_LOG(log_error, "-s and -g cannot be combined");
0138             EXFAIL_OUT(ret);
0139         }
0140 
0141         if (EXSUCCEED!=Bchg(p_ub, EX_CPMTAG, 0, tag, 0L))
0142         {
0143             NDRX_LOG(log_error, "Failed to set EX_CPMCOMMAND to %s!", tag);        
0144             EXFAIL_OUT(ret);
0145         }
0146 
0147         if (EXSUCCEED!=Bchg(p_ub, EX_CPMSUBSECT, 0, subsect, 0L))
0148         {
0149             NDRX_LOG(log_error, "Failed to set EX_CPMSUBSECT to %s!", subsect);        
0150             EXFAIL_OUT(ret);
0151         }
0152 
0153         if (EXSUCCEED!=Bchg(p_ub, EX_CPMPROCGRP, 0, procgrp, 0L))
0154         {
0155             NDRX_LOG(log_error, "Failed to set EX_CPMPROCGRP to %s!", subsect);        
0156             EXFAIL_OUT(ret);
0157         }
0158     }
0159     
0160     /* if we run batch commands, the no time-out please */
0161     
0162     if (EXFAIL == (cd = tpconnect(svcnm,
0163                                     (char *)p_ub,
0164                                     0,
0165                                     TPNOTRAN |
0166                                     TPRECVONLY)))
0167     {
0168         NDRX_LOG(log_error, "Connect error [%s]", tpstrerror(tperrno) );
0169         
0170         ret = EXFAIL;
0171         goto out;
0172     }
0173     NDRX_LOG(log_debug, "Connected OK, cd = %d", cd );
0174 
0175     while (recv_continue)
0176     {
0177         recv_continue=0;
0178         if (EXFAIL == tprecv(cd,
0179                             (char **)&p_ub,
0180                             0L,
0181                             0L,
0182                             &revent))
0183         {
0184             ret = EXFAIL;
0185             tp_errno = tperrno;
0186             if (TPEEVENT == tp_errno)
0187             {
0188                 if (TPEV_SVCSUCC == revent)
0189                 {
0190                         ret = EXSUCCEED;
0191                 }
0192                 else
0193                 {
0194                     NDRX_LOG(log_error,
0195                              "Unexpected conv event %lx", revent );
0196                     EXFAIL_OUT(ret);
0197                 }
0198             }
0199             else if (TPETIME == tp_errno)
0200             {
0201                 fprintf(stderr, "Error ! Timeout waiting on server reply, -w shall be smaller than NDRX_TOUT env.\n");
0202                 fprintf(stderr, "The cpmsrv will complete the operation in background...\n");
0203             }
0204             else
0205             {
0206                 NDRX_LOG(log_error, "recv error %d", tp_errno  );
0207                 EXFAIL_OUT(ret);
0208             }
0209         }
0210         else
0211         {
0212             /*
0213             fprintf(stderr, "Response: \n");
0214             Bfprint(p_ub, stderr);
0215             */
0216             if (EXSUCCEED!=print_buffer(p_ub, svcnm))
0217             {
0218                 EXFAIL_OUT(ret);
0219             }
0220             rcv_count++;
0221             recv_continue=1;
0222         }
0223     }
0224 
0225 out:
0226 
0227     if (NULL!=p_ub)
0228     {
0229         tpfree((char *)p_ub);
0230     }
0231 /*
0232     tpdiscon(cd);
0233 */
0234     return ret;
0235 }
0236 
0237 /**
0238  * Print Clients
0239  * @param p_cmd_map
0240  * @param argc
0241  * @param argv
0242  * @return SUCCEED
0243  */
0244 expublic int cmd_pc(cmd_mapping_t *p_cmd_map, int argc, char **argv, int *p_have_next)
0245 {
0246     int ret = EXSUCCEED;
0247     
0248     call_cpm(NDRX_SVC_CPM, CPM_CMD_PC, NULL, NULL, NULL, 0);
0249     
0250 out:
0251     return ret;
0252 }
0253 
0254 /**
0255  * Stop client
0256  * @param p_cmd_map
0257  * @param argc
0258  * @param argv
0259  * @return SUCCEED
0260  */
0261 expublic int cmd_sc(cmd_mapping_t *p_cmd_map, int argc, char **argv, int *p_have_next)
0262 {
0263     int ret = EXSUCCEED;
0264     char tag[CPM_TAG_LEN]={EXEOS};
0265     char subsect[CPM_SUBSECT_LEN] = {"-"};
0266     char procgrp[MAXTIDENT+1] = {EXEOS};
0267     long twait = 0;
0268     char *p;
0269     ncloptmap_t clopt[] =
0270     {
0271         {'t', BFLD_STRING, (void *)tag, sizeof(tag), 
0272                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Tag"},
0273         {'s', BFLD_STRING, (void *)subsect, sizeof(subsect), 
0274                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Subsection"},
0275         {'g', BFLD_STRING, (void *)procgrp, sizeof(procgrp), 
0276                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Process group name"},
0277         {'w', BFLD_LONG, (void *)&twait, sizeof(twait), 
0278                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Wait milliseconds"},
0279         {0}
0280     };
0281     
0282     if (argc>=2 && '-'!=argv[1][0])
0283     {
0284         /* parse the tag/sub */
0285         p = strtok(argv[1], SUBSECT_SEP);
0286         
0287         if (NULL!=p)
0288         {
0289             NDRX_STRCPY_SAFE(tag, p);
0290         }
0291         else
0292         {
0293             fprintf(stderr, "Missing tag! Syntax sc <TAG>[/SUBSECT], e.g. sc POS/1\n");
0294             EXFAIL_OUT(ret);
0295         }
0296         
0297         p = strtok(NULL, SUBSECT_SEP);
0298         
0299         if (NULL!=p)
0300         {
0301             NDRX_STRCPY_SAFE(subsect, p);
0302         }
0303     }
0304     else
0305     {
0306         /* parse command line */
0307         if (nstd_parse_clopt(clopt, EXTRUE,  argc, argv, EXFALSE))
0308         {
0309             fprintf(stderr, XADMIN_INVALID_OPTIONS_MSG);
0310             EXFAIL_OUT(ret);
0311         } 
0312         else if (EXEOS==tag[0] && EXEOS==procgrp[0])
0313         {
0314             fprintf(stderr, XADMIN_INVALID_OPTIONS_MSG);
0315             EXFAIL_OUT(ret);
0316         }
0317     }
0318     
0319     ret = call_cpm(NDRX_SVC_CPM, CPM_CMD_SC, tag, subsect, procgrp, twait);
0320     
0321 out:
0322     return ret;
0323 }
0324 
0325 /**
0326  * Boot client
0327  * @param p_cmd_map
0328  * @param argc
0329  * @param argv
0330  * @return SUCCEED
0331  */
0332 expublic int cmd_bc(cmd_mapping_t *p_cmd_map, int argc, char **argv, int *p_have_next)
0333 {
0334     int ret = EXSUCCEED;
0335     char tag[CPM_TAG_LEN]={EXEOS};
0336     char subsect[CPM_SUBSECT_LEN] = {"-"};
0337     char procgrp[MAXTIDENT+1] = {EXEOS};
0338     long twait = 0;
0339     char *p;
0340     ncloptmap_t clopt[] =
0341     {
0342         {'t', BFLD_STRING, (void *)tag, sizeof(tag), 
0343                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Tag"},
0344         {'s', BFLD_STRING, (void *)subsect, sizeof(subsect), 
0345                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Subsection"},
0346         {'g', BFLD_STRING, (void *)procgrp, sizeof(procgrp), 
0347                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Process group name"},
0348         {'w', BFLD_LONG, (void *)&twait, sizeof(twait), 
0349                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Wait milliseconds"},
0350         {0}
0351     };
0352     
0353     /* parse command line */
0354     if (argc>=2 && '-'!=argv[1][0])
0355     {
0356         /* parse the tag/sub */
0357         p = strtok(argv[1], SUBSECT_SEP);
0358         
0359         if (NULL!=p)
0360         {
0361             NDRX_STRCPY_SAFE(tag, p);
0362         }
0363         else
0364         {
0365             fprintf(stderr, "Missing tag! Syntax bc <TAG>[/SUBSECT], e.g. sc POS/1\n");
0366             EXFAIL_OUT(ret);
0367         }
0368         
0369         p = strtok(NULL, SUBSECT_SEP);
0370         
0371         if (NULL!=p)
0372         {
0373             NDRX_STRCPY_SAFE(subsect, p);
0374         }
0375     }
0376     else if (nstd_parse_clopt(clopt, EXTRUE,  argc, argv, EXFALSE))
0377     {
0378         fprintf(stderr, XADMIN_INVALID_OPTIONS_MSG);
0379         EXFAIL_OUT(ret);
0380     }
0381     else if (EXEOS==tag[0] && EXEOS==procgrp[0])
0382     {
0383         fprintf(stderr, XADMIN_INVALID_OPTIONS_MSG);
0384         EXFAIL_OUT(ret);
0385     }
0386 
0387     
0388     ret = call_cpm(NDRX_SVC_CPM, CPM_CMD_BC, tag, subsect, procgrp, twait);
0389     
0390 out:
0391     return ret;
0392 }
0393 
0394 /**
0395  * Reload client
0396  * @param p_cmd_map
0397  * @param argc
0398  * @param argv
0399  * @return SUCCEED
0400  */
0401 expublic int cmd_rc(cmd_mapping_t *p_cmd_map, int argc, char **argv, int *p_have_next)
0402 {
0403     int ret = EXSUCCEED;
0404     char tag[CPM_TAG_LEN]={EXEOS};
0405     char subsect[CPM_SUBSECT_LEN] = {"-"};
0406     char procgrp[MAXTIDENT+1] = {EXEOS};
0407     long twait = 0;
0408     char *p;
0409     
0410     ncloptmap_t clopt[] =
0411     {
0412         {'t', BFLD_STRING, (void *)tag, sizeof(tag), 
0413                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Tag"},
0414         {'s', BFLD_STRING, (void *)subsect, sizeof(subsect), 
0415                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Subsection"},
0416         {'g', BFLD_STRING, (void *)procgrp, sizeof(procgrp), 
0417                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Process group name"},
0418         {'w', BFLD_LONG, (void *)&twait, sizeof(twait), 
0419                                 NCLOPT_OPT | NCLOPT_HAVE_VALUE, "Wait milliseconds"},
0420         {0}
0421     };
0422     
0423     /* parse command line */
0424     if (argc>=2 && '-'!=argv[1][0])
0425     {
0426         /* parse the tag/sub */
0427         p = strtok(argv[1], SUBSECT_SEP);
0428         
0429         if (NULL!=p)
0430         {
0431             NDRX_STRCPY_SAFE(tag, p);
0432         }
0433         else
0434         {
0435             fprintf(stderr, "Missing tag! Syntax rc <TAG>[/SUBSECT], e.g. sc POS/1\n");
0436             EXFAIL_OUT(ret);
0437         }
0438         
0439         p = strtok(NULL, SUBSECT_SEP);
0440         
0441         if (NULL!=p)
0442         {
0443             NDRX_STRCPY_SAFE(subsect, p);
0444         }
0445     }
0446     else if (nstd_parse_clopt(clopt, EXTRUE,  argc, argv, EXFALSE))
0447     {
0448         fprintf(stderr, XADMIN_INVALID_OPTIONS_MSG);
0449         EXFAIL_OUT(ret);
0450     }
0451     else if (EXEOS==tag[0] && EXEOS==procgrp[0])
0452     {
0453         fprintf(stderr, XADMIN_INVALID_OPTIONS_MSG);
0454         EXFAIL_OUT(ret);
0455     }
0456     
0457     ret = call_cpm(NDRX_SVC_CPM, CPM_CMD_RC, tag, subsect, procgrp, twait);
0458     
0459 out:
0460     return ret;
0461 }
0462 
0463 /* vim: set ts=4 sw=4 et smartindent: */