summaryrefslogtreecommitdiff
path: root/src/mongo/base
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2018-02-27 09:47:29 -0500
committerHenrik Edin <henrik.edin@mongodb.com>2018-03-12 10:57:28 -0400
commit0486c9ff50402c8680d14a495c2d9dfe543939a1 (patch)
treeae6959309757d62c055a2f6cecbc8532aba17400 /src/mongo/base
parentd7012b42d747b498dc06747240c79f576425bbc6 (diff)
downloadmongo-0486c9ff50402c8680d14a495c2d9dfe543939a1.tar.gz
SERVER-33629 Deinitialization support for MONGO_INITIALIZER. Done via the GlobalInitializerRegisterer instead of macros. Deinitialization executes in reverse order from initialization.
Diffstat (limited to 'src/mongo/base')
-rw-r--r--src/mongo/base/deinitializer_context.cpp30
-rw-r--r--src/mongo/base/deinitializer_context.h51
-rw-r--r--src/mongo/base/global_initializer_registerer.cpp16
-rw-r--r--src/mongo/base/global_initializer_registerer.h202
-rw-r--r--src/mongo/base/init.h8
-rw-r--r--src/mongo/base/initializer.cpp50
-rw-r--r--src/mongo/base/initializer.h17
-rw-r--r--src/mongo/base/initializer_dependency_graph.cpp30
-rw-r--r--src/mongo/base/initializer_dependency_graph.h43
-rw-r--r--src/mongo/base/initializer_dependency_graph_test.cpp9
-rw-r--r--src/mongo/base/initializer_function.h10
-rw-r--r--src/mongo/base/initializer_test.cpp17
12 files changed, 428 insertions, 55 deletions
diff --git a/src/mongo/base/deinitializer_context.cpp b/src/mongo/base/deinitializer_context.cpp
new file mode 100644
index 00000000000..1708587da36
--- /dev/null
+++ b/src/mongo/base/deinitializer_context.cpp
@@ -0,0 +1,30 @@
+/* Copyright 2018 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#include "mongo/base/deinitializer_context.h"
+
+namespace mongo {} // namespace mongo
diff --git a/src/mongo/base/deinitializer_context.h b/src/mongo/base/deinitializer_context.h
new file mode 100644
index 00000000000..0e8edc32066
--- /dev/null
+++ b/src/mongo/base/deinitializer_context.h
@@ -0,0 +1,51 @@
+/* Copyright 2018 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "mongo/base/disallow_copying.h"
+
+namespace mongo {
+
+/**
+ * Context of a deinitialization process. Passed as a parameter to deinitialization functions.
+ *
+ * See mongo/base/initializer.h and mongo/base/initializer_dependency_graph.h for more details.
+ */
+class DeinitializerContext {
+public:
+ DeinitializerContext() = default;
+
+ DeinitializerContext(DeinitializerContext const&) = delete;
+ DeinitializerContext& operator=(DeinitializerContext const&) = delete;
+};
+
+} // namespace mongo
diff --git a/src/mongo/base/global_initializer_registerer.cpp b/src/mongo/base/global_initializer_registerer.cpp
index f9fb925ef44..73986e3bc0c 100644
--- a/src/mongo/base/global_initializer_registerer.cpp
+++ b/src/mongo/base/global_initializer_registerer.cpp
@@ -35,13 +35,17 @@
namespace mongo {
-GlobalInitializerRegisterer::GlobalInitializerRegisterer(
- const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents) {
+GlobalInitializerRegisterer::GlobalInitializerRegisterer(std::string name,
+ std::vector<std::string> prerequisites,
+ std::vector<std::string> dependents,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn) {
Status status = getGlobalInitializer().getInitializerDependencyGraph().addInitializer(
- name, fn, prerequisites, dependents);
+ std::move(name),
+ std::move(initFn),
+ std::move(deinitFn),
+ std::move(prerequisites),
+ std::move(dependents));
if (Status::OK() != status) {
diff --git a/src/mongo/base/global_initializer_registerer.h b/src/mongo/base/global_initializer_registerer.h
index 78e77b242cd..fd73c7622aa 100644
--- a/src/mongo/base/global_initializer_registerer.h
+++ b/src/mongo/base/global_initializer_registerer.h
@@ -34,6 +34,13 @@
#include "mongo/base/initializer_function.h"
#include "mongo/base/status.h"
+/**
+* Convenience parameter representing the default set of dependents for initializer functions. Should
+* just be used internally, for MONGO_INITIALIZER macros, use MONGO_DEFAULT_PREREQUISITES from init.h
+* instead.
+*/
+#define MONGO_DEFAULT_PREREQUISITES_STR "default"
+
namespace mongo {
/**
@@ -47,10 +54,197 @@ class GlobalInitializerRegisterer {
MONGO_DISALLOW_COPYING(GlobalInitializerRegisterer);
public:
- GlobalInitializerRegisterer(const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents);
+ /**
+ * Defines an initializer function that depends on default prerequisites and has no explicit
+ * dependents.
+ *
+ * Does not support deinitialization and will never be re-initialized.
+ *
+ * Usage:
+ * GlobalInitializerRegisterer myRegsisterer(
+ * "myInitializer",
+ * [](InitializerContext* context) {
+ * // initialization code
+ * return Status::OK();
+ * }
+ * );
+ */
+ GlobalInitializerRegisterer(std::string name, InitializerFunction initFn);
+
+ /**
+ * Defines an initializer function that depends on PREREQUISITES and has no explicit dependents.
+ *
+ * At run time, the full set of prerequisites for NAME will be computed as the union of the
+ * explicit PREREQUISITES.
+ *
+ * Does not support deinitialization and will never be re-initialized.
+ *
+ * Usage:
+ * GlobalInitializerRegisterer myRegsisterer(
+ * "myInitializer",
+ * {"myPrereq1", "myPrereq2", ...},
+ * [](InitializerContext* context) {
+ * // initialization code
+ * return Status::OK();
+ * }
+ * );
+ */
+ GlobalInitializerRegisterer(std::string name,
+ std::vector<std::string> prerequisites,
+ InitializerFunction initFn);
+
+ /**
+ * Defines an initializer function that depends on PREREQUISITES and has DEPENDENTS as explicit
+ * dependents.
+ *
+ * At run time, the full set of prerequisites for NAME will be computed as the union of the
+ * explicit PREREQUISITES and the set of all other mongo initializers that name NAME in their
+ * list of dependents.
+ *
+ * Does not support deinitialization and will never be re-initialized.
+ *
+ * Usage:
+ * GlobalInitializerRegisterer myRegsisterer(
+ * "myInitializer",
+ * {"myPrereq1", "myPrereq2", ...},
+ * {"myDependent1", "myDependent2", ...},
+ * [](InitializerContext* context) {
+ * // initialization code
+ * return Status::OK();
+ * }
+ * );
+ */
+ GlobalInitializerRegisterer(std::string name,
+ std::vector<std::string> prerequisites,
+ std::vector<std::string> dependents,
+ InitializerFunction initFn);
+
+ /**
+ * Defines an initializer function that depends on default prerequisites and has no explicit
+ * dependents.
+ * It also provides a deinitialization that will execute in reverse order from initialization and
+ * support re-initialization.
+ *
+ * Usage:
+ * GlobalInitializerRegisterer myRegsisterer(
+ * "myInitializer",
+ * [](InitializerContext* context) {
+ * // initialization code
+ * return Status::OK();
+ * },
+ * [](DeinitializerContext* context) {
+ * // deinitialization code
+ * return Status::OK();
+ * }
+ * );
+ */
+ GlobalInitializerRegisterer(std::string name,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn);
+
+ /**
+ * Defines an initializer function that depends on PREREQUISITES and has no explicit dependents.
+ *
+ * At run time, the full set of prerequisites for NAME will be computed as the union of the
+ * explicit PREREQUISITES.
+ *
+ * It also provides a deinitialization that will execute in reverse order from initialization and
+ * support re-initialization.
+ *
+ * Usage:
+ * GlobalInitializerRegisterer myRegsisterer(
+ * "myInitializer",
+ * {"myPrereq1", "myPrereq2", ...},
+ * [](InitializerContext* context) {
+ * // initialization code
+ * return Status::OK();
+ * },
+ * [](DeinitializerContext* context) {
+ * // deinitialization code
+ * return Status::OK();
+ * }
+ * );
+ */
+ GlobalInitializerRegisterer(std::string name,
+ std::vector<std::string> prerequisites,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn);
+
+ /**
+ * Defines an initializer function that depends on PREREQUISITES and has DEPENDENTS as explicit
+ * dependents.
+ *
+ * At run time, the full set of prerequisites for NAME will be computed as the union of the
+ * explicit PREREQUISITES and the set of all other mongo initializers that name NAME in their
+ * list of dependents.
+ *
+ * It also provides a deinitialization that will execute in reverse order from initialization and
+ * support re-initialization.
+ *
+ * Usage:
+ * GlobalInitializerRegisterer myRegsisterer(
+ * "myInitializer",
+ * {"myPrereq1", "myPrereq2", ...},
+ * {"myDependent1", "myDependent2", ...},
+ * [](InitializerContext* context) {
+ * // initialization code
+ * return Status::OK();
+ * },
+ * [](DeinitializerContext* context) {
+ * // deinitialization code
+ * return Status::OK();
+ * }
+ * );
+ */
+ GlobalInitializerRegisterer(std::string name,
+ std::vector<std::string> prerequisites,
+ std::vector<std::string> dependents,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn);
};
+inline GlobalInitializerRegisterer::GlobalInitializerRegisterer(std::string name,
+ InitializerFunction initFn)
+ : GlobalInitializerRegisterer(std::move(name),
+ {MONGO_DEFAULT_PREREQUISITES_STR},
+ {},
+ std::move(initFn),
+ DeinitializerFunction()) {}
+
+inline GlobalInitializerRegisterer::GlobalInitializerRegisterer(
+ std::string name, std::vector<std::string> prerequisites, InitializerFunction initFn)
+ : GlobalInitializerRegisterer(std::move(name),
+ std::move(prerequisites),
+ {},
+ std::move(initFn),
+ DeinitializerFunction()) {}
+
+inline GlobalInitializerRegisterer::GlobalInitializerRegisterer(
+ std::string name,
+ std::vector<std::string> prerequisites,
+ std::vector<std::string> dependents,
+ InitializerFunction initFn)
+ : GlobalInitializerRegisterer(std::move(name),
+ std::move(prerequisites),
+ std::move(dependents),
+ std::move(initFn),
+ DeinitializerFunction()) {}
+
+inline GlobalInitializerRegisterer::GlobalInitializerRegisterer(std::string name,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn)
+ : GlobalInitializerRegisterer(std::move(name),
+ {MONGO_DEFAULT_PREREQUISITES_STR},
+ {},
+ std::move(initFn),
+ std::move(deinitFn)) {}
+
+inline GlobalInitializerRegisterer::GlobalInitializerRegisterer(
+ std::string name,
+ std::vector<std::string> prerequisites,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn)
+ : GlobalInitializerRegisterer(
+ std::move(name), std::move(prerequisites), {}, std::move(initFn), std::move(deinitFn)) {}
+
} // namespace mongo
diff --git a/src/mongo/base/init.h b/src/mongo/base/init.h
index c68eb027e0f..5fc8aed2c86 100644
--- a/src/mongo/base/init.h
+++ b/src/mongo/base/init.h
@@ -61,7 +61,7 @@
/**
* Convenience parameter representing the default set of dependents for initializer functions.
*/
-#define MONGO_DEFAULT_PREREQUISITES ("default")
+#define MONGO_DEFAULT_PREREQUISITES (MONGO_DEFAULT_PREREQUISITES_STR)
/**
* Macro to define an initializer function named "NAME" with the default prerequisites, and
@@ -119,10 +119,10 @@
::mongo::Status _MONGO_INITIALIZER_FUNCTION_NAME(NAME)(::mongo::InitializerContext*); \
namespace { \
::mongo::GlobalInitializerRegisterer _mongoInitializerRegisterer_##NAME( \
- #NAME, \
- _MONGO_INITIALIZER_FUNCTION_NAME(NAME), \
+ std::string(#NAME), \
MONGO_MAKE_STRING_VECTOR PREREQUISITES, \
- MONGO_MAKE_STRING_VECTOR DEPENDENTS); \
+ MONGO_MAKE_STRING_VECTOR DEPENDENTS, \
+ mongo::InitializerFunction(_MONGO_INITIALIZER_FUNCTION_NAME(NAME))); \
} \
::mongo::Status _MONGO_INITIALIZER_FUNCTION_NAME(NAME)
diff --git a/src/mongo/base/initializer.cpp b/src/mongo/base/initializer.cpp
index 8de4eb41533..9939057b070 100644
--- a/src/mongo/base/initializer.cpp
+++ b/src/mongo/base/initializer.cpp
@@ -27,6 +27,7 @@
#include "mongo/base/initializer.h"
+#include "mongo/base/deinitializer_context.h"
#include "mongo/base/global_initializer.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/quick_exit.h"
@@ -37,8 +38,8 @@ namespace mongo {
Initializer::Initializer() {}
Initializer::~Initializer() {}
-Status Initializer::execute(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) const {
+Status Initializer::executeInitializers(const InitializerContext::ArgumentVector& args,
+ const InitializerContext::EnvironmentMap& env) {
std::vector<std::string> sortedNodes;
Status status = _graph.topSort(&sortedNodes);
if (Status::OK() != status)
@@ -47,7 +48,14 @@ Status Initializer::execute(const InitializerContext::ArgumentVector& args,
InitializerContext context(args, env);
for (size_t i = 0; i < sortedNodes.size(); ++i) {
- InitializerFunction fn = _graph.getInitializerFunction(sortedNodes[i]);
+ InitializerDependencyNode* node = _graph.getInitializerNode(sortedNodes[i]);
+
+ // If already initialized then this node is a legacy initializer without re-initialization
+ // support.
+ if (node->isInitialized())
+ continue;
+
+ auto const& fn = node->getInitializerFunction();
if (!fn) {
return Status(ErrorCodes::InternalError,
"topSort returned a node that has no associated function: \"" +
@@ -61,13 +69,43 @@ Status Initializer::execute(const InitializerContext::ArgumentVector& args,
if (Status::OK() != status)
return status;
+
+ node->setInitialized(true);
+ }
+ return Status::OK();
+}
+
+Status Initializer::executeDeinitializers() {
+ std::vector<std::string> sortedNodes;
+ Status status = _graph.topSort(&sortedNodes);
+ if (Status::OK() != status)
+ return status;
+
+ DeinitializerContext context;
+
+ // Execute deinitialization in reverse order from initialization.
+ for (auto it = sortedNodes.rbegin(), end = sortedNodes.rend(); it != end; ++it) {
+ InitializerDependencyNode* node = _graph.getInitializerNode(*it);
+ auto const& fn = node->getDeinitializerFunction();
+ if (fn) {
+ try {
+ status = fn(&context);
+ } catch (const DBException& xcp) {
+ return xcp.toStatus();
+ }
+
+ if (Status::OK() != status)
+ return status;
+
+ node->setInitialized(false);
+ }
}
return Status::OK();
}
Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
const InitializerContext::EnvironmentMap& env) {
- return getGlobalInitializer().execute(args, env);
+ return getGlobalInitializer().executeInitializers(args, env);
}
Status runGlobalInitializers(int argc, const char* const* argv, const char* const* envp) {
@@ -89,6 +127,10 @@ Status runGlobalInitializers(int argc, const char* const* argv, const char* cons
return runGlobalInitializers(args, env);
}
+Status runGlobalDeinitializers() {
+ return getGlobalInitializer().executeDeinitializers();
+}
+
void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp) {
Status status = runGlobalInitializers(argc, argv, envp);
if (!status.isOK()) {
diff --git a/src/mongo/base/initializer.h b/src/mongo/base/initializer.h
index fa4ba508981..904356fdbef 100644
--- a/src/mongo/base/initializer.h
+++ b/src/mongo/base/initializer.h
@@ -65,8 +65,10 @@ public:
* Returns Status::OK on success. All other returns constitute initialization failures,
* and the thing being initialized should be considered dead in the water.
*/
- Status execute(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) const;
+ Status executeInitializers(const InitializerContext::ArgumentVector& args,
+ const InitializerContext::EnvironmentMap& env);
+
+ Status executeDeinitializers();
private:
InitializerDependencyGraph _graph;
@@ -92,4 +94,15 @@ Status runGlobalInitializers(int argc, const char* const* argv, const char* cons
*/
void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp);
+/**
+* Run the global deinitializers. They will execute in reverse order from initialization.
+*
+* It's a programming error for this to fail, but if it does it will return a status other
+* than Status::OK.
+*
+* This means that the few initializers that might want to terminate the program by failing
+* should probably arrange to terminate the process themselves.
+*/
+Status runGlobalDeinitializers();
+
} // namespace mongo
diff --git a/src/mongo/base/initializer_dependency_graph.cpp b/src/mongo/base/initializer_dependency_graph.cpp
index 927c8c87658..014c8110b28 100644
--- a/src/mongo/base/initializer_dependency_graph.cpp
+++ b/src/mongo/base/initializer_dependency_graph.cpp
@@ -36,19 +36,21 @@ namespace mongo {
InitializerDependencyGraph::InitializerDependencyGraph() {}
InitializerDependencyGraph::~InitializerDependencyGraph() {}
-Status InitializerDependencyGraph::addInitializer(const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents) {
- if (!fn)
+Status InitializerDependencyGraph::addInitializer(std::string name,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn,
+ std::vector<std::string> prerequisites,
+ std::vector<std::string> dependents) {
+ if (!initFn)
return Status(ErrorCodes::BadValue, "Illegal to supply a NULL function");
- NodeData& newNode = _nodes[name];
- if (newNode.fn) {
+ InitializerDependencyNode& newNode = _nodes[name];
+ if (newNode.initFn) {
return Status(ErrorCodes::DuplicateKey, name);
}
- newNode.fn = fn;
+ newNode.initFn = std::move(initFn);
+ newNode.deinitFn = std::move(deinitFn);
for (size_t i = 0; i < prerequisites.size(); ++i) {
newNode.prerequisites.insert(prerequisites[i]);
@@ -61,12 +63,12 @@ Status InitializerDependencyGraph::addInitializer(const std::string& name,
return Status::OK();
}
-InitializerFunction InitializerDependencyGraph::getInitializerFunction(
- const std::string& name) const {
- NodeMap::const_iterator iter = _nodes.find(name);
+InitializerDependencyNode* InitializerDependencyGraph::getInitializerNode(const std::string& name) {
+ NodeMap::iterator iter = _nodes.find(name);
if (iter == _nodes.end())
- return InitializerFunction();
- return iter->second.fn;
+ return nullptr;
+
+ return &iter->second;
}
Status InitializerDependencyGraph::topSort(std::vector<std::string>* sortedNames) const {
@@ -92,7 +94,7 @@ Status InitializerDependencyGraph::topSort(std::vector<std::string>* sortedNames
return status;
}
for (const auto& node : _nodes) {
- if (!node.second.fn) {
+ if (!node.second.initFn) {
std::ostringstream os;
os << "No implementation provided for initializer " << node.first;
return {ErrorCodes::BadValue, os.str()};
diff --git a/src/mongo/base/initializer_dependency_graph.h b/src/mongo/base/initializer_dependency_graph.h
index bad3154e19b..dfbddcab459 100644
--- a/src/mongo/base/initializer_dependency_graph.h
+++ b/src/mongo/base/initializer_dependency_graph.h
@@ -39,6 +39,31 @@
namespace mongo {
+class InitializerDependencyNode {
+ friend class InitializerDependencyGraph;
+
+public:
+ bool isInitialized() const {
+ return initialized;
+ }
+ void setInitialized(bool value) {
+ initialized = value;
+ };
+
+ InitializerFunction const& getInitializerFunction() const {
+ return initFn;
+ }
+ DeinitializerFunction const& getDeinitializerFunction() const {
+ return deinitFn;
+ }
+
+private:
+ InitializerFunction initFn;
+ DeinitializerFunction deinitFn;
+ stdx::unordered_set<std::string> prerequisites;
+ bool initialized{false};
+};
+
/**
* Representation of a dependency graph of "initialization operations."
*
@@ -74,16 +99,17 @@ public:
* to the graph. Note that cycles in the dependency graph are not discovered in this phase.
* Rather, they're discovered by topSort, below.
*/
- Status addInitializer(const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents);
+ Status addInitializer(std::string name,
+ InitializerFunction initFn,
+ DeinitializerFunction deinitFn,
+ std::vector<std::string> prerequisites,
+ std::vector<std::string> dependents);
/**
* Given a dependency operation node named "name", return its behavior function. Returns
* a value that evaluates to "false" in boolean context, otherwise.
*/
- InitializerFunction getInitializerFunction(const std::string& name) const;
+ InitializerDependencyNode* getInitializerNode(const std::string& name);
/**
* Construct a topological sort of the dependency graph, and store that order into
@@ -101,12 +127,7 @@ public:
Status topSort(std::vector<std::string>* sortedNames) const;
private:
- struct NodeData {
- InitializerFunction fn;
- stdx::unordered_set<std::string> prerequisites;
- };
-
- typedef stdx::unordered_map<std::string, NodeData> NodeMap;
+ typedef stdx::unordered_map<std::string, InitializerDependencyNode> NodeMap;
typedef NodeMap::value_type Node;
/**
diff --git a/src/mongo/base/initializer_dependency_graph_test.cpp b/src/mongo/base/initializer_dependency_graph_test.cpp
index 2039d65da42..9a67fa0899a 100644
--- a/src/mongo/base/initializer_dependency_graph_test.cpp
+++ b/src/mongo/base/initializer_dependency_graph_test.cpp
@@ -34,9 +34,12 @@
#include "mongo/base/make_string_vector.h"
#include "mongo/unittest/unittest.h"
-#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
- (GRAPH).addInitializer( \
- (NAME), (FN), MONGO_MAKE_STRING_VECTOR PREREQS, MONGO_MAKE_STRING_VECTOR DEPS)
+#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
+ (GRAPH).addInitializer((NAME), \
+ (FN), \
+ DeinitializerFunction(), \
+ MONGO_MAKE_STRING_VECTOR PREREQS, \
+ MONGO_MAKE_STRING_VECTOR DEPS)
#define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
ASSERT_EQUALS(Status::OK(), ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS))
diff --git a/src/mongo/base/initializer_function.h b/src/mongo/base/initializer_function.h
index 93575ef01e2..eacba7e6697 100644
--- a/src/mongo/base/initializer_function.h
+++ b/src/mongo/base/initializer_function.h
@@ -33,6 +33,7 @@
namespace mongo {
class InitializerContext;
+class DeinitializerContext;
/**
* An InitializerFunction implements the behavior of an initializer operation.
@@ -42,4 +43,13 @@ class InitializerContext;
*/
typedef stdx::function<Status(InitializerContext*)> InitializerFunction;
+/**
+* A DeinitializerFunction implements the behavior of a deinitializer operation.
+*
+* On successful execution, a DeinitializerFunction returns Status::OK(). It may
+* inspect and mutate the supplied DeinitializerContext.
+*/
+typedef stdx::function<Status(DeinitializerContext*)> DeinitializerFunction;
+
+
} // namespace mongo
diff --git a/src/mongo/base/initializer_test.cpp b/src/mongo/base/initializer_test.cpp
index 260d8d01ef0..9be5f0eb6f5 100644
--- a/src/mongo/base/initializer_test.cpp
+++ b/src/mongo/base/initializer_test.cpp
@@ -49,9 +49,12 @@
*
*/
-#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
- (GRAPH).addInitializer( \
- (NAME), (FN), MONGO_MAKE_STRING_VECTOR PREREQS, MONGO_MAKE_STRING_VECTOR DEPS)
+#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
+ (GRAPH).addInitializer((NAME), \
+ (FN), \
+ DeinitializerFunction(), \
+ MONGO_MAKE_STRING_VECTOR PREREQS, \
+ MONGO_MAKE_STRING_VECTOR DEPS)
#define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
ASSERT_EQUALS(Status::OK(), ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS))
@@ -157,8 +160,8 @@ TEST(InitializerTest, SuccessfulInitialization) {
set7,
set8);
clearCounts();
- ASSERT_OK(initializer.execute(InitializerContext::ArgumentVector(),
- InitializerContext::EnvironmentMap()));
+ ASSERT_OK(initializer.executeInitializers(InitializerContext::ArgumentVector(),
+ InitializerContext::EnvironmentMap()));
for (int i = 0; i < 9; ++i)
ASSERT_EQUALS(1, globalCounts[i]);
}
@@ -177,8 +180,8 @@ TEST(InitializerTest, Step5Misimplemented) {
set8);
clearCounts();
ASSERT_EQUALS(ErrorCodes::UnknownError,
- initializer.execute(InitializerContext::ArgumentVector(),
- InitializerContext::EnvironmentMap()));
+ initializer.executeInitializers(InitializerContext::ArgumentVector(),
+ InitializerContext::EnvironmentMap()));
ASSERT_EQUALS(1, globalCounts[0]);
ASSERT_EQUALS(1, globalCounts[1]);
ASSERT_EQUALS(1, globalCounts[2]);