summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Saltz <matthew.saltz@mongodb.com>2018-12-06 17:58:28 -0500
committerCharlie Swanson <charlie.swanson@mongodb.com>2019-01-11 18:28:22 -0500
commitc48f6c22e5a8013bbcd6e08cb489b1e809dbbfed (patch)
treed10a9536e65d015c6014a6b5c0d7a093466ee01f
parenteef9ac3727d949d05f25d16ed3e6f87444e06838 (diff)
downloadmongo-c48f6c22e5a8013bbcd6e08cb489b1e809dbbfed.tar.gz
SERVER-38445 Fix Date_t addition with Duration
(cherry picked from commit d899a205ef66d916b071dd42fbb619775561a523)
-rw-r--r--src/mongo/db/s/collection_range_deleter.cpp4
-rw-r--r--src/mongo/db/s/collection_sharding_runtime.cpp4
-rw-r--r--src/mongo/db/session.cpp2
-rw-r--r--src/mongo/db/session_test.cpp4
-rw-r--r--src/mongo/util/time_support.h6
-rw-r--r--src/mongo/util/time_support_test.cpp36
6 files changed, 45 insertions, 11 deletions
diff --git a/src/mongo/db/s/collection_range_deleter.cpp b/src/mongo/db/s/collection_range_deleter.cpp
index c86d8630988..3832d495e88 100644
--- a/src/mongo/db/s/collection_range_deleter.cpp
+++ b/src/mongo/db/s/collection_range_deleter.cpp
@@ -288,7 +288,7 @@ boost::optional<Date_t> CollectionRangeDeleter::cleanUpNextRange(
<< redact(self->_orphans.front().range.toString()) << " next.";
}
- return Date_t::now() + stdx::chrono::milliseconds{rangeDeleterBatchDelayMS.load()};
+ return Date_t::now() + Milliseconds(rangeDeleterBatchDelayMS.load());
}
invariant(range);
@@ -296,7 +296,7 @@ boost::optional<Date_t> CollectionRangeDeleter::cleanUpNextRange(
invariant(wrote.getValue() > 0);
notification.abandon();
- return Date_t::now() + stdx::chrono::milliseconds{rangeDeleterBatchDelayMS.load()};
+ return Date_t::now() + Milliseconds(rangeDeleterBatchDelayMS.load());
}
bool CollectionRangeDeleter::_checkCollectionMetadataStillValid(
diff --git a/src/mongo/db/s/collection_sharding_runtime.cpp b/src/mongo/db/s/collection_sharding_runtime.cpp
index 473206d40d9..80a006c61bb 100644
--- a/src/mongo/db/s/collection_sharding_runtime.cpp
+++ b/src/mongo/db/s/collection_sharding_runtime.cpp
@@ -81,8 +81,8 @@ void CollectionShardingRuntime::forgetReceive(const ChunkRange& range) {
auto CollectionShardingRuntime::cleanUpRange(ChunkRange const& range, CleanWhen when)
-> CleanupNotification {
- Date_t time = (when == kNow) ? Date_t{} : Date_t::now() +
- stdx::chrono::seconds{orphanCleanupDelaySecs.load()};
+ Date_t time =
+ (when == kNow) ? Date_t{} : Date_t::now() + Seconds(orphanCleanupDelaySecs.load());
return _metadataManager->cleanUpRange(range, time);
}
diff --git a/src/mongo/db/session.cpp b/src/mongo/db/session.cpp
index b20f1141496..0dac6a9d2ce 100644
--- a/src/mongo/db/session.cpp
+++ b/src/mongo/db/session.cpp
@@ -629,7 +629,7 @@ void Session::_beginOrContinueTxn(WithLock wl,
const auto now = curTimeMicros64();
_transactionExpireDate = Date_t::fromMillisSinceEpoch(now / 1000) +
- stdx::chrono::seconds{transactionLifetimeLimitSeconds.load()};
+ Seconds{transactionLifetimeLimitSeconds.load()};
// Tracks various transactions metrics.
{
stdx::lock_guard<stdx::mutex> ls(_statsMutex);
diff --git a/src/mongo/db/session_test.cpp b/src/mongo/db/session_test.cpp
index ebfbf50b84a..6b23812169d 100644
--- a/src/mongo/db/session_test.cpp
+++ b/src/mongo/db/session_test.cpp
@@ -766,7 +766,7 @@ TEST_F(SessionTest, ReportStashedResources) {
ASSERT_EQ(
dateFromISOString(transactionDocument.getField("expiryTime").valueStringData()).getValue(),
Date_t::fromMillisSinceEpoch(session.getSingleTransactionStats()->getStartTime() / 1000) +
- stdx::chrono::seconds{transactionLifetimeLimitSeconds.load()});
+ Seconds{transactionLifetimeLimitSeconds.load()});
ASSERT_EQ(stashedState.getField("client").valueStringData().toString(), "");
ASSERT_EQ(stashedState.getField("connectionId").numberLong(), 0);
ASSERT_EQ(stashedState.getField("appName").valueStringData().toString(), "appName");
@@ -843,7 +843,7 @@ TEST_F(SessionTest, ReportUnstashedResources) {
ASSERT_EQ(
dateFromISOString(transactionDocument.getField("expiryTime").valueStringData()).getValue(),
Date_t::fromMillisSinceEpoch(session.getSingleTransactionStats()->getStartTime() / 1000) +
- stdx::chrono::seconds{transactionLifetimeLimitSeconds.load()});
+ Seconds{transactionLifetimeLimitSeconds.load()});
// For the following time metrics, we are only verifying that the transaction sub-document is
// being constructed correctly with proper types because we have other tests to verify that the
// values are being tracked correctly.
diff --git a/src/mongo/util/time_support.h b/src/mongo/util/time_support.h
index f42c81567c8..457ff516469 100644
--- a/src/mongo/util/time_support.h
+++ b/src/mongo/util/time_support.h
@@ -178,7 +178,7 @@ public:
template <typename Duration>
Date_t& operator+=(Duration d) {
- millis += duration_cast<Milliseconds>(d).count();
+ *this = *this + d;
return *this;
}
@@ -189,9 +189,7 @@ public:
template <typename Duration>
Date_t operator+(Duration d) const {
- Date_t result = *this;
- result += d;
- return result;
+ return Date_t::fromDurationSinceEpoch(toDurationSinceEpoch() + d);
}
template <typename Duration>
diff --git a/src/mongo/util/time_support_test.cpp b/src/mongo/util/time_support_test.cpp
index 0dcd341ae9a..b827da75867 100644
--- a/src/mongo/util/time_support_test.cpp
+++ b/src/mongo/util/time_support_test.cpp
@@ -857,5 +857,41 @@ TEST(SystemTime, ConvertDateToSystemTime) {
ASSERT_EQUALS(aDate, Date_t(aTimePoint));
}
+TEST(DateTArithmetic, AdditionNoOverflowSucceeds) {
+ auto dateFromMillis = [](long long ms) {
+ return Date_t::fromDurationSinceEpoch(Milliseconds{ms});
+ };
+
+ // Test operator+
+ ASSERT_EQ(dateFromMillis(1001), dateFromMillis(1000) + Milliseconds{1});
+ // Test operator+=
+ auto dateToIncrement = dateFromMillis(1000);
+ dateToIncrement += Milliseconds(1);
+ ASSERT_EQ(dateFromMillis(1001), dateToIncrement);
+}
+
+TEST(DateTArithmetic, AdditionOverflowThrows) {
+ // Test operator+
+ ASSERT_THROWS_CODE(Date_t::max() + Milliseconds(1), DBException, ErrorCodes::DurationOverflow);
+ // Test operator+=
+ auto dateToIncrement = Date_t::max();
+ ASSERT_THROWS_CODE(
+ dateToIncrement += Milliseconds(1), DBException, ErrorCodes::DurationOverflow);
+
+ // TODO (SERVER-38442): Can change Date_t::fromDurationSinceEpoch(Milliseconds::min()) to
+ // Date_t::min() once it's correct.
+ ASSERT_THROWS_CODE(Date_t::fromDurationSinceEpoch(Milliseconds::min()) + Milliseconds(-1),
+ DBException,
+ ErrorCodes::DurationOverflow);
+}
+
+TEST(DateTArithmetic, SubtractionOverflowThrows) {
+ // TODO (SERVER-38442): Can change Date_t::fromDurationSinceEpoch(Milliseconds::min()) to
+ // Date_t::min() once it's correct.
+ ASSERT_THROWS_CODE(Date_t::fromDurationSinceEpoch(Milliseconds::min()) - Milliseconds(1),
+ DBException,
+ ErrorCodes::DurationOverflow);
+ ASSERT_THROWS_CODE(Date_t::max() - Milliseconds(-1), DBException, ErrorCodes::DurationOverflow);
+}
} // namespace
} // namespace mongo