diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2020-09-22 12:12:04 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-29 22:37:24 +0000 |
commit | d47784296374ed335d07c895820fdf8066e538e3 (patch) | |
tree | 9b73e13655d7135fda7de71de46c68bab6fcee7d /src/mongo/db/ftdc | |
parent | 1399e3ad7248ceb191dfbced2fb785a4a4170f63 (diff) | |
download | mongo-d47784296374ed335d07c895820fdf8066e538e3.tar.gz |
SERVER-50662 Handle large and non-finite doubles in FTDC
Diffstat (limited to 'src/mongo/db/ftdc')
-rw-r--r-- | src/mongo/db/ftdc/compressor_test.cpp | 41 | ||||
-rw-r--r-- | src/mongo/db/ftdc/util.cpp | 20 |
2 files changed, 60 insertions, 1 deletions
diff --git a/src/mongo/db/ftdc/compressor_test.cpp b/src/mongo/db/ftdc/compressor_test.cpp index 509504037b7..f8dee52f889 100644 --- a/src/mongo/db/ftdc/compressor_test.cpp +++ b/src/mongo/db/ftdc/compressor_test.cpp @@ -170,6 +170,11 @@ public: ValidateDocumentList(list, _docs, _mode); } + void setExpectedDocuments(const std::vector<BSONObj>& docs) { + _docs.clear(); + std::copy(docs.begin(), docs.end(), std::back_inserter(_docs)); + } + private: std::vector<BSONObj> _docs; FTDCConfig _config; @@ -537,4 +542,40 @@ TEST_F(FTDCCompressorTest, TestManyMetrics) { } } +// Test various non-finite double values +TEST_F(FTDCCompressorTest, TestDoubleValues) { + TestTie c; + + auto st = c.addSample(BSON("d" << 0.0)); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << -42.0)); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << 42.0)); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << std::numeric_limits<double>::max())); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << std::numeric_limits<double>::min())); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << std::numeric_limits<double>::lowest())); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << std::numeric_limits<double>::infinity())); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << -std::numeric_limits<double>::infinity())); + ASSERT_HAS_SPACE(st); + st = c.addSample(BSON("d" << std::numeric_limits<double>::quiet_NaN())); + ASSERT_HAS_SPACE(st); + + c.setExpectedDocuments({ + BSON("d" << 0.0), + BSON("d" << -42.0), + BSON("d" << 42.0), + BSON("d" << std::numeric_limits<long long>::max()), + BSON("d" << 0), + BSON("d" << std::numeric_limits<long long>::min()), + BSON("d" << std::numeric_limits<long long>::max()), + BSON("d" << std::numeric_limits<long long>::min()), + BSON("d" << 0), + }); +} + } // namespace mongo diff --git a/src/mongo/db/ftdc/util.cpp b/src/mongo/db/ftdc/util.cpp index 39cf8fa343e..e3b52800c03 100644 --- a/src/mongo/db/ftdc/util.cpp +++ b/src/mongo/db/ftdc/util.cpp @@ -222,7 +222,25 @@ StatusWith<bool> extractMetricsFromDocument(const BSONObj& referenceDoc, // all numeric types are extracted as long (int64) // this supports the loose schema matching mentioned above, // but does create a range issue for doubles, and requires doubles to be integer - case NumberDouble: + // Doubles and Decimal that fall out of the range of int64 are converted to: + // NaN -> 0 + // Inf -> MAX + // -Inf -> MIN + case NumberDouble: { + double value = currentElement.numberDouble(); + long long newValue = 0; + if (std::isnan(value)) { + newValue = 0; + } else if (!(value < BSONElement::kLongLongMaxPlusOneAsDouble)) { + newValue = std::numeric_limits<long long>::max(); + } else if (value < std::numeric_limits<long long>::min()) { + newValue = std::numeric_limits<long long>::min(); + } else { + newValue = static_cast<long long>(value); + } + metrics->emplace_back(newValue); + break; + } case NumberInt: case NumberLong: case NumberDecimal: |