Browse Source

dinitcheck: find and report cycles due to "before" service links

Davin McCall 10 months ago
parent
commit
b9c1e3cec6
1 changed files with 32 additions and 5 deletions
  1. 32 5
      src/dinitcheck.cc

+ 32 - 5
src/dinitcheck.cc

@@ -44,12 +44,13 @@ class service_record
 {
 public:
     service_record(const std::string &name_p, const std::string &chain_to_p,
-            std::list<prelim_dep> dependencies_p)
-                : name(name_p), dependencies(dependencies_p) {}
+            std::list<prelim_dep> dependencies_p, std::list<string> before_svcs)
+                : name(name_p), dependencies(dependencies_p), before_svcs(before_svcs) {}
 
     std::string name;
     std::string chain_to;
     std::list<prelim_dep> dependencies;
+    std::list<string> before_svcs;
 
     bool visited = false;  // flag used to detect cyclic dependencies
     bool cycle_free = false;
@@ -139,7 +140,15 @@ int main(int argc, char **argv)
             }
             // add chain_to to services_to_check
             if (!sr->chain_to.empty() && !contains(services_to_check, sr->chain_to)) {
-                services_to_check.push_back(sr->chain_to);
+            	if (!contains(services_to_check, sr->chain_to)) {
+            		services_to_check.push_back(sr->chain_to);
+            	}
+            }
+            // add before_svcs to services_to_check
+            for (const std::string &before_name : sr->before_svcs) {
+            	if (!contains(services_to_check, before_name)) {
+            		services_to_check.push_back(before_name);
+            	}
             }
         }
         catch (service_load_exc &exc) {
@@ -148,6 +157,17 @@ int main(int argc, char **argv)
         }
     }
 
+    // For "before" reverse-dependencies, set up dependencies in the forwards direction (from the dependent)
+    for (const auto &svc_name_record : service_set) {
+    	for (const std::string &before_name : svc_name_record.second->before_svcs) {
+    		auto before_svc_it = service_set.find(before_name);
+    		if (before_svc_it != service_set.end()) {
+    			before_svc_it->second->dependencies.emplace_back(svc_name_record.first,
+    					dependency_type::BEFORE);
+    		}
+    	}
+    }
+
     // Check for circular dependencies
     std::vector<std::tuple<service_record *, size_t>> service_chain;
 
@@ -207,7 +227,14 @@ int main(int argc, char **argv)
         errors_found = true;
         std::cerr << "Found dependency cycle:\n";
         for (auto chain_link : service_chain) {
-            std::cerr << "    " << std::get<0>(chain_link)->name << " ->\n";
+        	service_record *svc = std::get<0>(chain_link);
+            size_t dep_index = std::get<1>(chain_link);
+            std::cerr << "    " << svc->name << " ->";
+            auto dep_it = std::next(svc->dependencies.begin(), dep_index);
+            if (dep_it->dep_type == dependency_type::BEFORE) {
+            	std::cerr << " (via 'before')";
+            }
+            std::cerr << "\n";
         }
         std::cerr << "    " << std::get<0>(service_chain[0])->name << ".\n";
     }
@@ -433,5 +460,5 @@ service_record *load_service(service_set_t &services, const std::string &name,
                 settings.stop_command.substr(offset_start, offset_end - offset_start).c_str());
     }
 
-    return new service_record(name, settings.chain_to_name, settings.depends);
+    return new service_record(name, settings.chain_to_name, settings.depends, settings.before_svcs);
 }