|
7 | 7 | #include "base/scriptglobal.hpp"
|
8 | 8 | #include "base/namespace.hpp"
|
9 | 9 | #include "base/objectlock.hpp"
|
10 |
| -#include <algorithm> |
11 | 10 | #include <functional>
|
12 |
| -#include <unordered_map> |
13 | 11 |
|
14 | 12 | using namespace icinga;
|
15 | 13 |
|
@@ -41,53 +39,37 @@ INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
41 | 39 | static std::vector<Type::Ptr> l_SortedByLoadDependencies;
|
42 | 40 | static Atomic l_SortingByLoadDependenciesDone (false);
|
43 | 41 |
|
44 |
| -typedef std::unordered_map<Type*, bool> Visited; // https://stackoverflow.com/a/8942986 |
45 |
| - |
46 | 42 | INITIALIZE_ONCE_WITH_PRIORITY([] {
|
47 |
| - auto types (Type::GetAllTypes()); |
48 |
| - |
49 |
| - types.erase(std::remove_if(types.begin(), types.end(), [](auto& type) { |
50 |
| - return !ConfigObject::TypeInstance->IsAssignableFrom(type); |
51 |
| - }), types.end()); |
52 |
| - |
53 |
| - // Depth-first search |
54 |
| - std::unordered_set<Type*> unsorted; |
55 |
| - Visited visited; |
56 |
| - std::vector<Type::Ptr> sorted; |
57 |
| - |
58 |
| - for (auto type : types) { |
59 |
| - unsorted.emplace(type.get()); |
60 |
| - } |
| 43 | + std::unordered_set<Type*> visited; |
61 | 44 |
|
62 |
| - std::function<void(Type*)> visit ([&visit, &unsorted, &visited, &sorted](Type* type) { |
63 |
| - if (unsorted.find(type) == unsorted.end()) { |
| 45 | + std::function<void(Type*)> visit; |
| 46 | + // Please note that this callback does not detect any cyclic load dependencies, |
| 47 | + // instead, it relies on the "sort_by_load_after" unit test to fail. |
| 48 | + visit = ([&visit, &visited](Type* type) { |
| 49 | + if (visited.find(type) != visited.end()) { |
64 | 50 | return;
|
65 | 51 | }
|
| 52 | + visited.emplace(type); |
66 | 53 |
|
67 |
| - bool& alreadyVisited (visited.at(type)); |
68 |
| - VERIFY(!alreadyVisited); |
69 |
| - alreadyVisited = true; |
70 |
| - |
71 |
| - for (auto dep : type->GetLoadDependencies()) { |
72 |
| - visit(dep); |
| 54 | + for (auto dependency : type->GetLoadDependencies()) { |
| 55 | + visit(dependency); |
73 | 56 | }
|
74 | 57 |
|
75 |
| - unsorted.erase(type); |
76 |
| - sorted.emplace_back(type); |
| 58 | + // We have managed to reach the final/top node in this dependency graph, |
| 59 | + // so let's place them in reverse order to their final place. |
| 60 | + l_SortedByLoadDependencies.emplace_back(type); |
77 | 61 | });
|
78 | 62 |
|
79 |
| - while (!unsorted.empty()) { |
80 |
| - for (auto& type : types) { |
81 |
| - visited[type.get()] = false; |
| 63 | + // Sort the types by their load_after dependencies in a Depth-First search manner. |
| 64 | + for (const Type::Ptr& type : Type::GetAllTypes()) { |
| 65 | + // Note that only those types that are assignable to the dynamic ConfigObject type can have "load_after" |
| 66 | + // dependencies, otherwise they are just some Icinga 2 primitive types such as Number, String, etc. and |
| 67 | + // we need to ignore them. |
| 68 | + if (ConfigObject::TypeInstance->IsAssignableFrom(type)) { |
| 69 | + visit(type.get()); |
82 | 70 | }
|
83 |
| - |
84 |
| - visit(*unsorted.begin()); |
85 | 71 | }
|
86 | 72 |
|
87 |
| - VERIFY(sorted.size() == types.size()); |
88 |
| - VERIFY(sorted[0]->GetLoadDependencies().empty()); |
89 |
| - |
90 |
| - std::swap(sorted, l_SortedByLoadDependencies); |
91 | 73 | l_SortingByLoadDependenciesDone.store(true);
|
92 | 74 | }, InitializePriority::SortTypes);
|
93 | 75 |
|
|
0 commit comments