diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2018-02-27 09:47:29 -0500 |
---|---|---|
committer | Henrik Edin <henrik.edin@mongodb.com> | 2018-03-12 10:57:28 -0400 |
commit | 0486c9ff50402c8680d14a495c2d9dfe543939a1 (patch) | |
tree | ae6959309757d62c055a2f6cecbc8532aba17400 /src/mongo/base | |
parent | d7012b42d747b498dc06747240c79f576425bbc6 (diff) | |
download | mongo-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.cpp | 30 | ||||
-rw-r--r-- | src/mongo/base/deinitializer_context.h | 51 | ||||
-rw-r--r-- | src/mongo/base/global_initializer_registerer.cpp | 16 | ||||
-rw-r--r-- | src/mongo/base/global_initializer_registerer.h | 202 | ||||
-rw-r--r-- | src/mongo/base/init.h | 8 | ||||
-rw-r--r-- | src/mongo/base/initializer.cpp | 50 | ||||
-rw-r--r-- | src/mongo/base/initializer.h | 17 | ||||
-rw-r--r-- | src/mongo/base/initializer_dependency_graph.cpp | 30 | ||||
-rw-r--r-- | src/mongo/base/initializer_dependency_graph.h | 43 | ||||
-rw-r--r-- | src/mongo/base/initializer_dependency_graph_test.cpp | 9 | ||||
-rw-r--r-- | src/mongo/base/initializer_function.h | 10 | ||||
-rw-r--r-- | src/mongo/base/initializer_test.cpp | 17 |
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]); |