return true;
}
- ServiceRecord * record = nullptr;
+ service_record * record = nullptr;
string serviceName = rbuf.extract_string(3, svcSize);
handle_t handle;
rbuf.extract((char *) &handle, 2, sizeof(handle));
- ServiceRecord *service = findServiceForKey(handle);
+ service_record *service = findServiceForKey(handle);
if (service == nullptr) {
// Service handle is bad
char badreqRep[] = { DINIT_RP_BADREQ };
handle_t handle;
rbuf.extract((char *) &handle, 1, sizeof(handle));
- ServiceRecord *service = findServiceForKey(handle);
+ service_record *service = findServiceForKey(handle);
if (service == nullptr) {
// Service handle is bad
char badreqRep[] = { DINIT_RP_BADREQ };
}
}
-ControlConn::handle_t ControlConn::allocateServiceHandle(ServiceRecord *record)
+ControlConn::handle_t ControlConn::allocateServiceHandle(service_record *record)
{
bool is_unique = true;
handle_t largest_seen = 0;
// N bytes: packet data (N = (length - 2))
class ServiceSet;
-class ServiceRecord;
+class service_record;
class ControlConnWatcher : public EventLoop_t::bidi_fd_watcher_impl<ControlConnWatcher>
{
// A mapping between service records and their associated numerical identifier used
// in communction
using handle_t = uint32_t;
- std::unordered_multimap<ServiceRecord *, handle_t> serviceKeyMap;
- std::unordered_map<handle_t, ServiceRecord *> keyServiceMap;
+ std::unordered_multimap<service_record *, handle_t> serviceKeyMap;
+ std::unordered_map<handle_t, service_record *> keyServiceMap;
// Buffer for outgoing packets. Each outgoing back is represented as a vector<char>.
list<vector<char>> outbuf;
bool sendData() noexcept;
// Allocate a new handle for a service; may throw std::bad_alloc
- handle_t allocateServiceHandle(ServiceRecord *record);
+ handle_t allocateServiceHandle(service_record *record);
- ServiceRecord *findServiceForKey(uint32_t key)
+ service_record *findServiceForKey(uint32_t key)
{
try {
return keyServiceMap.at(key);
// Process service event broadcast.
// Note that this can potentially be called during packet processing (upon issuing
// service start/stop orders etc).
- void serviceEvent(ServiceRecord * service, ServiceEvent event) noexcept final override
+ void serviceEvent(service_record * service, ServiceEvent event) noexcept final override
{
// For each service handle corresponding to the event, send an information packet.
auto range = serviceKeyMap.equal_range(service);
// Might throw a ServiceLoadExc exception if a dependency cycle is found or if another
// problem occurs (I/O error, service description not found etc). Throws std::bad_alloc
// if a memory allocation failure occurs.
-ServiceRecord * ServiceSet::loadServiceRecord(const char * name)
+service_record * ServiceSet::loadServiceRecord(const char * name)
{
using std::string;
using std::ifstream;
using std::pair;
// First try and find an existing record...
- ServiceRecord * rval = find_service(string(name));
+ service_record * rval = find_service(string(name));
if (rval != 0) {
if (rval->isDummy()) {
throw ServiceCyclicDependency(name);
string pid_file;
ServiceType service_type = ServiceType::PROCESS;
- std::list<ServiceRecord *> depends_on;
- std::list<ServiceRecord *> depends_soft;
+ std::list<service_record *> depends_on;
+ std::list<service_record *> depends_soft;
string logfile;
OnstartFlags onstart_flags;
int term_signal = -1; // additional termination signal
}
// Add a dummy service record now to prevent infinite recursion in case of cyclic dependency
- rval = new ServiceRecord(this, string(name));
+ rval = new service_record(this, string(name));
records.push_back(rval);
try {
rval->setStopCommand(stop_command, stop_command_offsets);
}
else {
- rval = new ServiceRecord(this, string(name), service_type, std::move(command), command_offsets,
+ rval = new service_record(this, string(name), service_type, std::move(command), command_offsets,
&depends_on, &depends_soft);
}
rval->setLogfile(logfile);
#include "service-constants.h"
-class ServiceRecord;
+class service_record;
// Interface for listening to services
class ServiceListener
// An event occurred on the service being observed.
// Listeners must not be added or removed during event notification.
- virtual void serviceEvent(ServiceRecord * service, ServiceEvent event) noexcept = 0;
+ virtual void serviceEvent(service_record * service, ServiceEvent event) noexcept = 0;
};
#endif
extern EventLoop_t eventLoop;
// Find the requested service by name
-static ServiceRecord * find_service(const std::list<ServiceRecord *> & records,
+static service_record * find_service(const std::list<service_record *> & records,
const char *name) noexcept
{
using std::list;
- list<ServiceRecord *>::const_iterator i = records.begin();
+ list<service_record *>::const_iterator i = records.begin();
for ( ; i != records.end(); i++ ) {
if (strcmp((*i)->getServiceName().c_str(), name) == 0) {
return *i;
}
}
- return (ServiceRecord *)0;
+ return (service_record *)0;
}
-ServiceRecord * ServiceSet::find_service(const std::string &name) noexcept
+service_record * ServiceSet::find_service(const std::string &name) noexcept
{
return ::find_service(records, name.c_str());
}
void ServiceSet::startService(const char *name)
{
using namespace std;
- ServiceRecord *record = loadServiceRecord(name);
+ service_record *record = loadServiceRecord(name);
record->start();
processQueues(true);
void ServiceSet::stopService(const std::string & name) noexcept
{
- ServiceRecord *record = find_service(name);
+ service_record *record = find_service(name);
if (record != nullptr) {
record->stop();
processQueues(false);
// Called when a service has actually stopped; dependents have stopped already, unless this stop
// is due to an unexpected process termination.
-void ServiceRecord::stopped() noexcept
+void service_record::stopped() noexcept
{
if (onstart_flags.runs_on_console) {
tcsetpgrp(0, getpgrp());
return rearm::REMOVED;
}
-bool ServiceRecord::do_auto_restart() noexcept
+bool service_record::do_auto_restart() noexcept
{
if (auto_restart) {
return service_set->get_auto_restart();
return false;
}
-void ServiceRecord::emergency_stop() noexcept
+void service_record::emergency_stop() noexcept
{
if (! do_auto_restart() && start_explicit) {
start_explicit = false;
return rearm::REMOVED;
}
-void ServiceRecord::require() noexcept
+void service_record::require() noexcept
{
if (required_by++ == 0) {
prop_require = !prop_release;
}
}
-void ServiceRecord::release() noexcept
+void service_record::release() noexcept
{
if (--required_by == 0) {
desired_state = ServiceState::STOPPED;
}
}
-void ServiceRecord::release_dependencies() noexcept
+void service_record::release_dependencies() noexcept
{
for (sr_iter i = depends_on.begin(); i != depends_on.end(); ++i) {
(*i)->release();
}
for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
- ServiceRecord * to = i->getTo();
+ service_record * to = i->getTo();
if (i->holding_acq) {
to->release();
i->holding_acq = false;
}
}
-void ServiceRecord::start(bool activate) noexcept
+void service_record::start(bool activate) noexcept
{
if (activate && ! start_explicit) {
require();
}
}
-void ServiceRecord::do_propagation() noexcept
+void service_record::do_propagation() noexcept
{
if (prop_require) {
// Need to require all our dependencies
}
for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
- ServiceRecord * to = i->getTo();
+ service_record * to = i->getTo();
to->require();
i->holding_acq = true;
}
}
}
-void ServiceRecord::execute_transition() noexcept
+void service_record::execute_transition() noexcept
{
if (service_state == ServiceState::STARTING) {
if (startCheckDependencies(false)) {
}
}
-void ServiceRecord::do_start() noexcept
+void service_record::do_start() noexcept
{
if (pinned_stopped) return;
}
}
-void ServiceRecord::dependencyStarted() noexcept
+void service_record::dependencyStarted() noexcept
{
if (service_state == ServiceState::STARTING && waiting_for_deps) {
service_set->addToStartQueue(this);
}
}
-bool ServiceRecord::startCheckDependencies(bool start_deps) noexcept
+bool service_record::startCheckDependencies(bool start_deps) noexcept
{
bool all_deps_started = true;
}
for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
- ServiceRecord * to = i->getTo();
+ service_record * to = i->getTo();
if (start_deps) {
if (to->service_state != ServiceState::STARTED) {
to->prop_start = true;
return all_deps_started;
}
-bool ServiceRecord::open_socket() noexcept
+bool service_record::open_socket() noexcept
{
if (socket_path.empty() || socket_fd != -1) {
// No socket, or already open
return true;
}
-void ServiceRecord::allDepsStarted(bool has_console) noexcept
+void service_record::allDepsStarted(bool has_console) noexcept
{
if (onstart_flags.starts_on_console && ! has_console) {
waiting_for_deps = true;
}
}
-void ServiceRecord::acquiredConsole() noexcept
+void service_record::acquiredConsole() noexcept
{
if (service_state != ServiceState::STARTING) {
// We got the console but no longer want it.
}
}
-void ServiceRecord::started() noexcept
+void service_record::started() noexcept
{
if (onstart_flags.starts_on_console && ! onstart_flags.runs_on_console) {
tcsetpgrp(0, getpgrp());
}
}
-void ServiceRecord::failed_to_start(bool depfailed) noexcept
+void service_record::failed_to_start(bool depfailed) noexcept
{
if (!depfailed && onstart_flags.starts_on_console) {
tcsetpgrp(0, getpgrp());
}
}
-bool ServiceRecord::start_ps_process() noexcept
+bool service_record::start_ps_process() noexcept
{
// default implementation: there is no process, so we are started.
started();
return false;
}
-void ServiceRecord::run_child_proc(const char * const *args, const char *logfile, bool on_console,
+void service_record::run_child_proc(const char * const *args, const char *logfile, bool on_console,
int wpipefd, int csfd) noexcept
{
// Child process. Must not allocate memory (or otherwise risk throwing any exception)
}
// Mark this and all dependent services as force-stopped.
-void ServiceRecord::forceStop() noexcept
+void service_record::forceStop() noexcept
{
if (service_state != ServiceState::STOPPED) {
force_stop = true;
}
}
-void ServiceRecord::dependentStopped() noexcept
+void service_record::dependentStopped() noexcept
{
if (service_state == ServiceState::STOPPING && waiting_for_deps) {
service_set->addToStopQueue(this);
}
}
-void ServiceRecord::stop(bool bring_down) noexcept
+void service_record::stop(bool bring_down) noexcept
{
if (start_explicit) {
start_explicit = false;
}
}
-void ServiceRecord::do_stop() noexcept
+void service_record::do_stop() noexcept
{
if (pinned_started) return;
}
}
-bool ServiceRecord::stopCheckDependents() noexcept
+bool service_record::stopCheckDependents() noexcept
{
bool all_deps_stopped = true;
for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
return all_deps_stopped;
}
-bool ServiceRecord::stopDependents() noexcept
+bool service_record::stopDependents() noexcept
{
bool all_deps_stopped = true;
for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
}
// All dependents have stopped; we can stop now, too. Only called when STOPPING.
-void ServiceRecord::all_deps_stopped() noexcept
+void service_record::all_deps_stopped() noexcept
{
waiting_for_deps = false;
stopped();
}
}
-void ServiceRecord::unpin() noexcept
+void service_record::unpin() noexcept
{
if (pinned_started) {
pinned_started = false;
}
}
-void ServiceRecord::queue_for_console() noexcept
+void service_record::queue_for_console() noexcept
{
service_set->append_console_queue(this);
}
-void ServiceRecord::release_console() noexcept
+void service_record::release_console() noexcept
{
service_set->pull_console_queue();
}
-void ServiceRecord::interrupt_start() noexcept
+void service_record::interrupt_start() noexcept
{
service_set->unqueue_console(this);
}
-void ServiceSet::service_active(ServiceRecord *sr) noexcept
+void ServiceSet::service_active(service_record *sr) noexcept
{
active_services++;
}
-void ServiceSet::service_inactive(ServiceRecord *sr) noexcept
+void ServiceSet::service_inactive(service_record *sr) noexcept
{
active_services--;
}
base_process_service::base_process_service(ServiceSet *sset, string name, ServiceType service_type, string &&command,
std::list<std::pair<unsigned,unsigned>> &command_offsets,
sr_list * pdepends_on, sr_list * pdepends_soft)
- : ServiceRecord(sset, name, service_type, std::move(command), command_offsets,
+ : service_record(sset, name, service_type, std::move(command), command_offsets,
pdepends_on, pdepends_soft), child_listener(this), child_status_listener(this)
{
restart_interval_count = 0;
restart_timer.stop_timer(eventLoop);
waiting_restart_timer = false;
}
- ServiceRecord::interrupt_start();
+ service_record::interrupt_start();
}
dasynq::rearm process_restart_timer::timer_expiry(EventLoop_t &, int expiry_count)
}
};
-class ServiceRecord;
+class service_record;
class ServiceSet;
class base_process_service;
/* Service dependency record */
class ServiceDep
{
- ServiceRecord * from;
- ServiceRecord * to;
+ service_record * from;
+ service_record * to;
public:
/* Whether the 'from' service is waiting for the 'to' service to start */
/* Whether the 'from' service is holding an acquire on the 'to' service */
bool holding_acq;
- ServiceDep(ServiceRecord * from, ServiceRecord * to) noexcept : from(from), to(to), waiting_on(false), holding_acq(false)
+ ServiceDep(service_record * from, service_record * to) noexcept : from(from), to(to), waiting_on(false), holding_acq(false)
{ }
- ServiceRecord * getFrom() noexcept
+ service_record * getFrom() noexcept
{
return from;
}
- ServiceRecord * getTo() noexcept
+ service_record * getTo() noexcept
{
return to;
}
ServiceIoWatcher(base_process_service * sr) noexcept : service(sr) { }
};
-class ServiceRecord
+class service_record
{
protected:
typedef std::string string;
int required_by = 0; // number of dependents wanting this service to be started
- typedef std::list<ServiceRecord *> sr_list;
+ typedef std::list<service_record *> sr_list;
typedef sr_list::iterator sr_iter;
// list of soft dependencies
public:
// Console queue.
- lld_node<ServiceRecord> console_queue_node;
+ lld_node<service_record> console_queue_node;
// Propagation and start/stop queues
- lls_node<ServiceRecord> prop_queue_node;
- lls_node<ServiceRecord> stop_queue_node;
+ lls_node<service_record> prop_queue_node;
+ lls_node<service_record> stop_queue_node;
protected:
public:
- ServiceRecord(ServiceSet *set, string name)
+ service_record(ServiceSet *set, string name)
: service_state(ServiceState::STOPPED), desired_state(ServiceState::STOPPED),
auto_restart(false), smooth_recovery(false),
pinned_stopped(false), pinned_started(false), waiting_for_deps(false),
service_type = ServiceType::DUMMY;
}
- ServiceRecord(ServiceSet *set, string name, ServiceType service_type, string &&command, std::list<std::pair<unsigned,unsigned>> &command_offsets,
+ service_record(ServiceSet *set, string name, ServiceType service_type, string &&command, std::list<std::pair<unsigned,unsigned>> &command_offsets,
sr_list * pdepends_on, sr_list * pdepends_soft)
- : ServiceRecord(set, name)
+ : service_record(set, name)
{
service_set = set;
service_name = name;
}
}
- virtual ~ServiceRecord() noexcept
+ virtual ~service_record() noexcept
{
}
rearm timer_expiry(EventLoop_t &, int expiry_count);
};
-class base_process_service : public ServiceRecord
+class base_process_service : public service_record
{
friend class ServiceChildWatcher;
friend class ServiceIoWatcher;
virtual bool can_interrupt_start() noexcept override
{
- return waiting_restart_timer || ServiceRecord::can_interrupt_start();
+ return waiting_restart_timer || service_record::can_interrupt_start();
}
virtual void interrupt_start() noexcept override;
}
};
-inline auto extract_prop_queue(ServiceRecord *sr) -> decltype(sr->prop_queue_node) &
+inline auto extract_prop_queue(service_record *sr) -> decltype(sr->prop_queue_node) &
{
return sr->prop_queue_node;
}
-inline auto extract_stop_queue(ServiceRecord *sr) -> decltype(sr->stop_queue_node) &
+inline auto extract_stop_queue(service_record *sr) -> decltype(sr->stop_queue_node) &
{
return sr->stop_queue_node;
}
-inline auto extract_console_queue(ServiceRecord *sr) -> decltype(sr->console_queue_node) &
+inline auto extract_console_queue(service_record *sr) -> decltype(sr->console_queue_node) &
{
return sr->console_queue_node;
}
class ServiceSet
{
int active_services;
- std::list<ServiceRecord *> records;
+ std::list<service_record *> records;
const char *service_dir; // directory containing service descriptions
bool restart_enabled; // whether automatic restart is enabled (allowed)
ShutdownType shutdown_type = ShutdownType::CONTINUE; // Shutdown type, if stopping
// Services waiting for exclusive access to the console
- dlist<ServiceRecord, extract_console_queue> console_queue;
+ dlist<service_record, extract_console_queue> console_queue;
// Propagation and start/stop "queues" - list of services waiting for processing
- slist<ServiceRecord, extract_prop_queue> prop_queue;
- slist<ServiceRecord, extract_stop_queue> stop_queue;
+ slist<service_record, extract_prop_queue> prop_queue;
+ slist<service_record, extract_stop_queue> stop_queue;
// Private methods
// Throws:
// ServiceLoadException (or subclass) on problem with service description
// std::bad_alloc on out-of-memory condition
- ServiceRecord *loadServiceRecord(const char *name);
+ service_record *loadServiceRecord(const char *name);
// Public
void startService(const char *name);
// Locate an existing service record.
- ServiceRecord *find_service(const std::string &name) noexcept;
+ service_record *find_service(const std::string &name) noexcept;
// Find a loaded service record, or load it if it is not loaded.
// Throws:
// ServiceLoadException (or subclass) on problem with service description
// std::bad_alloc on out-of-memory condition
- ServiceRecord *loadService(const std::string &name)
+ service_record *loadService(const std::string &name)
{
- ServiceRecord *record = find_service(name);
+ service_record *record = find_service(name);
if (record == nullptr) {
record = loadServiceRecord(name.c_str());
}
}
// Get the list of all loaded services.
- const std::list<ServiceRecord *> &listServices()
+ const std::list<service_record *> &listServices()
{
return records;
}
// Add a service record to the state propagation queue. The service record will have its
// do_propagation() method called when the queue is processed.
- void addToPropQueue(ServiceRecord *service) noexcept
+ void addToPropQueue(service_record *service) noexcept
{
if (! prop_queue.is_queued(service)) {
prop_queue.insert(service);
// Add a service record to the start queue. The service record will have its
// execute_transition() method called when the queue is processed.
- void addToStartQueue(ServiceRecord *service) noexcept
+ void addToStartQueue(service_record *service) noexcept
{
// The start/stop queue is actually one queue:
addToStopQueue(service);
// Add a service record to the stop queue. The service record will have its
// execute_transition() method called when the queue is processed.
- void addToStopQueue(ServiceRecord *service) noexcept
+ void addToStopQueue(service_record *service) noexcept
{
if (! stop_queue.is_queued(service)) {
stop_queue.insert(service);
}
// Set the console queue tail (returns previous tail)
- void append_console_queue(ServiceRecord * newTail) noexcept
+ void append_console_queue(service_record * newTail) noexcept
{
bool was_empty = console_queue.is_empty();
console_queue.append(newTail);
enable_console_log(true);
}
else {
- ServiceRecord * front = console_queue.pop_front();
+ service_record * front = console_queue.pop_front();
front->acquiredConsole();
}
}
- void unqueue_console(ServiceRecord * service) noexcept
+ void unqueue_console(service_record * service) noexcept
{
if (console_queue.is_queued(service)) {
console_queue.unlink(service);
// Notification from service that it is active (state != STOPPED)
// Only to be called on the transition from inactive to active.
- void service_active(ServiceRecord *) noexcept;
+ void service_active(service_record *) noexcept;
// Notification from service that it is inactive (STOPPED)
// Only to be called on the transition from active to inactive.
- void service_inactive(ServiceRecord *) noexcept;
+ void service_inactive(service_record *) noexcept;
// Find out how many services are active (starting, running or stopping,
// but not stopped).
{
restart_enabled = false;
shutdown_type = type;
- for (std::list<ServiceRecord *>::iterator i = records.begin(); i != records.end(); ++i) {
+ for (std::list<service_record *>::iterator i = records.begin(); i != records.end(); ++i) {
(*i)->stop(false);
(*i)->unpin();
}