/* * This is a post- fix recursive function for starting every service * that s depends on before starting s. * @param s A Service_T object */ static void do_start(Service_T s) { ASSERT(s); if (s->visited) return; s->visited = TRUE; if (s->dependantlist) { Dependant_T d; for (d = s->dependantlist; d; d = d->next ) { Service_T parent = Util_getService(d->dependant); ASSERT(parent); do_start(parent); } } if (s->start && (s->type!=TYPE_PROCESS || !Util_isProcessRunning(s))) { LogInfo("'%s' start: %s\n", s->name, s->start->arg[0]); spawn(s, s->start, NULL); /* We only wait for a process type, other service types does not have a pid file to watch */ if (s->type == TYPE_PROCESS) wait_start(s); } Util_monitorSet(s); }
/* * This function simply restarts the service s. * @param s A Service_T object */ static void do_restart(Service_T s) { if (s->restart) { LogInfo("'%s' restart: %s\n", s->name, s->restart->arg[0]); spawn(s, s->restart, NULL); /* We only wait for a process type, other service types does not have a pid file to watch */ if (s->type == TYPE_PROCESS) wait_process(s, Process_Started); } else { LogDebug("'%s' restart skipped -- method not defined\n", s->name); } Util_monitorSet(s); }
/* * This is a post- fix recursive function for enabling monitoring every service * that s depends on before monitor s. * @param s A Service_T object * @param flag A Custom flag */ static void do_monitor(Service_T s, int flag) { ASSERT(s); if (s->visited) return; s->visited = TRUE; if (s->dependantlist) { Dependant_T d; for (d = s->dependantlist; d; d = d->next ) { Service_T parent = Util_getService(d->dependant); ASSERT(parent); do_monitor(parent, flag); } } Util_monitorSet(s); }
/** * Check to see if we should try to start/stop service * @param S A service name as stated in the config file * @param A An action id describing the action to execute * @return FALSE for error, otherwise TRUE */ int control_service(const char *S, int A) { Service_T s = NULL; ASSERT(S); if (! (s = Util_getService(S))) { LogError("%s: service '%s' -- doesn't exist\n", prog, S); return FALSE; } switch(A) { case ACTION_START: if (s->type == TYPE_PROCESS) { if (Util_isProcessRunning(s)) { DEBUG("%s: Process already running -- process %s\n", prog, S); Util_monitorSet(s); return TRUE; } if (!s->start) { LogError("%s: Start method not defined -- process %s\n", prog, S); Util_monitorSet(s); return FALSE; } } do_depend(s, ACTION_STOP); do_start(s); do_depend(s, ACTION_START); break; case ACTION_STOP: if (s->type == TYPE_PROCESS && !s->stop) { LogError("%s: Stop method not defined -- process %s\n", prog, S); Util_monitorUnset(s); return FALSE; } /* soft unmonitor and stop: */ do_depend(s, ACTION_STOP); do_stop(s); /* hard unmonitor - will reset all counters and flags: */ do_depend(s, ACTION_UNMONITOR); do_unmonitor(s); break; case ACTION_RESTART: if (s->type == TYPE_PROCESS && (!s->start || !s->stop)) { LogError("%s: Start or stop method not defined -- process %s\n", prog, S); Util_monitorSet(s); return FALSE; } LogInfo("'%s' trying to restart\n", s->name); do_depend(s, ACTION_STOP); if (do_stop(s)) { /* Only start if stop succeeded */ do_start(s); do_depend(s, ACTION_START); } else { /* enable monitoring of this service again to allow the restart retry * in the next cycle up to timeout limit */ Util_monitorSet(s); } break; case ACTION_MONITOR: /* We only enable monitoring of this service and all prerequisite * services. Chain of services which depends on this service keep * its state */ do_monitor(s); break; case ACTION_UNMONITOR: /* We disable monitoring of this service and all services which * depends on it */ do_depend(s, ACTION_UNMONITOR); do_unmonitor(s); break; default: LogError("%s: service '%s' -- invalid action %s\n", prog, S, A); return FALSE; } return TRUE; }