Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Main command processor.
0003  *   This serves requests/responses either from ndrx (admin utlity)
0004  *   or from EnduroX servers.
0005  *
0006  * @file cmd_processor.c
0007  */
0008 /* -----------------------------------------------------------------------------
0009  * Enduro/X Middleware Platform for Distributed Transaction Processing
0010  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0011  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0012  * This software is released under one of the following licenses:
0013  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0014  * See LICENSE file for full text.
0015  * -----------------------------------------------------------------------------
0016  * AGPL license:
0017  *
0018  * This program is free software; you can redistribute it and/or modify it under
0019  * the terms of the GNU Affero General Public License, version 3 as published
0020  * by the Free Software Foundation;
0021  *
0022  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0023  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0024  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0025  * for more details.
0026  *
0027  * You should have received a copy of the GNU Affero General Public License along 
0028  * with this program; if not, write to the Free Software Foundation, Inc.,
0029  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0030  *
0031  * -----------------------------------------------------------------------------
0032  * A commercial use license is available from Mavimax, Ltd
0033  * contact@mavimax.com
0034  * -----------------------------------------------------------------------------
0035  */
0036 #include <string.h>
0037 #include <stdio.h>
0038 #include <stdlib.h>
0039 #include <memory.h>
0040 #include <errno.h>
0041 
0042 /* Mqueue: */
0043 #include <fcntl.h>           /* For O_* constants */
0044 #include <sys_mqueue.h>
0045 #include <sys/stat.h>
0046 #include <sys/time.h>
0047 
0048 #include <ndrstandard.h>
0049 #include <ndebug.h>
0050 #include <ndrxd.h>
0051 #include <ndrxdcmn.h>
0052 
0053 #include <cmd_processor.h>
0054 #include <signal.h>
0055 #include <userlog.h>
0056 
0057 /*---------------------------Externs------------------------------------*/
0058 /*---------------------------Macros-------------------------------------*/
0059 #define QUEUE_WAIT              1           /* Wait one second on queue, move to param? */
0060 /*---------------------------Enums--------------------------------------*/
0061 /*---------------------------Typedefs-----------------------------------*/
0062 /*---------------------------Globals------------------------------------*/
0063 command_state_t G_command_state;
0064 command_call_t * G_last_interactive_call=NULL;  /* The last call make by user (in progress) */
0065 /*---------------------------Statics------------------------------------*/
0066 /*---------------------------Prototypes---------------------------------*/
0067 
0068 exprivate int cmd_dummy (command_call_t * call, char *data, size_t len, int context);
0069 typedef struct
0070 {
0071     int command;        /* Command id */
0072     /* Function to call: */
0073     int (*p_cmd_call) (command_call_t * call, char *data, size_t len, int context);
0074     char  *descr;
0075     char  *contexts;
0076     int interactive; /* Interactive shall be those which run command processor inside. */
0077     int entercontext;
0078 } command_map_t;
0079 
0080 command_map_t M_command_map [] =
0081 {   /* Command */
0082     {NDRXD_COM_LDCF_RQ,      cmd_config_load,"ldcf",        ",0,", 0, NDRXD_CTX_NOCHG},
0083     {NDRXD_COM_LDCF_RP,      cmd_dummy,      "ldcf",        "",  0, NDRXD_CTX_NOCHG}, /* not used */
0084     {NDRXD_COM_START_RQ,     cmd_start,      "start",       ",0,", 1, NDRXD_CTX_START},
0085     {NDRXD_COM_START_RP,     cmd_dummy,      "start",       "",  1, NDRXD_CTX_ZERO},  /* not used */
0086     /* We can get svcinfo any time... */
0087     {NDRXD_COM_SVCINFO_RQ,   cmd_srvinfo,    "srvinfo",     ",-1,",0,NDRXD_CTX_NOCHG},
0088     {NDRXD_COM_SVCINFO_RP,   cmd_dummy,      "srvinfo",     "",  0,NDRXD_CTX_NOCHG}, /* not used */
0089     /* Notification */
0090     {NDRXD_COM_PMNTIFY_RQ,   cmd_notify,     "notify",      ",-1,", 0,NDRXD_CTX_NOCHG},
0091     {NDRXD_COM_PMNTIFY_RP,   cmd_dummy,      "notify",      "",   0,NDRXD_CTX_NOCHG}, /* not used */
0092     /* psc command */
0093     {NDRXD_COM_PSC_RQ,       cmd_psc,        "psc",         ",-1,", 0,NDRXD_CTX_NOCHG},
0094     {NDRXD_COM_PSC_RP,       cmd_dummy,      "psc",         "",  0,NDRXD_CTX_NOCHG},  /* not used */
0095     /* stop command */
0096     {NDRXD_COM_STOP_RQ,      cmd_stop,       "stop",        ",0,",1,NDRXD_CTX_STOP},
0097     {NDRXD_COM_STOP_RP,      cmd_dummy,      "stop",        "", 1,NDRXD_CTX_ZERO},  /* not used */
0098     /* These two are requests to servers, not received by ndrxd in requests! */
0099     {NDRXD_COM_SRVSTOP_RQ,   cmd_dummy,      "srvstop",     "", 0,NDRXD_CTX_NOCHG},  /* not used */
0100     {NDRXD_COM_SRVSTOP_RP,   cmd_dummy,      "srvstop",     "", 0,NDRXD_CTX_NOCHG},  /* not used */
0101     /* attach command, this is not interactive (so to not mix up) */
0102     {NDRXD_COM_AT_RQ,        cmd_at,         "at",          ",-1,",0,NDRXD_CTX_NOCHG},
0103     {NDRXD_COM_AT_RP,        cmd_at,         "at",          "", 0,NDRXD_CTX_NOCHG},  /* not used */
0104     {NDRXD_COM_RELOAD_RQ,    cmd_reload,     "reload",      ",0,",0,NDRXD_CTX_NOCHG},
0105     {NDRXD_COM_RELOAD_RP,    cmd_reload,     "reload",      "", 0,NDRXD_CTX_NOCHG},  /* not used */
0106     {NDRXD_COM_TESTCFG_RQ,   cmd_testcfg,    "testcfg",     ",0,",0,NDRXD_CTX_NOCHG},
0107     {NDRXD_COM_TESTCFG_RP,   cmd_testcfg,    "testcfg",     "", 0,NDRXD_CTX_NOCHG},  /* not used */
0108     {NDRXD_COM_SRVINFO_RQ,   cmd_dummy,      "srvinfo",     ",0,",0,NDRXD_CTX_NOCHG},
0109     {NDRXD_COM_SRVINFO_RP,   cmd_dummy,      "srvinfo",     "", 0,NDRXD_CTX_NOCHG},  /* not used */
0110     {NDRXD_COM_SRVUNADV_RQ,  cmd_srvunadv,   "srvunadv",    ",-1,", 0,NDRXD_CTX_NOCHG},
0111     {NDRXD_COM_SRVUNADV_RP,  cmd_dummy,      "srvunadv",    "", 0,NDRXD_CTX_NOCHG},
0112     {NDRXD_COM_XADUNADV_RQ,  cmd_xadunadv,   "xadunadv",    ",0,", 0,NDRXD_CTX_NOCHG},
0113     {NDRXD_COM_XADUNADV_RP,  cmd_dummy,      "xadunadv",    "", 0,NDRXD_CTX_NOCHG},
0114     {NDRXD_COM_NXDUNADV_RQ,  cmd_dummy,      "nxdunadv",    ",-1,", 0,NDRXD_CTX_NOCHG},
0115     {NDRXD_COM_NXDUNADV_RP,  cmd_dummy,      "nxdunadv",    "", 0,NDRXD_CTX_NOCHG},
0116     {NDRXD_COM_SRVADV_RQ,    cmd_srvadv,     "srvadv",      ",-1,", 0,NDRXD_CTX_NOCHG},
0117     {NDRXD_COM_SRVADV_RP,    cmd_dummy,      "srvadv",      "", 0,NDRXD_CTX_NOCHG},
0118     {NDRXD_COM_XAPPM_RQ,     cmd_ppm,        "xappm",       ",-1,", 0,NDRXD_CTX_NOCHG},
0119     {NDRXD_COM_XAPPM_RP,     cmd_dummy,      "xappm",       "", 0,NDRXD_CTX_NOCHG},
0120     {NDRXD_COM_XASHM_PSVC_RQ,cmd_shm_psvc,   "xashm_psvc",  ",-1,", 0,NDRXD_CTX_NOCHG},
0121     {NDRXD_COM_XASHM_PSVC_RP,cmd_dummy,      "xashm_psvc",  "", 0,NDRXD_CTX_NOCHG},
0122     {NDRXD_COM_XASHM_PSRV_RQ,cmd_shm_psrv,   "xashm_psrv",  ",-1,", 0,NDRXD_CTX_NOCHG},
0123     {NDRXD_COM_XASHM_PSRV_RP,cmd_dummy,      "xashm_psrv",  "", 0,NDRXD_CTX_NOCHG},
0124     {NDRXD_COM_NXDREADV_RQ,  cmd_dummy,      "nxdreadv",    ",-1,", 0,NDRXD_CTX_NOCHG},
0125     {NDRXD_COM_NXDREADV_RP,  cmd_dummy,      "nxdreadv",    "", 0,NDRXD_CTX_NOCHG},
0126     {NDRXD_COM_XADREADV_RQ,  cmd_xadreadv,   "xadreadv",    ",0,", 0,NDRXD_CTX_NOCHG},
0127     {NDRXD_COM_XADREADV_RP,  cmd_dummy,      "xadreadv",    "", 0,NDRXD_CTX_NOCHG},
0128     {NDRXD_COM_XACABORT_RQ,  cmd_abort,       "xaabort",    ",1,2,", 0,NDRXD_CTX_NOCHG},
0129     {NDRXD_COM_XAABORT_RP,  cmd_dummy,       "xaabort",    "", 0,NDRXD_CTX_NOCHG},
0130     /* Bridge internal commands: */
0131     {NDRXD_COM_BRCON_RQ,    cmd_brcon,       "brcon",      ",-1,", 0,NDRXD_CTX_NOCHG},
0132     {NDRXD_COM_BRCON_RP,    cmd_dummy,       "brcon",      "", 0,NDRXD_CTX_NOCHG},
0133     {NDRXD_COM_BRDISCON_RQ, cmd_brdiscon,    "brdiscon",   ",-1,", 0,NDRXD_CTX_NOCHG},
0134     {NDRXD_COM_BRDISCON_RP, cmd_dummy,       "brdiscon",   "", 0,NDRXD_CTX_NOCHG},
0135     {NDRXD_COM_BRREFERSH_RQ,cmd_brrefresh,   "brrefresh",  ",-1,", 0,NDRXD_CTX_NOCHG},
0136     {NDRXD_COM_BRREFERSH_RP,cmd_dummy,       "brrefresh",  "", 0,NDRXD_CTX_NOCHG},
0137     {NDRXD_COM_BRCLOCK_RQ, cmd_dummy,        "brclock",   "", 0,NDRXD_CTX_NOCHG},
0138     {NDRXD_COM_BRCLOCK_RP, cmd_dummy,        "brclock",   "", 0,NDRXD_CTX_NOCHG},
0139     {NDRXD_COM_SRVGETBRS_RQ,cmd_getbrs,      "getbrs",  ",-1,", 0,NDRXD_CTX_NOCHG},
0140     {NDRXD_COM_SRVGETBRS_RP,cmd_dummy,       "getbrs",     "", 0,NDRXD_CTX_NOCHG},
0141     {NDRXD_COM_SRVPING_RQ,cmd_dummy,         "srvping",  ",-1,", 0,NDRXD_CTX_NOCHG},
0142     {NDRXD_COM_SRVPING_RP,cmd_srvpingrsp,    "srvping",  ",-1,", 0,NDRXD_CTX_NOCHG},
0143     /* sreload function... */
0144     {NDRXD_COM_SRELOAD_RQ,cmd_sreload,         "sreload",  ",0,", 0,NDRXD_CTX_START},
0145     {NDRXD_COM_SRELOAD_RP,cmd_dummy,           "sreload",  ",0,", 0,NDRXD_CTX_START},
0146     /* Print Queue */
0147     {NDRXD_COM_XAPQ_RQ,   cmd_pq,              "xapq",     ",-1,", 0,NDRXD_CTX_NOCHG},
0148     {NDRXD_COM_XAPQ_RP,   cmd_dummy,           "xapq",     "", 0,NDRXD_CTX_NOCHG},
0149     /* Print Environment */
0150     {NDRXD_COM_PE_RQ,     cmd_pe,              "xape",     ",-1,", 0,NDRXD_CTX_NOCHG},
0151     {NDRXD_COM_PE_RP,     cmd_dummy,           "xape",     "", 0,NDRXD_CTX_NOCHG},
0152     /* Set Environment */
0153     {NDRXD_COM_SET_RQ,     cmd_set,            "xaset",     ",-1,", 0,NDRXD_CTX_NOCHG},
0154     {NDRXD_COM_SET_RP,     cmd_dummy,          "xaset",     "", 0,NDRXD_CTX_NOCHG},
0155     {NDRXD_COM_UNSET_RQ,   cmd_unset,          "xaunset",   ",-1,", 0,NDRXD_CTX_NOCHG},
0156     {NDRXD_COM_UNSET_RP,   cmd_dummy,          "xaunset",   "", 0,NDRXD_CTX_NOCHG},
0157     {NDRXD_COM_SRELOADI_RQ,cmd_sreloadi,       "sreloadi",  ",0,", 0,NDRXD_CTX_START},
0158     {NDRXD_COM_SRELOADI_RP,cmd_dummy,          "sreloadi",  ",0,", 0,NDRXD_CTX_START},
0159     {NDRXD_COM_APPCONFIG_RQ,cmd_appconfig,     "appconfig",  ",-1,", 0,NDRXD_CTX_NOCHG},
0160     {NDRXD_COM_APPCONFIG_RP,cmd_dummy,         "appconfig",  ",-1,", 0,NDRXD_CTX_NOCHG},
0161     {NDRXD_COM_DPING_RQ,    cmd_dping,         "dping",  ",-1,", 0,NDRXD_CTX_NOCHG},
0162     {NDRXD_COM_DPING_RP,    cmd_dummy,         "dping",  ",-1,", 0,NDRXD_CTX_NOCHG},
0163     {NDRXD_COM_DSLEEP_RQ,   cmd_dsleep,        "dsleep",  ",-1,", 0,NDRXD_CTX_NOCHG},
0164     {NDRXD_COM_DSLEEP_RP,   cmd_dummy,         "dsleep",  ",-1,", 0,NDRXD_CTX_NOCHG},
0165     {NDRXD_COM_BLIST_RQ,    cmd_blist,         "blist",   ",-1,", 0,NDRXD_CTX_NOCHG},
0166     {NDRXD_COM_BLIST_RP,    cmd_dummy,         "blist",   "",  0,NDRXD_CTX_NOCHG}
0167     
0168 };
0169 
0170 /**
0171  * Dummy function for mapping command replies
0172  * @param call
0173  * @param data
0174  * @param len
0175  * @return 
0176  */
0177 exprivate int cmd_dummy(command_call_t * call, char *data, size_t len, int context)
0178 {
0179     NDRX_LOG(log_debug, "Un-expected command call!");
0180     return EXSUCCEED;
0181 }
0182 
0183 /**
0184  * Open listening queue
0185  * @return
0186  */
0187 exprivate int cmd_open_queue(void)
0188 {
0189     int ret=EXSUCCEED;
0190 
0191     /* Unlink previous admin queue (if have such) - ignore any error */
0192     ndrx_mq_unlink(G_command_state.listenq_str);
0193     NDRX_LOG(log_debug, "About to open deamon queue: [%s]",
0194                                         G_command_state.listenq_str);
0195     /* Open new queue (non blocked, so  that we do not get deadlock on batch deaths! */
0196     if ((mqd_t)EXFAIL==(G_command_state.listenq = ndrx_mq_open_at(
0197                                 G_command_state.listenq_str, O_RDWR | O_CREAT,
0198                                 S_IWUSR | S_IRUSR, NULL)))
0199     {
0200         NDRX_LOG(log_error, "Failed to open queue: [%s] err: %s",
0201                                         G_command_state.listenq_str, strerror(errno));
0202         userlog("Failed to open queue: [%s] err: %s",
0203                                         G_command_state.listenq_str, strerror(errno));
0204         ret=EXFAIL;
0205         goto out;
0206     }
0207 
0208     NDRX_LOG(log_error, "Queue [%s] opened!", G_command_state.listenq_str);
0209     
0210 out:
0211     return ret;
0212 }
0213 
0214 /**
0215  * Open listening queue
0216  * @return
0217  */
0218 expublic int cmd_close_queue(void)
0219 {
0220     int ret=EXSUCCEED;
0221 
0222     if (EXSUCCEED!=ndrx_mq_close(G_command_state.listenq))
0223     {
0224         NDRX_LOG(log_error, "Failed to close: [%s] err: %s",
0225                                      G_command_state.listenq_str, strerror(errno));
0226     }
0227 
0228     /* Unlink previous admin queue (if have such) - ignore any error */
0229     if (EXSUCCEED!=ndrx_mq_unlink(G_command_state.listenq_str))
0230     {
0231             NDRX_LOG(log_error, "Failed to unlink: [%s] err: %s",
0232                                      G_command_state.listenq_str, strerror(errno));
0233     }
0234     
0235 out:
0236     return ret;
0237 }
0238 /**
0239  * Initialize command processor
0240  * @return
0241  */
0242 expublic int cmd_processor_init(void)
0243 {
0244     int ret=EXSUCCEED;
0245 
0246     memset(&G_command_state, 0, sizeof(G_command_state));
0247     snprintf(G_command_state.listenq_str, sizeof(G_command_state.listenq_str), 
0248             NDRX_NDRXD, G_sys_config.qprefix);
0249 
0250     if (EXFAIL==cmd_open_queue())
0251     {
0252         ret=EXFAIL;
0253         goto out;
0254     }
0255 
0256 out:
0257     return ret;
0258 }
0259 
0260 /**
0261  * Get Q attribs.
0262  * @param attr
0263  * @return 
0264  */
0265 expublic int get_cmdq_attr(struct mq_attr *attr)
0266 {
0267     int ret=EXSUCCEED;
0268     
0269     if (EXFAIL==ndrx_mq_getattr(G_command_state.listenq, attr))
0270     {
0271         NDRX_LOG(log_error, "Failed to ex_mq_getattr on cmd q: %s", 
0272                 strerror(errno));
0273         ret=EXFAIL;
0274     }
0275     
0276     return ret;
0277 }
0278 
0279 /**
0280  * Return context string
0281  * @param ctx context number
0282  * @return static context string
0283  */
0284 exprivate char * get_ctx_string(int ctx)
0285 {
0286     /* must match NDRXD_CTX* constants, array index = ctx+1 */
0287     static char* ctx_str[] = {"any", "normal", "starting", "stopping"};
0288     
0289     return ctx_str[ctx+1];
0290 }
0291 
0292 /**
0293  * Calculate the next command wati time
0294  * Get the shortest sleep time from:
0295  * - G_sys_config.cmd_wait_time
0296  * or
0297  * - Time left wait to next sanity scan (as wait can be interrupted by ongoing commands)
0298  * use value which ever is shorter.
0299  * @param[out] abs_timeout absolute time to wait for command timeout.
0300  */
0301 exprivate void get_cmd_wait_time(struct timespec *abs_timeout)
0302 {
0303     long wait_time_ms = G_sys_config.cmd_wait_time*1000;
0304     long sanity_wait_time;
0305     long nsec_tmp;
0306     /* Set recieve time-out */
0307     struct timeval  timeval;
0308     ndrx_stopwatch_t *w;
0309 
0310     gettimeofday (&timeval, NULL);
0311     memset(abs_timeout, 0, sizeof(struct timespec));
0312     w=ndrx_get_santiy_stopwatch();
0313 
0314     if (NULL!=w)
0315     {
0316         sanity_wait_time = G_app_config->sanity*1000 - ndrx_stopwatch_get_delta(w);
0317 
0318         if (sanity_wait_time  < wait_time_ms)
0319         {
0320             wait_time_ms = sanity_wait_time;
0321         }
0322 
0323         if (wait_time_ms<0)
0324         {
0325             wait_time_ms=0;
0326         }
0327     }
0328 
0329     NDRX_LOG(log_dump, "planned cmd wait: %ld ms", wait_time_ms);
0330 
0331     /* apply to time spec */
0332     abs_timeout->tv_sec = timeval.tv_sec + (wait_time_ms / 1000) ;
0333     nsec_tmp = (wait_time_ms % 1000) * 1000000 + timeval.tv_usec*1000;
0334     abs_timeout->tv_sec+= (nsec_tmp/1000000000);
0335     abs_timeout->tv_nsec = nsec_tmp%1000000000;    
0336 }
0337 
0338 /**
0339  * Wait for commands and process the one by one...
0340  * @param finished
0341  * @return
0342  */
0343 expublic int command_wait_and_run(int *finished, int *abort)
0344 {
0345     int ret=EXSUCCEED;
0346     char    *msg_buffer_max=NULL;
0347     size_t buf_max;
0348     unsigned int prio = 0;
0349     struct timespec abs_timeout;
0350     command_call_t * call;
0351     size_t  data_len;
0352     int     error;
0353     command_map_t *cmd;
0354     int marked_interactive = EXFALSE;
0355     char context_check[16];
0356     int prev_context = NDRXD_CTX_NOCHG;
0357     
0358     NDRX_SYSBUF_MALLOC_OUT(msg_buffer_max, buf_max, ret);
0359     
0360     call = (command_call_t *)msg_buffer_max;
0361     memset(msg_buffer_max, 0, sizeof(command_call_t));
0362     snprintf(context_check, sizeof(context_check), ",%d,", G_command_state.context);
0363 
0364     /* check for child exit... 
0365     if (check_child_exit())
0366     {
0367         goto out;
0368     }
0369      * */
0370     
0371     if (G_sys_config.restarting)
0372     {
0373         /* Check for learning time after restart */
0374         do_restart_chk();
0375     }
0376     else
0377     {
0378         /* We will ignore return code, because sanity is not deadly requirement! */
0379         do_sanity_check(EXFALSE);
0380     }
0381     
0382     /* Wait for buffer 
0383     NDRX_LOG(log_warn, "Waiting for message..."); */
0384     /*siginterrupt(SIGCHLD, TRUE);  This region must be interruptible...
0385      This causes some messages to be lost! */
0386     
0387     /* Change to blocked, if not already! */
0388     ndrx_q_setblock(G_command_state.listenq, EXTRUE);
0389 
0390     /* Also, as santiy scan resets it's timer after the check,
0391      * this prevents us from looping for ever on checks on slow systems.
0392      */
0393     get_cmd_wait_time(&abs_timeout);
0394     
0395     /* For OSX we need a special case here, we try to access to 
0396      * the queue for serveral minutes. If we get trylock rejected for
0397      * configured number of time, we shall close the queue and open it again
0398      * That would mean that somebody have got the queue lock and died for 
0399      * some reason (killed). In that secnario, robust mutexes might help
0400      * but OSX do no have such....
0401      */ 
0402     if (EXFAIL==(data_len = ndrx_mq_timedreceive (G_command_state.listenq,
0403                     msg_buffer_max, buf_max, &prio, &abs_timeout)))
0404     {
0405         error = errno;
0406     }
0407     else
0408     {
0409         NDRX_LOG(log_info, ">>>>>>>>>>>>>>>>>>got message, len : %ld",
0410                         data_len);
0411 
0412         /* reset error code */
0413         NDRXD_unset_error();
0414     }
0415     /*siginterrupt(SIGCHLD, FALSE);*/
0416 
0417     if (EXFAIL==data_len && EINTR==error)
0418     {
0419         NDRX_LOG(log_warn, "ex_mq_timedreceive got interrupted!");
0420         ret=EXSUCCEED;
0421         goto out;
0422     }
0423     else if (EXFAIL==data_len && ETIMEDOUT==error)
0424     {
0425         /* nothing recieved - OK */
0426         ret=EXSUCCEED;
0427         goto out;
0428     }
0429     else if (EXFAIL==data_len)
0430     {
0431         NDRX_LOG(log_error, "Error occurred when listening on :%s - %d/%s,"
0432                                 "issuing re-init",
0433                                 G_command_state.listenq_str, error, strerror(error));
0434         
0435         /* wait some time, so that we do not overfill logs in the system */
0436         
0437         sleep(5);
0438 
0439 /*
0440         ndrx_mq_close(G_command_state.listenq);
0441 */
0442         cmd_close_queue();
0443 
0444         if (EXFAIL==cmd_open_queue())
0445         {
0446             ret=EXFAIL;
0447         }
0448         else
0449         {
0450             NDRX_LOG(log_error, "Re-init OK");
0451             ret=EXSUCCEED;
0452         }
0453 
0454         goto out; /* finish with this loop */
0455     }
0456 
0457     /* Check the buffer type... */
0458     if (NDRX_MAGIC!=call->magic)
0459     {
0460         NDRX_LOG(log_error, "Invalid request received, bad magic: got %ld expected %ld",
0461                 call->magic, NDRX_MAGIC);
0462         /* Dump content... */
0463         NDRX_DUMP(log_error, "Invalid request received", msg_buffer_max, data_len);
0464         goto out;
0465     }
0466 #if 0
0467 
0468     /* We can get responses from servers! */
0469 
0470     /* Check is it request or response, we want requests only - even numbers! */
0471     if (0 != call->command % 2)
0472     {
0473         /* Dump content... */
0474         NDRX_DUMP(log_error, "Response recieved!", msg_buffer_max, data_len);
0475         goto out;
0476     }
0477 #endif
0478     NDRX_LOG(log_debug, "Command ID: %d", call->command);
0479     if (call->command < NDRXD_COM_MIN || call->command > NDRXD_COM_MAX)
0480     {
0481         NDRX_LOG(log_error, "Invalid command received: %d from [%s]!",
0482                                 call->command, call->reply_queue);
0483 
0484         /* Reply with error - non supported! */
0485         NDRXD_set_error_fmt(NDRXD_ECMDNOTFOUND, "Unknown command %d", call->command);
0486         if (EXSUCCEED!=simple_command_reply(call, EXFAIL, 0L, NULL, NULL, 0L, 0, NULL))
0487         {
0488             userlog("Failed to send reply back to [%s]", call->reply_queue);
0489         }
0490         goto out;
0491     }
0492     
0493     /* Execute command handler */
0494     cmd = &M_command_map[call->command];
0495 
0496     /* process command received */
0497     NDRX_LOG(log_debug, "Source: [%s] Command: %d Executing command: %s",
0498                 call->reply_queue, call->command, cmd->descr);
0499     
0500     /* Check the running context if not in context & not any. */
0501     if (NULL==strstr(cmd->contexts, context_check) && NULL==strstr(cmd->contexts, ",-1,"))
0502     {
0503         char tmp_modes[128]="";
0504         char tmp_out[128]="";
0505         char *p;
0506         char *savePtr;
0507         int is_normal_only = EXFALSE;
0508         
0509         /* loop over the contexts and build the string */
0510         NDRX_STRCPY_SAFE(tmp_modes, cmd->contexts);
0511         
0512         /* perform strrtok_r */
0513         p = strtok_r(tmp_modes, ",", &savePtr);
0514         while (p != NULL)
0515         {
0516             int ct = atoi(p);
0517             
0518             if (EXEOS==tmp_out[0])
0519             {
0520                 NDRX_STRCPY_SAFE(tmp_out, get_ctx_string(ct));
0521                 
0522                 if (NDRXD_CTX_ZERO==ct)
0523                 {
0524                     is_normal_only=EXTRUE;
0525                 }
0526             }
0527             else
0528             {
0529                 NDRX_STRCAT_S(tmp_out, sizeof(tmp_out), ", ");
0530                 NDRX_STRCAT_S(tmp_out, sizeof(tmp_out), get_ctx_string(ct));
0531                 
0532                 is_normal_only=EXFALSE;
0533             }
0534             
0535             p = strtok_r(NULL, ",", &savePtr);
0536         }
0537     
0538         if (is_normal_only)
0539         {
0540             NDRXD_set_error_fmt(NDRXD_ENORMAL, "Invalid ndrxd mode. Current is "
0541                 "'%s' but required '%s'", get_ctx_string(G_command_state.context), tmp_out);
0542         }
0543         else
0544         {
0545             NDRXD_set_error_fmt(NDRXD_ECONTEXT, "Invalid ndrxd mode. Current is "
0546                 "'%s' but required '%s'", get_ctx_string(G_command_state.context), tmp_out);
0547         }
0548 
0549         if (EXSUCCEED!=simple_command_reply(call, EXFAIL, 0L, NULL, NULL, 0L, 0, NULL))
0550         {
0551             userlog("Failed to send reply back to [%s]", call->reply_queue);
0552         }
0553         
0554         goto out;
0555     }
0556 
0557 
0558     /* save the interactive call */
0559     if (cmd->interactive && NULL==G_last_interactive_call)
0560     {
0561         G_last_interactive_call = call;
0562         marked_interactive=EXTRUE;
0563     }
0564     
0565     /* Enter context */
0566     if (NDRXD_CTX_NOCHG!=cmd->entercontext)
0567     {
0568         prev_context = G_command_state.context;
0569         NDRX_LOG(log_debug, "Entering context: %d", cmd->entercontext);
0570         G_command_state.context = cmd->entercontext;
0571     }
0572         
0573     /* Handle abort here.  */
0574     if (NDRXD_COM_XACABORT_RQ==cmd->command)
0575     {
0576         NDRX_LOG(log_warn, "Abort requested from xadmin!");
0577         *abort = EXTRUE;
0578     }
0579   
0580     ret = cmd->p_cmd_call(call, msg_buffer_max, data_len, G_command_state.context);
0581 
0582     /* Return from call, remove interactive ptr */
0583     if (marked_interactive)
0584     {
0585         G_last_interactive_call = NULL;
0586         marked_interactive=EXFALSE;
0587     }
0588     
0589 
0590 out:
0591     /* Restore original context */
0592     if (NDRXD_CTX_NOCHG!=prev_context)
0593     {
0594         G_command_state.context = prev_context;
0595         NDRX_LOG(log_debug, "Restoring context: %d", G_command_state.context);
0596     }
0597 
0598     if (NULL!=msg_buffer_max)
0599     {
0600         NDRX_SYSBUF_FREE(msg_buffer_max);
0601     }
0602 
0603     return ret;
0604 }
0605 
0606 /* ndrx will start ndrxd_guard, which will start ndrxd.
0607  * Meanwhile ndrx will try to open the queue for passing commands to.
0608  */
0609 
0610 
0611 /* vim: set ts=4 sw=4 et smartindent: */