summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorADAM David Alan Martin <adam.martin@10gen.com>2018-05-23 18:26:42 -0400
committerADAM David Alan Martin <adam.martin@10gen.com>2018-05-23 18:37:44 -0400
commit56c53c382daef891ac0951464e5e23ccdd5c0263 (patch)
tree7ab7ca94df97dab433a3edae58391b2356030a23
parentf8697053fc39ade3ac2e9368d466d01b4587caee (diff)
downloadmongo-56c53c382daef891ac0951464e5e23ccdd5c0263.tar.gz
SERVER-34944 Create a shim-override mechanism.
Modules for MongoDB need to be able to indicate their own overrides of shimmed funcitons. These overrides must be able to access the underlying registered shim. Further, the overrides must be installed in the correct position in the initializer dependency graph. (cherry picked from commit bad5afd612e8fc917fb035d8333cffd7d68a37cc)
-rw-r--r--src/mongo/base/shim.h66
-rw-r--r--src/mongo/db/auth/authorization_manager_global.cpp5
-rw-r--r--src/mongo/db/catalog/SConscript7
3 files changed, 70 insertions, 8 deletions
diff --git a/src/mongo/base/shim.h b/src/mongo/base/shim.h
index a782109d24d..14de94df7c8 100644
--- a/src/mongo/base/shim.h
+++ b/src/mongo/base/shim.h
@@ -193,6 +193,15 @@ const bool checkShimsViaTUHook = false;
} \
}
+
+/**
+ * Evaluates to a string which represents the `MONGO_INITIALIZER` step name in which this specific
+ * shim is registered. This can be useful to make sure that some initializers depend upon a shim's
+ * execution and presence in a binary.
+ */
+#define MONGO_SHIM_DEPENDENCY(...) MONGO_SHIM_EVIL_STRINGIFY_(__VA_ARGS__)
+#define MONGO_SHIM_EVIL_STRINGIFY_(args) #args
+
/**
* Define a shimmable function with name `SHIM_NAME`, returning a value of type `RETURN_TYPE`, with
* any arguments. This shim definition macro should go in the associated C++ file to the header
@@ -205,20 +214,25 @@ const bool checkShimsViaTUHook = false;
namespace { \
namespace shim_namespace##LN { \
using ShimType = decltype(__VA_ARGS__); \
+ ::mongo::Status initializerGroupStartup(::mongo::InitializerContext*) { \
+ return Status::OK(); \
+ } \
+ ::mongo::GlobalInitializerRegisterer _mongoInitializerRegisterer( \
+ std::string(MONGO_SHIM_DEPENDENCY(__VA_ARGS__)), \
+ {}, \
+ {MONGO_SHIM_DEPENDENTS}, \
+ mongo::InitializerFunction(initializerGroupStartup)); \
} /*namespace shim_namespace*/ \
} /*namespace*/ \
shim_namespace##LN::ShimType::MongoShimImplGuts::LibTUHookTypeBase::LibTUHookTypeBase() = \
default; \
shim_namespace##LN::ShimType __VA_ARGS__{};
-#define MONGO_SHIM_EVIL_STRINGIFY_(args) #args
-
-
/**
* Define an implementation of a shimmable function with name `SHIM_NAME`. The compiler will check
* supplied parameters for correctness. This shim registration macro should go in the associated
* C++ implementation file to the header where a SHIM was defined. Such a file would be a mock
- * implementation or a real implementation, for example
+ * implementation or a real implementation, for example.
*/
#define MONGO_REGISTER_SHIM(/*SHIM_NAME*/...) MONGO_REGISTER_SHIM_1(__LINE__, __VA_ARGS__)
#define MONGO_REGISTER_SHIM_1(LN, ...) MONGO_REGISTER_SHIM_2(LN, __VA_ARGS__)
@@ -240,9 +254,9 @@ const bool checkShimsViaTUHook = false;
} \
\
const ::mongo::GlobalInitializerRegisterer registrationHook{ \
- std::string(MONGO_SHIM_EVIL_STRINGIFY_(__VA_ARGS__)), \
+ std::string(MONGO_SHIM_DEPENDENCY(__VA_ARGS__) "_registration"), \
{}, \
- {MONGO_SHIM_DEPENDENTS}, \
+ {MONGO_SHIM_DEPENDENCY(__VA_ARGS__), MONGO_SHIM_DEPENDENTS}, \
mongo::InitializerFunction(createInitializerRegistration)}; \
} /*namespace shim_namespace*/ \
} /*namespace*/ \
@@ -255,3 +269,43 @@ const bool checkShimsViaTUHook = false;
and return value (using arrow \
notation). Then they write the \
body. */
+
+/**
+ * Define an overriding implementation of a shimmable function with `SHIM_NAME`. The compiler will
+ * check the supplied parameters for correctness. This shim override macro should go in the
+ * associated C++ implementation file to the header where a SHIM was defined. Such a file
+ * specifying an override would be a C++ implementation used by a mongodb extension module.
+ * This creates a runtime dependency upon the original registration being linked in.
+ */
+#define MONGO_OVERRIDE_SHIM(/*SHIM_NAME*/...) MONGO_OVERRIDE_SHIM_1(__LINE__, __VA_ARGS__)
+#define MONGO_OVERRIDE_SHIM_1(LN, ...) MONGO_OVERRIDE_SHIM_2(LN, __VA_ARGS__)
+#define MONGO_OVERRIDE_SHIM_2(LN, ...) \
+ namespace { \
+ namespace shim_namespace##LN { \
+ using ShimType = decltype(__VA_ARGS__); \
+ \
+ class OverrideImplementation final : public ShimType::MongoShimImplGuts { \
+ /* Some compilers don't work well with the trailing `override` in this kind of \
+ * function declaration. */ \
+ ShimType::MongoShimImplGuts::function_type implementation; /* override */ \
+ }; \
+ \
+ ::mongo::Status createInitializerOverride(::mongo::InitializerContext* const) { \
+ static OverrideImplementation overrideImpl; \
+ ShimType::storage::data = &overrideImpl; \
+ return Status::OK(); \
+ } \
+ \
+ const ::mongo::GlobalInitializerRegisterer overrideHook{ \
+ std::string(MONGO_SHIM_DEPENDENCY(__VA_ARGS__) "_override"), \
+ {MONGO_SHIM_DEPENDENCY( \
+ __VA_ARGS__) "_registration"}, /* Override happens after first registration */ \
+ {MONGO_SHIM_DEPENDENCY(__VA_ARGS__), /* Provides impl for this shim */ \
+ MONGO_SHIM_DEPENDENTS}, /* Still a shim registration */ \
+ mongo::InitializerFunction(createInitializerOverride)}; \
+ } /*namespace shim_namespace*/ \
+ } /*namespace*/ \
+ \
+ auto shim_namespace##LN::OverrideImplementation:: \
+ implementation /* After this point someone just writes the signature's arguments and \
+ return value (using arrow notation). Then they write the body. */
diff --git a/src/mongo/db/auth/authorization_manager_global.cpp b/src/mongo/db/auth/authorization_manager_global.cpp
index b626c3b5573..3f8a8808d04 100644
--- a/src/mongo/db/auth/authorization_manager_global.cpp
+++ b/src/mongo/db/auth/authorization_manager_global.cpp
@@ -93,7 +93,10 @@ MONGO_EXPORT_STARTUP_SERVER_PARAMETER(startupAuthSchemaValidation, bool, true);
GlobalInitializerRegisterer authorizationManagerInitializer(
"CreateAuthorizationManager",
- {"OIDGeneration", "EndStartupOptionStorage", "ServiceContext"},
+ {MONGO_SHIM_DEPENDENCY(AuthorizationManager::create),
+ "OIDGeneration",
+ "EndStartupOptionStorage",
+ "ServiceContext"},
[](InitializerContext* context) {
auto authzManager = AuthorizationManager::create();
authzManager->setAuthEnabled(serverGlobalParams.authState ==
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript
index 259ea12ab77..5ced8ff384b 100644
--- a/src/mongo/db/catalog/SConscript
+++ b/src/mongo/db/catalog/SConscript
@@ -103,6 +103,7 @@ env.Library(
"index_catalog.cpp",
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
],
)
@@ -112,6 +113,7 @@ env.Library(
"index_catalog_entry.cpp",
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
],
)
@@ -158,9 +160,10 @@ env.CppUnitTest(
env.Library(
target='database_holder',
source=[
- "database_holder.cpp",
+ 'database_holder.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
],
)
@@ -170,6 +173,7 @@ env.Library(
'collection_info_cache.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
],
)
@@ -179,6 +183,7 @@ env.Library(
'index_create.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
],
)