diff options
author | Benety Goh <benety@mongodb.com> | 2018-04-23 13:40:09 -0400 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2018-04-23 13:41:42 -0400 |
commit | fc8096229e6ba7745431f77ec985eb65ee0541af (patch) | |
tree | 454f2cb064ddd4602d408a257aa37932235d2292 | |
parent | dba852d5d9cd0b3f067fd8d880e7e576db580653 (diff) | |
download | mongo-fc8096229e6ba7745431f77ec985eb65ee0541af.tar.gz |
SERVER-34364 add Status and StatusWith support to invariant()
-rw-r--r-- | src/mongo/util/assert_util.cpp | 21 | ||||
-rw-r--r-- | src/mongo/util/assert_util.h | 49 | ||||
-rw-r--r-- | src/mongo/util/assert_util_test.cpp | 42 | ||||
-rw-r--r-- | src/mongo/util/invariant.h | 43 |
4 files changed, 130 insertions, 25 deletions
diff --git a/src/mongo/util/assert_util.cpp b/src/mongo/util/assert_util.cpp index 7fda800f414..7ff79f092e0 100644 --- a/src/mongo/util/assert_util.cpp +++ b/src/mongo/util/assert_util.cpp @@ -106,7 +106,7 @@ NOINLINE_DECL void invariantFailed(const char* expr, const char* file, unsigned } NOINLINE_DECL void invariantFailedWithMsg(const char* expr, - const char* msg, + const std::string& msg, const char* file, unsigned line) noexcept { severe() << "Invariant failure " << expr << " " << msg << " " << file << ' ' << dec << line @@ -116,13 +116,6 @@ NOINLINE_DECL void invariantFailedWithMsg(const char* expr, std::abort(); } -NOINLINE_DECL void invariantFailedWithMsg(const char* expr, - const std::string& msg, - const char* file, - unsigned line) noexcept { - invariantFailedWithMsg(expr, msg.c_str(), file, line); -} - NOINLINE_DECL void invariantOKFailed(const char* expr, const Status& status, const char* file, @@ -134,6 +127,18 @@ NOINLINE_DECL void invariantOKFailed(const char* expr, std::abort(); } +NOINLINE_DECL void invariantOKFailedWithMsg(const char* expr, + const Status& status, + const std::string& msg, + const char* file, + unsigned line) noexcept { + severe() << "Invariant failure: " << expr << " " << msg << " resulted in status " + << redact(status) << " at " << file << ' ' << dec << line; + breakpoint(); + severe() << "\n\n***aborting after invariant() failure\n\n" << endl; + std::abort(); +} + NOINLINE_DECL void fassertFailedWithLocation(int msgid, const char* file, unsigned line) noexcept { severe() << "Fatal Assertion " << msgid << " at " << file << " " << dec << line; breakpoint(); diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h index 0859738392e..b3d91d71238 100644 --- a/src/mongo/util/assert_util.h +++ b/src/mongo/util/assert_util.h @@ -220,6 +220,11 @@ MONGO_COMPILER_NORETURN void invariantOKFailed(const char* expr, const Status& status, const char* file, unsigned line) noexcept; +MONGO_COMPILER_NORETURN void invariantOKFailedWithMsg(const char* expr, + const Status& status, + const std::string& msg, + const char* file, + unsigned line) noexcept; #define fassertFailed MONGO_fassertFailed #define MONGO_fassertFailed(...) ::mongo::fassertFailedWithLocation(__VA_ARGS__, __FILE__, __LINE__) @@ -449,6 +454,50 @@ inline void massertStatusOKWithLocation(const Status& status, const char* file, if (kDebugBuild) \ invariantOK(expression) +inline void invariantWithLocation(const Status& status, + const char* expr, + const char* file, + unsigned line) { + if (MONGO_unlikely(!status.isOK())) { + ::mongo::invariantOKFailed(expr, status, file, line); + } +} + +template <typename T> +inline T invariantWithLocation(StatusWith<T> sw, + const char* expr, + const char* file, + unsigned line) { + if (MONGO_unlikely(!sw.isOK())) { + ::mongo::invariantOKFailed(expr, sw.getStatus(), file, line); + } + return std::move(sw.getValue()); +} + +template <typename ContextExpr> +inline void invariantWithContextAndLocation(const Status& status, + const char* expr, + ContextExpr&& contextExpr, + const char* file, + unsigned line) { + if (MONGO_unlikely(!status.isOK())) { + ::mongo::invariantOKFailedWithMsg( + expr, status, std::forward<ContextExpr>(contextExpr)(), file, line); + } +} + +template <typename T, typename ContextExpr> +inline T invariantWithContextAndLocation(StatusWith<T> sw, + const char* expr, + ContextExpr&& contextExpr, + const char* file, + unsigned line) { + if (MONGO_unlikely(!sw.isOK())) { + ::mongo::invariantOKFailedWithMsg(expr, sw.getStatus(), contextExpr(), file, line); + } + return std::move(sw.getValue()); +} + // some special ids that we want to duplicate // > 10000 asserts diff --git a/src/mongo/util/assert_util_test.cpp b/src/mongo/util/assert_util_test.cpp index b4c3c4ab212..1405319e26e 100644 --- a/src/mongo/util/assert_util_test.cpp +++ b/src/mongo/util/assert_util_test.cpp @@ -290,6 +290,15 @@ DEATH_TEST(InvariantTerminationTest, invariant, "Invariant failure false " __FIL invariant(false); } +DEATH_TEST(InvariantTerminationTest, invariantOverload, "Terminating with invariant") { + invariant(Status(ErrorCodes::InternalError, "Terminating with invariant")); +} + +DEATH_TEST(InvariantTerminationTest, invariantStatusWithOverload, "Terminating with invariant") { + invariant(StatusWith<std::string>(ErrorCodes::InternalError, + "Terminating with invariantStatusWithOverload")); +} + DEATH_TEST(InvariantTerminationTest, invariantOK, "Terminating with invariantOK") { invariantOK(Status(ErrorCodes::InternalError, "Terminating with invariantOK")); } @@ -309,5 +318,38 @@ DEATH_TEST(InvariantTerminationTest, invariant(false, msg); } + +DEATH_TEST(InvariantTerminationTest, + invariantOverloadWithStringLiteralMsg, + "Terminating with string literal invariant message") { + invariant(Status(ErrorCodes::InternalError, "Terminating with invariant"), + "Terminating with string literal invariant message"); +} + +DEATH_TEST(InvariantTerminationTest, + invariantOverloadWithStdStringMsg, + "Terminating with std::string invariant message: 12345") { + const std::string msg = str::stream() << "Terminating with std::string invariant message: " + << 12345; + invariant(Status(ErrorCodes::InternalError, "Terminating with invariant"), msg); +} + +DEATH_TEST(InvariantTerminationTest, + invariantStatusWithOverloadWithStringLiteralMsg, + "Terminating with string literal invariant message") { + invariant(StatusWith<std::string>(ErrorCodes::InternalError, "Terminating with invariant"), + "Terminating with string literal invariant message"); +} + +DEATH_TEST(InvariantTerminationTest, + invariantStatusWithOverloadWithStdStringMsg, + "Terminating with std::string invariant message: 12345") { + const std::string msg = str::stream() << "Terminating with std::string invariant message: " + << 12345; + invariant(StatusWith<std::string>(ErrorCodes::InternalError, "Terminating with invariant"), + msg); +} + + } // namespace } // namespace mongo diff --git a/src/mongo/util/invariant.h b/src/mongo/util/invariant.h index edd2f210ce2..587eeb24f17 100644 --- a/src/mongo/util/invariant.h +++ b/src/mongo/util/invariant.h @@ -55,17 +55,18 @@ MONGO_COMPILER_NORETURN void invariantFailed(const char* expr, // // Invariant failure !condition some/file.cpp 528 // -#define MONGO_invariant_1(_Expression) \ - do { \ - if (MONGO_unlikely(!(_Expression))) { \ - ::mongo::invariantFailed(#_Expression, __FILE__, __LINE__); \ - } \ - } while (false) - -MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr, - const char* msg, - const char* file, - unsigned line) noexcept; +#define MONGO_invariant_1(Expression) \ + ::mongo::invariantWithLocation((Expression), #Expression, __FILE__, __LINE__) + +template <typename T> +inline void invariantWithLocation(const T& testOK, + const char* expr, + const char* file, + unsigned line) { + if (MONGO_unlikely(!testOK)) { + ::mongo::invariantFailed(expr, file, line); + } +} MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr, const std::string& msg, @@ -79,12 +80,20 @@ MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr, // // Invariant failure !condition "hello!" some/file.cpp 528 // -#define MONGO_invariant_2(_Expression, _Message) \ - do { \ - if (MONGO_unlikely(!(_Expression))) { \ - ::mongo::invariantFailedWithMsg(#_Expression, (_Message), __FILE__, __LINE__); \ - } \ - } while (false) +#define MONGO_invariant_2(Expression, contextExpr) \ + ::mongo::invariantWithContextAndLocation((Expression), \ + #Expression, \ + [&]() -> std::string { return (contextExpr); }, \ + __FILE__, \ + __LINE__) + +template <typename T, typename ContextExpr> +inline void invariantWithContextAndLocation( + const T& testOK, const char* expr, ContextExpr&& contextExpr, const char* file, unsigned line) { + if (MONGO_unlikely(!testOK)) { + ::mongo::invariantFailedWithMsg(expr, contextExpr(), file, line); + } +} // This helper macro is necessary to make the __VAR_ARGS__ expansion work properly on MSVC. #define MONGO_expand(x) x |