summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2019-02-22 16:17:42 -0500
committerJason Carey <jcarey@argv.me>2019-03-06 11:51:29 -0500
commit5926b6e06fec4f37e13740dc2eef8b5c7a806138 (patch)
tree217489bf4174dffd510320d243a4a199fc87911e
parent50f6bd4d6a9428a6f1df22db792d7b55d773762c (diff)
downloadmongo-5926b6e06fec4f37e13740dc2eef8b5c7a806138.tar.gz
SERVER-39688 Support namespaces for ErrorExtraInfo
Adds support for ErrorExtraInfo types that are not directly in the mongo namespace. I.e. something like mongo::nested::namespace::MyExtraInfo
-rw-r--r--src/mongo/base/error_codes.err1
-rw-r--r--src/mongo/base/error_codes.tpl.h8
-rw-r--r--src/mongo/base/error_extra_info.cpp20
-rw-r--r--src/mongo/base/error_extra_info.h35
-rw-r--r--src/mongo/base/generate_error_codes.py14
-rw-r--r--src/mongo/base/status_test.cpp18
6 files changed, 95 insertions, 1 deletions
diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err
index 068d3a15224..c5e6a5a698e 100644
--- a/src/mongo/base/error_codes.err
+++ b/src/mongo/base/error_codes.err
@@ -282,6 +282,7 @@ error_code("ChangeStreamFatalError", 280)
error_code("TransactionCoordinatorSteppingDown", 281) # Gets converted to InterruptedDueToStepDown
error_code("TransactionCoordinatorReachedAbortDecision", 282)
error_code("WouldChangeOwningShard", 283, extra="WouldChangeOwningShardInfo")
+error_code("ForTestingErrorExtraInfoWithExtraInfoInNamespace", 284, extra="nested::twice::NestedErrorExtraInfoExample")
# Error codes 4000-8999 are reserved.
diff --git a/src/mongo/base/error_codes.tpl.h b/src/mongo/base/error_codes.tpl.h
index 3f8d40c490d..b2c0ea617ba 100644
--- a/src/mongo/base/error_codes.tpl.h
+++ b/src/mongo/base/error_codes.tpl.h
@@ -43,7 +43,13 @@ class Status;
// ErrorExtraInfo subclasses:
//#for $ec in $codes:
//#if $ec.extra
-class $ec.extra;
+//#if $ec.extra_ns
+namespace $ec.extra_ns {
+ //#end if
+ class $ec.extra_class;
+ //#if $ec.extra_ns
+} // namespace $ec.extra_ns
+//#end if
//#end if
//#end for
diff --git a/src/mongo/base/error_extra_info.cpp b/src/mongo/base/error_extra_info.cpp
index 5c844bb4b8c..822904464c7 100644
--- a/src/mongo/base/error_extra_info.cpp
+++ b/src/mongo/base/error_extra_info.cpp
@@ -51,4 +51,24 @@ std::shared_ptr<const ErrorExtraInfo> ErrorExtraInfoExample::parse(const BSONObj
MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(ErrorExtraInfoExample);
+namespace nested::twice {
+
+bool NestedErrorExtraInfoExample::isParserEnabledForTest = false;
+
+void NestedErrorExtraInfoExample::serialize(BSONObjBuilder* builder) const {
+ builder->append("data", data);
+}
+
+std::shared_ptr<const ErrorExtraInfo> NestedErrorExtraInfoExample::parse(const BSONObj& obj) {
+ uassert(51100,
+ "ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace is only for testing",
+ isParserEnabledForTest);
+
+ return std::make_shared<NestedErrorExtraInfoExample>(obj["data"].Int());
+}
+
+MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(NestedErrorExtraInfoExample);
+
+} // namespace nested::twice
+
} // namespace mongo
diff --git a/src/mongo/base/error_extra_info.h b/src/mongo/base/error_extra_info.h
index bcaca9e890e..8f6bd54df1f 100644
--- a/src/mongo/base/error_extra_info.h
+++ b/src/mongo/base/error_extra_info.h
@@ -137,4 +137,39 @@ public:
private:
static bool isParserEnabledForTest;
};
+
+namespace nested::twice {
+
+/**
+ * This is an example ErrorExtraInfo subclass. It is used for testing the ErrorExtraInfoHandling.
+ *
+ * It is meant to be a duplicate of ErrorExtraInfoExample, except that it is within a namespace
+ * (and so exercises a different codepath in the parser).
+ */
+class NestedErrorExtraInfoExample final : public ErrorExtraInfo {
+public:
+ static constexpr auto code = ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace;
+
+ void serialize(BSONObjBuilder*) const override;
+ static std::shared_ptr<const ErrorExtraInfo> parse(const BSONObj&);
+
+ // Everything else in this class is just for testing and shouldn't by copied by users.
+
+ struct EnableParserForTest {
+ EnableParserForTest() {
+ isParserEnabledForTest = true;
+ }
+ ~EnableParserForTest() {
+ isParserEnabledForTest = false;
+ }
+ };
+
+ NestedErrorExtraInfoExample(int data) : data(data) {}
+ int data; // This uses the fieldname "data".
+private:
+ static bool isParserEnabledForTest;
+};
+
+} // namespace nested::twice
+
} // namespace mongo
diff --git a/src/mongo/base/generate_error_codes.py b/src/mongo/base/generate_error_codes.py
index a26627fd06d..57b88957dde 100644
--- a/src/mongo/base/generate_error_codes.py
+++ b/src/mongo/base/generate_error_codes.py
@@ -66,6 +66,20 @@ class ErrorCode:
self.name = name
self.code = code
self.extra = extra
+ if extra:
+ split = extra.split('::')
+ if not split[0]:
+ die("Error for %s with extra info %s: fully qualified namespaces aren't supported"
+ % (name, extra))
+ if split[0] == "mongo":
+ die("Error for %s with extra info %s: don't include the mongo namespace"
+ % (name, extra))
+ if len(split) > 1:
+ self.extra_class = split.pop()
+ self.extra_ns = "::".join(split)
+ else:
+ self.extra_class = extra
+ self.extra_ns = None
self.categories = []
class ErrorClass:
diff --git a/src/mongo/base/status_test.cpp b/src/mongo/base/status_test.cpp
index 5bc73efbdcf..eeff3daae91 100644
--- a/src/mongo/base/status_test.cpp
+++ b/src/mongo/base/status_test.cpp
@@ -319,5 +319,23 @@ TEST(ErrorExtraInfo, StatusParserWorks) {
ASSERT_EQ(status.extraInfo<ErrorExtraInfoExample>()->data, 123);
}
+TEST(ErrorExtraInfo, StatusParserWorksNested) {
+ nested::twice::NestedErrorExtraInfoExample::EnableParserForTest whenInScope;
+ auto status = Status(
+ ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace, "", fromjson("{data: 123}"));
+ ASSERT_EQ(status, ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace);
+ ASSERT(status.extraInfo());
+ ASSERT(status.extraInfo<nested::twice::NestedErrorExtraInfoExample>());
+ ASSERT_EQ(status.extraInfo<nested::twice::NestedErrorExtraInfoExample>()->data, 123);
+}
+
+TEST(ErrorExtraInfo, StatusWhenParserThrowsNested) {
+ auto status = Status(
+ ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace, "", fromjson("{data: 123}"));
+ ASSERT_EQ(status, ErrorCodes::duplicateCodeForTest(51100));
+ ASSERT(!status.extraInfo());
+ ASSERT(!status.extraInfo<nested::twice::NestedErrorExtraInfoExample>());
+}
+
} // namespace
} // namespace mongo