summaryrefslogtreecommitdiff
path: root/src/mongo/db/logical_clock.cpp
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2017-03-21 15:17:59 -0400
committerWilliam Schultz <william.schultz@mongodb.com>2017-03-30 18:05:42 -0400
commite77e2d54ab07f5d08580ea66e733b49372cf00e2 (patch)
tree6238951c0c6a91c4a22487348510d8965c4f5706 /src/mongo/db/logical_clock.cpp
parentc20914d6739c8474e80646e461b8f5121f9758cf (diff)
downloadmongo-e77e2d54ab07f5d08580ea66e733b49372cf00e2.tar.gz
SERVER-28352 Fix ticks increment in LogicalClock::reserveTicks
Diffstat (limited to 'src/mongo/db/logical_clock.cpp')
-rw-r--r--src/mongo/db/logical_clock.cpp51
1 files changed, 32 insertions, 19 deletions
diff --git a/src/mongo/db/logical_clock.cpp b/src/mongo/db/logical_clock.cpp
index 6f0e4c55574..4cdd3177d26 100644
--- a/src/mongo/db/logical_clock.cpp
+++ b/src/mongo/db/logical_clock.cpp
@@ -140,35 +140,48 @@ Status LogicalClock::signAndAdvanceClusterTime(LogicalTime newTime) {
return _advanceClusterTime_inlock(std::move(newSignedTime));
}
-LogicalTime LogicalClock::reserveTicks(uint64_t ticks) {
+LogicalTime LogicalClock::reserveTicks(uint64_t nTicks) {
- invariant(ticks > 0);
+ invariant(nTicks > 0 && nTicks < (1U << 31));
stdx::lock_guard<stdx::mutex> lock(_mutex);
+ LogicalTime clusterTime = _clusterTime.getTime();
+ LogicalTime nextClusterTime;
+
const unsigned wallClockSecs =
durationCount<Seconds>(_service->getFastClockSource()->now().toDurationSinceEpoch());
- unsigned currentSecs = _clusterTime.getTime().asTimestamp().getSecs();
- LogicalTime clusterTimestamp = _clusterTime.getTime();
+ unsigned clusterTimeSecs = clusterTime.asTimestamp().getSecs();
- if (MONGO_unlikely(currentSecs < wallClockSecs)) {
- clusterTimestamp = LogicalTime(Timestamp(wallClockSecs, 1));
- } else {
- clusterTimestamp.addTicks(1);
+ // Synchronize clusterTime with wall clock time, if clusterTime was behind in seconds.
+ if (clusterTimeSecs < wallClockSecs) {
+ clusterTime = LogicalTime(Timestamp(wallClockSecs, 0));
+ }
+ // If reserving 'nTicks' would force the cluster timestamp's increment field to exceed (2^31-1),
+ // overflow by moving to the next second. We use the signed integer maximum as an overflow point
+ // in order to preserve compatibility with potentially signed or unsigned integral Timestamp
+ // increment types. It is also unlikely to apply more than 2^31 oplog entries in the span of one
+ // second.
+ else if (clusterTime.asTimestamp().getInc() >= ((1U << 31) - nTicks)) {
+
+ log() << "Exceeded maximum allowable increment value within one second. Moving clusterTime "
+ "forward to the next second.";
+
+ // Move time forward to the next second
+ clusterTime = LogicalTime(Timestamp(clusterTime.asTimestamp().getSecs() + 1, 0));
}
- auto currentTime = clusterTimestamp;
- clusterTimestamp.addTicks(ticks - 1);
-
- // Fail if time is not moving forward for 2**31 ticks
- if (MONGO_unlikely(clusterTimestamp.asTimestamp().getSecs() > wallClockSecs) &&
- clusterTimestamp.asTimestamp().getInc() >= 1U << 31) {
- mongo::severe() << "clock skew detected, prev: " << wallClockSecs
- << " now: " << clusterTimestamp.asTimestamp().getSecs();
- fassertFailed(17449);
+
+ // Save the next cluster time.
+ clusterTime.addTicks(1);
+ nextClusterTime = clusterTime;
+
+ // Add the rest of the requested ticks if needed.
+ if (nTicks > 1) {
+ clusterTime.addTicks(nTicks - 1);
}
- _clusterTime = _makeSignedLogicalTime(clusterTimestamp);
- return currentTime;
+ _clusterTime = _makeSignedLogicalTime(clusterTime);
+ return nextClusterTime;
}
void LogicalClock::initClusterTimeFromTrustedSource(LogicalTime newTime) {