diff options
author | William Schultz <william.schultz@mongodb.com> | 2017-03-21 15:17:59 -0400 |
---|---|---|
committer | William Schultz <william.schultz@mongodb.com> | 2017-03-30 18:05:42 -0400 |
commit | e77e2d54ab07f5d08580ea66e733b49372cf00e2 (patch) | |
tree | 6238951c0c6a91c4a22487348510d8965c4f5706 /src/mongo/db/logical_clock.cpp | |
parent | c20914d6739c8474e80646e461b8f5121f9758cf (diff) | |
download | mongo-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.cpp | 51 |
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) { |