summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gómez Ferro <daniel.gomezferro@mongodb.com>2022-02-15 14:44:11 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-15 16:26:43 +0000
commita5705b89f02a4cc1c3b1ce0eebc11e53fe668c5b (patch)
treeade8e8cf85852b669ddca7d7f87dfec85c0eb4b1
parenteeff4a62ad0702abfe3d599e16696baefc6c8cec (diff)
downloadmongo-a5705b89f02a4cc1c3b1ce0eebc11e53fe668c5b.tar.gz
SERVER-63651 Support non-monotonic clocks in PrepareConflictTracker
-rw-r--r--src/mongo/db/prepare_conflict_tracker.cpp8
-rw-r--r--src/mongo/util/tick_source.h14
-rw-r--r--src/mongo/util/tick_source_test.cpp14
3 files changed, 29 insertions, 7 deletions
diff --git a/src/mongo/db/prepare_conflict_tracker.cpp b/src/mongo/db/prepare_conflict_tracker.cpp
index 7dc8123e282..e8e031a1405 100644
--- a/src/mongo/db/prepare_conflict_tracker.cpp
+++ b/src/mongo/db/prepare_conflict_tracker.cpp
@@ -51,14 +51,8 @@ void PrepareConflictTracker::endPrepareConflict(OperationContext* opCtx) {
auto tickSource = opCtx->getServiceContext()->getTickSource();
auto curTick = tickSource->getTicks();
- invariant(_prepareConflictStartTime <= curTick,
- str::stream() << "Prepare conflict start time ("
- << tickSource->ticksTo<Microseconds>(_prepareConflictStartTime)
- << ") is somehow greater than current time ("
- << tickSource->ticksTo<Microseconds>(curTick) << ")");
-
auto curConflictDuration =
- tickSource->ticksTo<Microseconds>(curTick - _prepareConflictStartTime);
+ tickSource->spanTo<Microseconds>(_prepareConflictStartTime, curTick);
_prepareConflictDuration.store(_prepareConflictDuration.load() + curConflictDuration);
_prepareConflictStartTime = 0;
diff --git a/src/mongo/util/tick_source.h b/src/mongo/util/tick_source.h
index f77ea9d1d6f..5b0abc88aca 100644
--- a/src/mongo/util/tick_source.h
+++ b/src/mongo/util/tick_source.h
@@ -29,6 +29,7 @@
#pragma once
+#include <algorithm>
#include <cstdint>
namespace mongo {
@@ -64,5 +65,18 @@ public:
static_cast<double>(getTicksPerSecond()) * D::period::num / D::period::den;
return D(static_cast<int64_t>(ticks / ticksPerD));
}
+
+ /**
+ * Measures the length of the span from the start tick to the end tick and returns the result
+ * using duration type D.
+ * If the start tick is after (greater than) the end tick, returns a duration equivalent to 0
+ * ticks.
+ *
+ * e.g. tickSource->spanTo<Milliseconds>(start, end);
+ */
+ template <typename D>
+ D spanTo(Tick start, Tick end) {
+ return ticksTo<D>(std::max((end - start), Tick{0}));
+ }
};
} // namespace mongo
diff --git a/src/mongo/util/tick_source_test.cpp b/src/mongo/util/tick_source_test.cpp
index aef28a7e97c..cf08b69cbdc 100644
--- a/src/mongo/util/tick_source_test.cpp
+++ b/src/mongo/util/tick_source_test.cpp
@@ -52,5 +52,19 @@ TEST(TickSourceTest, TicksToDurationConversion) {
tsMicros.reset(1);
ASSERT_EQ(tsMicros.ticksTo<Microseconds>(tsMicros.getTicks()).count(), 1);
}
+
+TEST(TickSourceTest, SpansToDurationConversion) {
+ TickSourceMock<Seconds> tsSecs;
+ tsSecs.reset(0);
+ TickSource::Tick zero = tsSecs.getTicks();
+ tsSecs.reset(10);
+ TickSource::Tick ten = tsSecs.getTicks();
+ ASSERT_EQ(tsSecs.spanTo<Seconds>(zero, ten).count(), 10);
+ ASSERT_EQ(tsSecs.spanTo<Seconds>(ten, zero).count(), 0);
+ ASSERT_EQ(tsSecs.spanTo<Milliseconds>(zero, ten).count(), 10 * 1000);
+ ASSERT_EQ(tsSecs.spanTo<Milliseconds>(ten, zero).count(), 0);
+ ASSERT_EQ(tsSecs.spanTo<Microseconds>(zero, ten).count(), 10 * 1000 * 1000);
+ ASSERT_EQ(tsSecs.spanTo<Microseconds>(ten, zero).count(), 0);
+}
} // namespace
} // namespace mongo