Browse Source

Add support for "after" ordering constraints (as for "before")

Davin McCall 1 year ago
parent
commit
5bc24d3ce8
5 changed files with 19 additions and 5 deletions
  1. 1 1
      src/control.cc
  2. 4 0
      src/includes/load-service.h
  3. 2 1
      src/includes/service-constants.h
  4. 9 1
      src/includes/service.h
  5. 3 2
      src/service.cc

+ 1 - 1
src/control.cc

@@ -343,7 +343,7 @@ bool control_conn_t::process_start_stop(int pktType)
             }
             bool found_dpt = false;
             for (auto dpt : service->get_dependents()) {
-                if (dpt->dep_type == dependency_type::BEFORE) continue;
+                if (dpt->is_only_ordering()) continue;
                 auto from = dpt->get_from();
                 auto from_state = from->get_state();
                 if (from_state == service_state_t::STARTED || from_state == service_state_t::STARTING) {

+ 4 - 0
src/includes/load-service.h

@@ -988,6 +988,10 @@ void process_service_line(settings_wrapper &settings, const char *name, string &
         string waitsford = read_setting_value(line_num, i, end);
         process_dep_dir(settings.depends, waitsford, dependency_type::WAITS_FOR);
     }
+    else if (setting == "after") {
+        string after_name = read_setting_value(line_num, i, end);
+        settings.depends.emplace_back(load_service(after_name.c_str()), dependency_type::AFTER);
+    }
     else if (setting == "before") {
         string before_name = read_setting_value(line_num, i, end);
         settings.before_svcs.emplace_back(std::move(before_name));

+ 2 - 1
src/includes/service-constants.h

@@ -106,7 +106,8 @@ enum class dependency_type
     SOFT,       // dependency starts in parallel, failure/stop does not affect dependent
     WAITS_FOR,  // as for SOFT, but dependent waits until dependency starts/fails before starting
     MILESTONE,  // dependency must start successfully, but once started the dependency becomes soft
-    BEFORE      // dependency due to "before" specified in the dependency (to) service
+    BEFORE,     // "before" ordering constraint (specified via the "to" service)
+    AFTER       // "after" ordering constraint (specified via the "from" service)
 };
 
 // Service set type identifiers:

+ 9 - 1
src/includes/service.h

@@ -169,6 +169,12 @@ class service_dep
                 || (dep_type == dependency_type::MILESTONE && waiting_on);
     }
 
+    // Check if the dependency represents only an ordering constraint (not really a dependency)
+    bool is_only_ordering()
+    {
+        return (dep_type == dependency_type::BEFORE) || (dep_type == dependency_type::AFTER);
+    }
+
     service_dep(service_record * from, service_record * to, dependency_type dep_type_p) noexcept
             : from(from), to(to), waiting_on(false), holding_acq(false), dep_type(dep_type_p)
     {  }
@@ -618,6 +624,8 @@ class service_record
     {
         if (check_deps) {
             for (auto *dept : dependents) {
+                // BEFORE links don't count because they are actually specified via the "to" service i.e.
+                // this service.
                 if (dept->dep_type != dependency_type::BEFORE) {
                     return false;
                 }
@@ -703,7 +711,7 @@ class service_record
             throw;
         }
 
-        if (dep_type != dependency_type::BEFORE) {
+        if (dep_type != dependency_type::BEFORE && dep_type != dependency_type::AFTER) {
             if (dep_type == dependency_type::REGULAR
                     || to->get_state() == service_state_t::STARTED
                     || to->get_state() == service_state_t::STARTING) {

+ 3 - 2
src/service.cc

@@ -218,7 +218,7 @@ void service_record::do_propagation() noexcept
     if (prop_require) {
         // Need to require all our dependencies
         for (auto & dep : depends_on) {
-            if (dep.dep_type != dependency_type::BEFORE) {
+            if (!dep.is_only_ordering()) {
                 dep.get_to()->require();
                 dep.holding_acq = true;
             }
@@ -335,7 +335,7 @@ bool service_record::start_check_dependencies() noexcept
 
     for (auto & dep : depends_on) {
         service_record * to = dep.get_to();
-        if (dep.dep_type == dependency_type::BEFORE
+        if (dep.is_only_ordering()
                 && to->service_state != service_state_t::STARTING) continue;
         if (to->service_state != service_state_t::STARTED) {
             dep.waiting_on = true;
@@ -454,6 +454,7 @@ void service_record::failed_to_start(bool depfailed, bool immediate_stop) noexce
         case dependency_type::WAITS_FOR:
         case dependency_type::SOFT:
         case dependency_type::BEFORE:
+        case dependency_type::AFTER:
             if (dept->waiting_on) {
                 dept->waiting_on = false;
                 dept->get_from()->dependency_started();