// Variables
-static service_set *services;
+static dirload_service_set *services;
static bool am_system_init = false; // true if we are the system init process
#endif
/* start requested services */
- services = new service_set(service_dir);
+ services = new dirload_service_set(service_dir);
init_log(services);
for (auto svc : services_to_start) {
try {
- services->startService(svc);
+ services->start_service(svc);
// Note in general if we fail to start a service we don't need any special error handling,
// since we either leave other services running or, if it was the only service, then no
// services will be running and we will process normally (reboot if system process,
// user has now exited the shell. We'll try and re-start the
// boot process...
try {
- services->startService("boot");
+ services->start_service("boot");
goto event_loop; // yes, the "evil" goto
}
catch (...) {
// 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.
-service_record * service_set::loadServiceRecord(const char * name)
+service_record * dirload_service_set::load_service(const char * name)
{
using std::string;
using std::ifstream;
// Add a dummy service record now to prevent infinite recursion in case of cyclic dependency
rval = new service_record(this, string(name));
- records.push_back(rval);
+ add_service(rval);
try {
// getline can set failbit if it reaches end-of-file, we don't want an exception in that case:
}
else if (setting == "depends-on") {
string dependency_name = read_setting_value(i, end);
- depends_on.push_back(loadServiceRecord(dependency_name.c_str()));
+ depends_on.push_back(load_service(dependency_name.c_str()));
}
else if (setting == "waits-for") {
string dependency_name = read_setting_value(i, end);
- depends_soft.push_back(loadServiceRecord(dependency_name.c_str()));
+ depends_soft.push_back(load_service(dependency_name.c_str()));
}
else if (setting == "logfile") {
logfile = read_setting_value(i, end);
service_name = name;
record_type = service_type::DUMMY;
}
-
- service_record(service_set *set, string name, service_type record_type_p, string &&command, std::list<std::pair<unsigned,unsigned>> &command_offsets,
+
+ service_record(service_set *set, string name, service_type record_type_p,
sr_list * pdepends_on, sr_list * pdepends_soft)
: service_record(set, name)
{
this->record_type = record_type_p;
this->depends_on = std::move(*pdepends_on);
- program_name = std::move(command);
- exec_arg_parts = separate_args(program_name, command_offsets);
-
for (sr_iter i = depends_on.begin(); i != depends_on.end(); ++i) {
(*i)->dependents.push_back(this);
}
}
}
+ service_record(service_set *set, string name, service_type record_type_p, string &&command, std::list<std::pair<unsigned,unsigned>> &command_offsets,
+ sr_list * pdepends_on, sr_list * pdepends_soft)
+ : service_record(set, name, record_type_p, pdepends_on, pdepends_soft)
+ {
+ program_name = std::move(command);
+ exec_arg_parts = separate_args(program_name, command_offsets);
+ }
+
virtual ~service_record() noexcept
{
}
*/
class service_set
{
+ protected:
int active_services;
std::list<service_record *> records;
- const char *service_dir; // directory containing service descriptions
bool restart_enabled; // whether automatic restart is enabled (allowed)
shutdown_type_t shutdown_type = shutdown_type_t::CONTINUE; // Shutdown type, if stopping
slist<service_record, extract_prop_queue> prop_queue;
slist<service_record, extract_stop_queue> stop_queue;
- // Private methods
-
+ public:
+ service_set()
+ {
+ active_services = 0;
+ restart_enabled = true;
+ }
+
+ // Start the specified service
+ void start_service(service_record *svc)
+ {
+ svc->start();
+ processQueues();
+ }
+
+ // Locate an existing service record.
+ service_record *find_service(const std::string &name) noexcept;
+
// Load a service description, and dependencies, if there is no existing
// record for the given name.
// Throws:
// ServiceLoadException (or subclass) on problem with service description
// std::bad_alloc on out-of-memory condition
- service_record *loadServiceRecord(const char *name);
-
- // Public
-
- public:
- service_set(const char *service_dir)
+ virtual service_record *load_service(const char *name)
{
- this->service_dir = service_dir;
- active_services = 0;
- restart_enabled = true;
+ auto r = find_service(name);
+ if (r == nullptr) {
+ throw service_not_found(name);
+ }
+ return r;
}
-
+
// Start the service with the given name. The named service will begin
// transition to the 'started' state.
//
// Throws a ServiceLoadException (or subclass) if the service description
// cannot be loaded or is invalid;
// Throws std::bad_alloc if out of memory.
- void startService(const char *name);
-
- // Locate an existing service record.
- service_record *find_service(const std::string &name) noexcept;
+ void start_service(const char *name)
+ {
+ using namespace std;
+ service_record *record = load_service(name);
+ service_set::start_service(record);
+ }
- // 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
- service_record *loadService(const std::string &name)
+ void add_service(service_record *svc)
{
- service_record *record = find_service(name);
- if (record == nullptr) {
- record = loadServiceRecord(name.c_str());
- }
- return record;
+ records.push_back(svc);
}
+ void remove_service(service_record *svc)
+ {
+ std::remove(records.begin(), records.end(), svc);
+ }
+
// Get the list of all loaded services.
const std::list<service_record *> &listServices()
{
}
};
+class dirload_service_set : public service_set
+{
+ const char *service_dir; // directory containing service descriptions
+
+ public:
+ dirload_service_set(const char *service_dir_p) : service_set(), service_dir(service_dir_p)
+ {
+ }
+
+ service_record *load_service(const char *name) override;
+};
+
#endif