Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Start & stop command backend.
0003  *
0004  * @file cmd_startstop.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 
0039 #include <ndrstandard.h>
0040 
0041 #include <ndebug.h>
0042 #include <userlog.h>
0043 #include <ndrxd.h>
0044 #include <ndrxdcmn.h>
0045 #include <atmi_shm.h>
0046 
0047 #include "cmd_processor.h"
0048 /*---------------------------Externs------------------------------------*/
0049 /*---------------------------Macros-------------------------------------*/
0050 /*---------------------------Enums--------------------------------------*/
0051 /*---------------------------Typedefs-----------------------------------*/
0052 /*---------------------------Globals------------------------------------*/
0053 /*---------------------------Statics------------------------------------*/
0054 /*---------------------------Prototypes---------------------------------*/
0055 
0056 /**
0057  * Modify reply according the data.
0058  * @param call
0059  * @param pm
0060  */
0061 expublic void reply_mod(command_reply_t *reply, size_t *send_size, mod_param_t *params)
0062 {
0063     command_reply_pm_t * pm_info = (command_reply_pm_t *)reply;
0064     pm_node_t *pm = (pm_node_t *)params->mod_param1;
0065 
0066     reply->msg_type = params->param2; /* set specific call type... */
0067     /* calculate new send size */
0068     *send_size += (sizeof(command_reply_pm_t) - sizeof(command_reply_t));
0069 
0070     NDRX_STRCPY_SAFE(pm_info->binary_name, pm->binary_name);
0071     NDRX_STRCPY_SAFE(pm_info->clopt, pm->clopt);
0072     pm_info->srvid = pm->srvid;
0073     pm_info->state = pm->state;
0074     pm_info->pid = pm->pid;
0075 
0076     NDRX_LOG(log_debug, "magic: %ld, pid: %d, state: %ld",
0077                             pm_info->rply.magic, pm_info->pid, pm_info->state);
0078 }
0079 
0080 /**
0081  * Callback to report startup progress
0082  * @param call
0083  * @param pm
0084  * @return
0085  */
0086 expublic void startup_progress(command_startstop_t * call, pm_node_t *pm, int calltype)
0087 {
0088     int ret=EXSUCCEED;
0089     mod_param_t params;
0090 
0091     NDRX_LOG(log_debug, "startup_progress enter, pid: %d", pm->pid);
0092     memset(&params, 0, sizeof(mod_param_t));
0093 
0094     /* pass to reply process model node */
0095     params.mod_param1 = (void *)pm;
0096     params.param2 = calltype;
0097 
0098     if (EXSUCCEED!=simple_command_reply((command_call_t *)call, ret, NDRXD_CALL_FLAGS_RSPHAVE_MORE,
0099                             /* hook up the reply */
0100                             &params, reply_mod, 0L, 0, NULL))
0101     {
0102         userlog("Failed to send progress back to [%s]", call->call.reply_queue);
0103     }
0104     
0105     NDRX_LOG(log_debug, "startup_progress exit");
0106 }
0107 
0108 /**
0109  * If we failt start the domain, then we have major failure and we should exit.
0110  * @param args
0111  * @return
0112  */
0113 expublic int cmd_start (command_call_t * call, char *data, size_t len, int context)
0114 {
0115     int ret=EXSUCCEED;
0116     command_startstop_t *start = (command_startstop_t *)call;
0117     long processes_started=0;
0118     
0119     ret = app_startup(start, startup_progress, &processes_started);
0120 
0121     if (EXSUCCEED!=simple_command_reply(call, ret, 0L, NULL, NULL, 
0122             processes_started, 0, NULL))
0123     {
0124         userlog("Failed to send reply back to [%s]", call->reply_queue);
0125     }
0126     
0127     NDRX_LOG(log_warn, "cmd_start returns with status %d", ret);
0128     
0129 out:
0130     
0131     /* Do not want exit ndrxd if failed...! */
0132     return EXSUCCEED;
0133 }
0134 
0135 /**
0136  * Notification about process...
0137  * @param args
0138  * @return
0139  */
0140 expublic int cmd_notify (command_call_t * call, char *data, size_t len, int context)
0141 {
0142     int ret=EXSUCCEED;
0143     srv_status_t * pm_status = (srv_status_t *)call;
0144     pm_pidhash_t *pm_pid;
0145     pm_node_t *p_pm=NULL;
0146     shm_srvinfo_t* srv;
0147     NDRX_LOG(log_warn, "Got notification for pid:%d srvid:%d",
0148                 pm_status->srvinfo.pid, pm_status->srvinfo.srvid);
0149 
0150     /* Now check the pidhash... */
0151     pm_pid = pid_hash_get(G_process_model_pid_hash, pm_status->srvinfo.pid);
0152 
0153     if (NULL!=pm_pid)
0154     {
0155         int org_state = pm_pid->p_pm->state;
0156         int srvid = pm_pid->p_pm->srvid;
0157         
0158         /* Bug #214 */
0159         if (NDRXD_PM_EXIT!=pm_status->srvinfo.state)
0160         {
0161             userlog("Server process [%s], srvid %d, pid %d died", 
0162                 pm_pid->p_pm->conf->binary_name, pm_pid->p_pm->srvid, pm_pid->pid);
0163         }
0164                 
0165         /* If we wanted it to stop, but it died, then let it be in exit status
0166          * which will not try to restart it!
0167          */
0168         if (pm_pid->p_pm->state!=NDRXD_PM_STOPPING)
0169         {
0170             /* try to use status from shared memory if available */
0171             srv=ndrxd_shm_getsrv(pm_pid->p_pm->srvid);
0172             
0173             if (srv->execerr!=0)
0174             {
0175                 pm_pid->p_pm->state = srv->execerr;
0176             }
0177             else
0178             {
0179                 pm_pid->p_pm->state = pm_status->srvinfo.state;
0180             }
0181         }
0182         else
0183         {
0184             /* so that we do no try again to wake it up! */
0185             pm_pid->p_pm->state=NDRXD_PM_EXIT;
0186         }
0187 
0188         /* reset state change counter */
0189         if (pm_pid->p_pm->state!=org_state)
0190         {
0191             pm_pid->p_pm->state_changed = SANITY_CNT_START;
0192         }
0193 
0194         /* reset PM fields */
0195         pm_pid->p_pm->procgrp_lp_no=0;
0196         
0197         NDRX_LOG(log_warn, "Removing resources allocated "
0198                             "for process [%s]", pm_pid->p_pm->binary_name);
0199         
0200         /* Find .the pm_p & remove failed process! */
0201 
0202         /* TODO: If the PID if different one than for srvid, then we remove 
0203          * this thing from
0204          * pidhash only!!!! - Yeah right this must be fixed.
0205          * we had an incident in i2nc, when PID 9862 died, other was started, 
0206          * but we remove that other, not 9862, which died actually!!!
0207          */
0208         remove_startfail_process(get_pm_from_srvid(srvid), NULL, pm_pid);
0209 
0210         /* reset shared memory! */
0211         ndrxd_shm_resetsrv(srvid);
0212         
0213     }
0214     else
0215     {
0216         NDRX_LOG(log_warn, "PID %d unknown to system!",
0217                                 pm_status->srvinfo.pid);
0218     }
0219     
0220     NDRX_LOG(log_warn, "cmd_notify returns with status %d", ret);
0221 
0222 out:
0223     return ret;
0224 }
0225 
0226 /**
0227  * Callback to report startup progress
0228  * @param call
0229  * @param pm
0230  * @return
0231  */
0232 expublic void shutdown_progress(command_call_t * call, pm_node_t *pm, int calltype)
0233 {
0234     int ret=EXSUCCEED;
0235     mod_param_t params;
0236 
0237     NDRX_LOG(log_debug, "shutdown_progress enter");
0238     memset(&params, 0, sizeof(mod_param_t));
0239 
0240     /* pass to reply process model node */
0241     params.mod_param1 = (void *)pm;
0242     params.param2 = calltype;
0243 
0244     if (EXSUCCEED!=simple_command_reply(call, ret, NDRXD_CALL_FLAGS_RSPHAVE_MORE,
0245                             /* hook up the reply */
0246                             &params, reply_mod, 0L, 0, NULL))
0247     {
0248         userlog("Failed to send progress back to [%s]", call->reply_queue);
0249     }
0250 
0251     NDRX_LOG(log_debug, "shutdown_progress exit");
0252 }
0253 
0254 /**
0255  * If we failt start the domain, then we have major failure and we should exit.
0256  * @param args
0257  * @return
0258  */
0259 expublic int cmd_stop (command_call_t * call, char *data, size_t len, int context)
0260 {
0261     int ret=EXSUCCEED;
0262     command_startstop_t *stop = (command_startstop_t *)call;
0263     long processes_shutdown=0;
0264     
0265     ret = app_shutdown(stop, shutdown_progress, &processes_shutdown);
0266 
0267     if (stop->complete_shutdown)
0268     {
0269         NDRX_LOG(log_warn, "Unlinking pid-file before shutdown down reply...");
0270         ndrxd_unlink_pid_file(EXFALSE);
0271     }
0272     
0273     if (EXSUCCEED!=simple_command_reply(call, ret, 0L, NULL, NULL, 
0274             processes_shutdown, 0, NULL))
0275     {
0276         userlog("Failed to send reply back to [%s]", call->reply_queue);
0277     }
0278 
0279     NDRX_LOG(log_warn, "cmd_start returns with status %d", ret);
0280 
0281     /* We should request app domain shutdown (if it was full shutdown?)
0282      * ndrxd main will hang running while there still will be processes, but
0283      * shutdown was requested....
0284      */
0285     if (stop->complete_shutdown)
0286     {
0287         NDRX_LOG(log_warn, "Putting system in shutdown state...");
0288         G_sys_config.stat_flags |= NDRXD_STATE_SHUTDOWN;
0289     }
0290     
0291 out:
0292     /* Do not want exit if failed..! */
0293     return EXSUCCEED;
0294 }
0295 
0296 /**
0297  * Simple reply on abort.
0298  * @param call
0299  * @param data
0300  * @param len
0301  * @param context
0302  * @return 
0303  */
0304 expublic int cmd_abort (command_call_t * call, char *data, size_t len, int context)
0305 {
0306     int ret=EXSUCCEED;
0307 
0308     if (EXSUCCEED!=simple_command_reply(call, ret, 0L, NULL, NULL, 0L, 0, NULL))
0309     {
0310         userlog("Failed to send reply back to [%s]", call->reply_queue);
0311     }
0312 
0313     /* Do not want exit if failed..! */
0314     return EXSUCCEED; /* Do not want to break the system! */
0315 }
0316 
0317 /**
0318  * Reload services...
0319  * @param args
0320  * @return
0321  */
0322 expublic int cmd_sreload (command_call_t * call, char *data, size_t len, int context)
0323 {
0324     int ret=EXSUCCEED;
0325     command_startstop_t *start = (command_startstop_t *)call;
0326     long processes_started=0;
0327     
0328     ret = app_sreload(start, startup_progress, shutdown_progress, &processes_started);
0329 
0330     if (EXSUCCEED!=simple_command_reply(call, ret, 0L, NULL, NULL, 
0331             processes_started, 0, NULL))
0332     {
0333         userlog("Failed to send reply back to [%s]", call->reply_queue);
0334     }
0335     
0336     NDRX_LOG(log_warn, "cmd_start returns with status %d", ret);
0337     
0338 out:
0339     
0340     /* Do not want exit ndrxd if failed...! */
0341     return EXSUCCEED;
0342 }
0343 
0344 /**
0345  * Reload services...  (internal version
0346  * @param args
0347  * @return
0348  */
0349 expublic int cmd_sreloadi (command_call_t * call, char *data, size_t len, int context)
0350 {
0351     int ret=EXSUCCEED;
0352     command_startstop_t *start = (command_startstop_t *)call;
0353     long processes_started=0;
0354     
0355     ret = app_sreload(start, NULL, NULL, &processes_started);
0356     
0357     NDRX_LOG(log_warn, "cmd_start returns with status %d", ret);
0358     
0359 out:
0360     
0361     /* Do not want exit ndrxd if failed...! */
0362     return EXSUCCEED;
0363 }
0364 
0365 /* vim: set ts=4 sw=4 et smartindent: */