diff options
Diffstat (limited to 'src/mongo')
26 files changed, 234 insertions, 174 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 91f6b2118bd..5aa01462143 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -243,17 +243,6 @@ env.CppUnitTest( ) env.Library( - target='global_timestamp', - source=[ - 'global_timestamp.cpp', - ], - LIBDEPS=[ - '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/db/service_context' - ] -) - -env.Library( target='namespace_string', source=[ 'namespace_string.cpp', @@ -881,7 +870,6 @@ env.Library( "exec/working_set", "fts/ftsmongod", "ftdc/ftdc_mongod", - "global_timestamp", "index/index_descriptor", "index/index_access_methods", "index_d", @@ -992,6 +980,19 @@ env.CppUnitTest( ) env.Library( + target= 'logical_clock_test_fixture', + source= [ + 'logical_clock_test_fixture.cpp', + ], + LIBDEPS= [ + 'service_context', + 'logical_clock', + 'signed_logical_time', + '$BUILD_DIR/mongo/unittest/unittest', + ], +) + +env.Library( target= 'op_observer_noop', source= [ 'op_observer_noop.cpp', diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp index 0381d462f56..4bedfe06e01 100644 --- a/src/mongo/db/commands/getmore_cmd.cpp +++ b/src/mongo/db/commands/getmore_cmd.cpp @@ -43,7 +43,6 @@ #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/working_set_common.h" -#include "mongo/db/global_timestamp.h" #include "mongo/db/query/cursor_response.h" #include "mongo/db/query/find.h" #include "mongo/db/query/find_common.h" diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 89b4360de91..c89eaa62cb7 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -74,6 +74,7 @@ #include "mongo/db/introspect.h" #include "mongo/db/json.h" #include "mongo/db/log_process_details.h" +#include "mongo/db/logical_clock.h" #include "mongo/db/mongod_options.h" #include "mongo/db/op_observer_impl.h" #include "mongo/db/operation_context.h" @@ -892,6 +893,10 @@ MONGO_INITIALIZER_WITH_PREREQUISITES(CreateReplicationManager, topoCoordOptions.maxSyncSourceLagSecs = Seconds(repl::maxSyncSourceLagSecs); topoCoordOptions.clusterRole = serverGlobalParams.clusterRole; + auto timeProofService = stdx::make_unique<TimeProofService>(); + auto logicalClock = + stdx::make_unique<LogicalClock>(serviceContext, std::move(timeProofService), false); + LogicalClock::set(serviceContext, std::move(logicalClock)); auto replCoord = stdx::make_unique<repl::ReplicationCoordinatorImpl>( serviceContext, getGlobalReplSettings(), diff --git a/src/mongo/db/global_timestamp.cpp b/src/mongo/db/global_timestamp.cpp deleted file mode 100644 index 0dbb6c2cf6b..00000000000 --- a/src/mongo/db/global_timestamp.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (C) 2014 MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - -#include "mongo/platform/basic.h" - -#include "mongo/db/global_timestamp.h" -#include "mongo/db/service_context.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/util/clock_source.h" -#include "mongo/util/log.h" -#include "mongo/util/time_support.h" - -namespace mongo { -namespace { -// This is the value of the next timestamp to handed out. -AtomicUInt64 globalTimestamp(0); -} // namespace - -void setGlobalTimestamp(ServiceContext* service, const Timestamp& newTime) { - // TODO: SERVER-27746 replace with LogicalTime - globalTimestamp.store(newTime.asULL() + 1); -} - -Timestamp getLastSetTimestamp() { - return Timestamp(globalTimestamp.load() - 1); -} - -Timestamp getNextGlobalTimestamp(ServiceContext* service, unsigned count) { - // TODO: SERVER-27746 replace with LogicalTime - const unsigned now = durationCount<Seconds>( - getGlobalServiceContext()->getFastClockSource()->now().toDurationSinceEpoch()); - invariant(now != 0); // This is a sentinel value for null Timestamps. - invariant(count != 0); - - // Optimistic approach: just increment the timestamp, assuming the seconds still match. - auto first = globalTimestamp.fetchAndAdd(count); - auto currentTimestamp = first + count; // What we just set it to. - unsigned globalSecs = Timestamp(currentTimestamp).getSecs(); - - // Fail if time is not moving forward for 2**31 calls to getNextGlobalTimestamp. - if (MONGO_unlikely(globalSecs > now) && Timestamp(currentTimestamp).getInc() >= 1U << 31) { - mongo::severe() << "clock skew detected, prev: " << globalSecs << " now: " << now; - fassertFailed(17449); - } - - // If the seconds need to be updated, try to do it. This can happen at most once per second. - if (MONGO_unlikely(globalSecs < now)) { - // First fix the seconds portion. - while (globalSecs < now) { - const auto desired = Timestamp(now, 1).asULL(); - - auto actual = globalTimestamp.compareAndSwap(currentTimestamp, desired); - if (actual == currentTimestamp) - break; // We successfully set the secs, so we're done here. - - // We raced with someone else. Try again, unless they fixed the secs field for us. - currentTimestamp = actual; - globalSecs = Timestamp(currentTimestamp).getSecs(); - } - - // Now reserve our timestamps with the new value of secs. - first = globalTimestamp.fetchAndAdd(count); - } - - return Timestamp(first); -} -} // namespace mongo diff --git a/src/mongo/db/logical_clock.cpp b/src/mongo/db/logical_clock.cpp index ad61792045b..6aeef259528 100644 --- a/src/mongo/db/logical_clock.cpp +++ b/src/mongo/db/logical_clock.cpp @@ -26,13 +26,17 @@ * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault + +#include "mongo/platform/basic.h" + #include "mongo/db/logical_clock.h" #include "mongo/base/status.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" #include "mongo/db/time_proof_service.h" -#include "mongo/platform/basic.h" +#include "mongo/util/log.h" namespace mongo { @@ -85,6 +89,16 @@ Status LogicalClock::advanceClusterTime(const SignedLogicalTime& newTime) { return Status::OK(); } +Status LogicalClock::advanceClusterTimeFromTrustedSource(LogicalTime newTime) { + stdx::lock_guard<stdx::mutex> lock(_mutex); + // TODO: rate check per SERVER-27721 + if (newTime > _clusterTime.getTime()) { + _clusterTime = _makeSignedLogicalTime(newTime); + } + + return Status::OK(); +} + LogicalTime LogicalClock::reserveTicks(uint64_t ticks) { invariant(ticks > 0); @@ -104,6 +118,14 @@ LogicalTime LogicalClock::reserveTicks(uint64_t ticks) { 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); + } + _clusterTime = _makeSignedLogicalTime(clusterTimestamp); return currentTime; } diff --git a/src/mongo/db/logical_clock.h b/src/mongo/db/logical_clock.h index 57d8dc4b80b..ffb78848986 100644 --- a/src/mongo/db/logical_clock.h +++ b/src/mongo/db/logical_clock.h @@ -63,7 +63,12 @@ public: * Returns an error if the newTime does not pass the rate check or proof validation, * OK otherwise. */ - Status advanceClusterTime(const SignedLogicalTime& newTime); + Status advanceClusterTime(const SignedLogicalTime&); + + /** + * Simliar to advaneClusterTime, but only does rate checking and not proof validation. + */ + Status advanceClusterTimeFromTrustedSource(LogicalTime); /** * Returns the current clusterTime. @@ -74,7 +79,7 @@ public: * Returns the next clusterTime value and provides the guarantee that the next reserveTicks * call will return the value at least nTicks ticks in the future from the current clusterTime. */ - LogicalTime reserveTicks(uint64_t nTicks = 1); + LogicalTime reserveTicks(uint64_t nTicks); /** * Resets _clusterTime to the signed time created from newTime. Should be used at the diff --git a/src/mongo/db/logical_clock_test_fixture.cpp b/src/mongo/db/logical_clock_test_fixture.cpp new file mode 100644 index 00000000000..64cf8182f22 --- /dev/null +++ b/src/mongo/db/logical_clock_test_fixture.cpp @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2017 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/db/logical_clock_test_fixture.h" + +#include "mongo/db/logical_clock.h" +#include "mongo/db/service_context.h" +#include "mongo/db/time_proof_service.h" +#include "mongo/stdx/memory.h" + +namespace mongo { + +void LogicalClockTest::setUp() { + auto service = getGlobalServiceContext(); + + auto timeProofService = stdx::make_unique<TimeProofService>(); + auto logicalClock = + stdx::make_unique<LogicalClock>(service, std::move(timeProofService), false); + LogicalClock::set(service, std::move(logicalClock)); +} + +} // namespace mongo diff --git a/src/mongo/db/global_timestamp.h b/src/mongo/db/logical_clock_test_fixture.h index 408d38a6aae..e304e3a5611 100644 --- a/src/mongo/db/global_timestamp.h +++ b/src/mongo/db/logical_clock_test_fixture.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 MongoDB, Inc. + * Copyright (C) 2017 MongoDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, @@ -28,21 +28,22 @@ #pragma once -#include "mongo/bson/timestamp.h" +#include "mongo/unittest/unittest.h" namespace mongo { -class ServiceContext; - -void setGlobalTimestamp(ServiceContext* service, const Timestamp& newTime); - /** - * Returns the value of the global Timestamp generated last time or set. + * A test fixture that installs a LogicalClock instance onto a service context. */ -Timestamp getLastSetTimestamp(); +class LogicalClockTest : public unittest::Test { +public: + ~LogicalClockTest() override = default; -/** - * Generates a new and unique Timestamp. - * If count > 1 that many unique Timestamps are reserved starting with the returned value. - */ -Timestamp getNextGlobalTimestamp(ServiceContext* service, unsigned count = 1); -} +protected: + /** + * Sets up this fixture with a context and a LogicalClock. + */ + void setUp() override; + void tearDown() override{}; +}; + +} // namespace mongo diff --git a/src/mongo/db/logical_time_test.cpp b/src/mongo/db/logical_time_test.cpp index d5d1f15a7b2..e7d7d8e2819 100644 --- a/src/mongo/db/logical_time_test.cpp +++ b/src/mongo/db/logical_time_test.cpp @@ -80,7 +80,7 @@ TEST(LogicalTime, addTicksConst) { Timestamp tY(2); const auto lT = LogicalTime(tX); - auto lQ = lT.addTicks(1); + const auto lQ = lT.addTicks(1); ASSERT_TRUE(tX == lT.asTimestamp()); ASSERT_TRUE(tY == lQ.asTimestamp()); diff --git a/src/mongo/db/ops/SConscript b/src/mongo/db/ops/SConscript index 9d833d2b06b..7b5ddd1f629 100644 --- a/src/mongo/db/ops/SConscript +++ b/src/mongo/db/ops/SConscript @@ -71,9 +71,11 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/logical_clock', + '$BUILD_DIR/mongo/db/logical_time', '$BUILD_DIR/mongo/db/bson/dotted_path_support', '$BUILD_DIR/mongo/db/matcher/expressions', - '$BUILD_DIR/mongo/db/global_timestamp', 'update_common', ], ) @@ -111,6 +113,7 @@ env.CppUnitTest( LIBDEPS=[ '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils', '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/logical_clock_test_fixture', 'update', ], ) @@ -130,6 +133,7 @@ env.CppUnitTest( LIBDEPS=[ '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils', '$BUILD_DIR/mongo/db/service_context_noop_init', + '$BUILD_DIR/mongo/db/logical_clock_test_fixture', 'update', ], ) diff --git a/src/mongo/db/ops/insert.cpp b/src/mongo/db/ops/insert.cpp index 3cddceac1d5..1928ceb3661 100644 --- a/src/mongo/db/ops/insert.cpp +++ b/src/mongo/db/ops/insert.cpp @@ -29,7 +29,8 @@ */ #include "mongo/db/ops/insert.h" -#include "mongo/db/global_timestamp.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" #include "mongo/db/views/durable_view_catalog.h" #include "mongo/util/mongoutils/str.h" @@ -124,7 +125,8 @@ StatusWith<BSONObj> fixDocumentForInsert(ServiceContext* service, const BSONObj& if (hadId && e.fieldNameStringData() == "_id") { // no-op } else if (e.type() == bsonTimestamp && e.timestampValue() == 0) { - b.append(e.fieldName(), getNextGlobalTimestamp(service)); + auto nextTime = LogicalClock::get(service)->reserveTicks(1); + b.append(e.fieldName(), nextTime.asTimestamp()); } else { b.append(e); } diff --git a/src/mongo/db/ops/modifier_current_date.cpp b/src/mongo/db/ops/modifier_current_date.cpp index f693292781d..78dc3c57d4f 100644 --- a/src/mongo/db/ops/modifier_current_date.cpp +++ b/src/mongo/db/ops/modifier_current_date.cpp @@ -26,11 +26,14 @@ * it in the license file. */ +#include "mongo/platform/basic.h" + #include "mongo/db/ops/modifier_current_date.h" #include "mongo/base/error_codes.h" #include "mongo/bson/mutable/document.h" -#include "mongo/db/global_timestamp.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" #include "mongo/db/ops/field_checker.h" #include "mongo/db/ops/log_builder.h" #include "mongo/db/ops/path_support.h" @@ -226,7 +229,8 @@ Status ModifierCurrentDate::apply() const { return s; } else { ServiceContext* service = getGlobalServiceContext(); - Status s = elemToSet.setValueTimestamp(getNextGlobalTimestamp(service)); + auto ts = LogicalClock::get(service)->reserveTicks(1).asTimestamp(); + Status s = elemToSet.setValueTimestamp(ts); if (!s.isOK()) return s; } diff --git a/src/mongo/db/ops/modifier_current_date_test.cpp b/src/mongo/db/ops/modifier_current_date_test.cpp index 81bcd4d04e0..a9f0865c8be 100644 --- a/src/mongo/db/ops/modifier_current_date_test.cpp +++ b/src/mongo/db/ops/modifier_current_date_test.cpp @@ -35,6 +35,7 @@ #include "mongo/bson/mutable/mutable_bson_test_utils.h" #include "mongo/db/jsobj.h" #include "mongo/db/json.h" +#include "mongo/db/logical_clock_test_fixture.h" #include "mongo/db/ops/log_builder.h" #include "mongo/unittest/unittest.h" @@ -52,6 +53,12 @@ using mongo::mutablebson::ConstElement; using mongo::mutablebson::Document; using mongo::mutablebson::Element; +using Init = mongo::LogicalClockTest; +using BoolInput = mongo::LogicalClockTest; +using DateInput = mongo::LogicalClockTest; +using TimestampInput = mongo::LogicalClockTest; +using DottedTimestampInput = mongo::LogicalClockTest; + /** * Helper to validate oplog entries in the tests below. */ @@ -99,7 +106,7 @@ private: ModifierCurrentDate _mod; }; -TEST(Init, ValidValues) { +TEST_F(Init, ValidValues) { BSONObj modObj; ModifierCurrentDate mod; @@ -116,7 +123,7 @@ TEST(Init, ValidValues) { ModifierInterface::Options::normal())); } -TEST(Init, FailToInitWithInvalidValue) { +TEST_F(Init, FailToInitWithInvalidValue) { BSONObj modObj; ModifierCurrentDate mod; @@ -166,7 +173,7 @@ TEST(Init, FailToInitWithInvalidValue) { ModifierInterface::Options::normal())); } -TEST(BoolInput, EmptyStartDoc) { +TEST_F(BoolInput, EmptyStartDoc) { Document doc(fromjson("{ }")); Mod mod(fromjson("{ $currentDate : { a : true } }")); @@ -187,7 +194,7 @@ TEST(BoolInput, EmptyStartDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(DateInput, EmptyStartDoc) { +TEST_F(DateInput, EmptyStartDoc) { Document doc(fromjson("{ }")); Mod mod(fromjson("{ $currentDate : { a : {$type: 'date' } } }")); @@ -208,7 +215,7 @@ TEST(DateInput, EmptyStartDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(TimestampInput, EmptyStartDoc) { +TEST_F(TimestampInput, EmptyStartDoc) { Document doc(fromjson("{ }")); Mod mod(fromjson("{ $currentDate : { a : {$type : 'timestamp' } } }")); @@ -230,7 +237,7 @@ TEST(TimestampInput, EmptyStartDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(BoolInput, ExistingStringDoc) { +TEST_F(BoolInput, ExistingStringDoc) { Document doc(fromjson("{ a: 'a' }")); Mod mod(fromjson("{ $currentDate : { a : true } }")); @@ -251,7 +258,7 @@ TEST(BoolInput, ExistingStringDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(BoolInput, ExistingDateDoc) { +TEST_F(BoolInput, ExistingDateDoc) { Document doc(fromjson("{ a: {$date: 0 } }")); Mod mod(fromjson("{ $currentDate : { a : true } }")); @@ -272,7 +279,7 @@ TEST(BoolInput, ExistingDateDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(DateInput, ExistingDateDoc) { +TEST_F(DateInput, ExistingDateDoc) { Document doc(fromjson("{ a: {$date: 0 } }")); Mod mod(fromjson("{ $currentDate : { a : {$type: 'date' } } }")); @@ -293,7 +300,7 @@ TEST(DateInput, ExistingDateDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(TimestampInput, ExistingDateDoc) { +TEST_F(TimestampInput, ExistingDateDoc) { Document doc(fromjson("{ a: {$date: 0 } }")); Mod mod(fromjson("{ $currentDate : { a : {$type : 'timestamp' } } }")); @@ -315,7 +322,7 @@ TEST(TimestampInput, ExistingDateDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(TimestampInput, ExistingEmbeddedDateDoc) { +TEST_F(TimestampInput, ExistingEmbeddedDateDoc) { Document doc(fromjson("{ a: {b: {$date: 0 } } }")); Mod mod(fromjson("{ $currentDate : { 'a.b' : {$type : 'timestamp' } } }")); @@ -337,7 +344,7 @@ TEST(TimestampInput, ExistingEmbeddedDateDoc) { validateOplogEntry(oplogFormat, logDoc); } -TEST(DottedTimestampInput, EmptyStartDoc) { +TEST_F(DottedTimestampInput, EmptyStartDoc) { Document doc(fromjson("{ }")); Mod mod(fromjson("{ $currentDate : { 'a.b' : {$type : 'timestamp' } } }")); diff --git a/src/mongo/db/ops/modifier_object_replace.cpp b/src/mongo/db/ops/modifier_object_replace.cpp index 4dd1565dbdb..e74617ea7ef 100644 --- a/src/mongo/db/ops/modifier_object_replace.cpp +++ b/src/mongo/db/ops/modifier_object_replace.cpp @@ -31,7 +31,8 @@ #include "mongo/base/data_view.h" #include "mongo/base/error_codes.h" #include "mongo/bson/mutable/document.h" -#include "mongo/db/global_timestamp.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" #include "mongo/db/ops/log_builder.h" #include "mongo/db/service_context.h" #include "mongo/util/mongoutils/str.h" @@ -57,7 +58,7 @@ Status fixupTimestamps(const BSONObj& obj) { if (timestamp == 0) { // performance note, this locks a mutex: ServiceContext* service = getGlobalServiceContext(); - Timestamp ts(getNextGlobalTimestamp(service)); + auto ts = LogicalClock::get(service)->reserveTicks(1).asTimestamp(); timestampView.write(tagLittleEndian(ts.asULL())); } } diff --git a/src/mongo/db/ops/modifier_object_replace_test.cpp b/src/mongo/db/ops/modifier_object_replace_test.cpp index 4f55fe2cbf4..c661246e7f5 100644 --- a/src/mongo/db/ops/modifier_object_replace_test.cpp +++ b/src/mongo/db/ops/modifier_object_replace_test.cpp @@ -39,6 +39,7 @@ #include "mongo/bson/timestamp.h" #include "mongo/db/jsobj.h" #include "mongo/db/json.h" +#include "mongo/db/logical_clock_test_fixture.h" #include "mongo/db/ops/log_builder.h" #include "mongo/unittest/unittest.h" @@ -58,6 +59,11 @@ using mongo::NumberInt; using mongo::Status; using mongo::StringData; +using Normal = mongo::LogicalClockTest; +using IdLeft = mongo::LogicalClockTest; +using IdImmutable = mongo::LogicalClockTest; +using Timestamp = mongo::LogicalClockTest; + /** Helper to build and manipulate a $set mod. */ class Mod { public: @@ -94,7 +100,7 @@ private: }; // Normal replacements below -TEST(Normal, SingleFieldDoc) { +TEST_F(Normal, SingleFieldDoc) { Document doc(fromjson("{_id:1, a:1}")); Mod mod(fromjson("{_id:1, b:12}")); @@ -111,7 +117,7 @@ TEST(Normal, SingleFieldDoc) { ASSERT_EQUALS(doc, logDoc); } -TEST(Normal, ComplexDoc) { +TEST_F(Normal, ComplexDoc) { Document doc(fromjson("{_id:1, a:1}")); Mod mod(fromjson("{_id:1, b:[123], c: {r:true}}")); @@ -128,7 +134,7 @@ TEST(Normal, ComplexDoc) { ASSERT_EQUALS(doc, logDoc); } -TEST(Normal, OnlyIdField) { +TEST_F(Normal, OnlyIdField) { Document doc(fromjson("{}")); Mod mod(fromjson("{_id:1}")); @@ -147,7 +153,7 @@ TEST(Normal, OnlyIdField) { // These updates have to do with updates without an _id field // (the existing _id isn't removed) -TEST(IdLeft, EmptyDocReplacement) { +TEST_F(IdLeft, EmptyDocReplacement) { Document doc(fromjson("{_id:1}")); Mod mod(fromjson("{}")); @@ -164,7 +170,7 @@ TEST(IdLeft, EmptyDocReplacement) { ASSERT_EQUALS(doc, logDoc); } -TEST(IdLeft, EmptyDoc) { +TEST_F(IdLeft, EmptyDoc) { Document doc(fromjson("{_id:1}")); Mod mod(fromjson("{}")); @@ -181,7 +187,7 @@ TEST(IdLeft, EmptyDoc) { ASSERT_EQUALS(doc, logDoc); } -TEST(IdLeft, SingleFieldAddition) { +TEST_F(IdLeft, SingleFieldAddition) { Document doc(fromjson("{_id:1}")); Mod mod(fromjson("{a:1}")); @@ -198,7 +204,7 @@ TEST(IdLeft, SingleFieldAddition) { ASSERT_EQUALS(doc, logDoc); } -TEST(IdLeft, SingleFieldReplaced) { +TEST_F(IdLeft, SingleFieldReplaced) { Document doc(fromjson("{a: []}")); Mod mod(fromjson("{a:10}")); @@ -215,7 +221,7 @@ TEST(IdLeft, SingleFieldReplaced) { ASSERT_EQUALS(doc, logDoc); } -TEST(IdLeft, SwapFields) { +TEST_F(IdLeft, SwapFields) { Document doc(fromjson("{_id:1, a:1}")); Mod mod(fromjson("{b:1}")); @@ -232,7 +238,7 @@ TEST(IdLeft, SwapFields) { ASSERT_EQUALS(doc, logDoc); } -TEST(IdImmutable, ReplaceIdNumber) { +TEST_F(IdImmutable, ReplaceIdNumber) { Document doc(fromjson("{_id:1, a:1}")); Mod mod(fromjson("{_id:2}")); @@ -242,7 +248,7 @@ TEST(IdImmutable, ReplaceIdNumber) { ASSERT_NOT_OK(mod.apply()); } -TEST(IdImmutable, ReplaceIdNumberSameVal) { +TEST_F(IdImmutable, ReplaceIdNumberSameVal) { Document doc(fromjson("{_id:1, a:1}")); Mod mod(fromjson("{_id:2}")); @@ -252,7 +258,7 @@ TEST(IdImmutable, ReplaceIdNumberSameVal) { ASSERT_NOT_OK(mod.apply()); } -TEST(IdImmutable, ReplaceEmbeddedId) { +TEST_F(IdImmutable, ReplaceEmbeddedId) { Document doc(fromjson("{_id:{a:1, b:2}, a:1}")); Mod mod(fromjson("{_id:{b:2, a:1}}")); @@ -262,7 +268,7 @@ TEST(IdImmutable, ReplaceEmbeddedId) { ASSERT_NOT_OK(mod.apply()); } -TEST(Timestamp, IdNotReplaced) { +TEST_F(Timestamp, IdNotReplaced) { Document doc(fromjson("{}")); Mod mod(fromjson("{_id:Timestamp(0,0), a:1}")); @@ -283,7 +289,7 @@ TEST(Timestamp, IdNotReplaced) { ASSERT(idElem.getValueTimestamp().isNull()); } -TEST(Timestamp, ReplaceAll) { +TEST_F(Timestamp, ReplaceAll) { Document doc(fromjson("{}")); Mod mod(fromjson("{a:Timestamp(0,0), r:1, x:1, b:Timestamp(0,0)}")); diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 1736bcc2c0c..dd7233cd6b3 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -424,7 +424,6 @@ env.Library('repl_coordinator_impl', ], LIBDEPS=[ '$BUILD_DIR/mongo/db/common', - '$BUILD_DIR/mongo/db/global_timestamp', '$BUILD_DIR/mongo/db/index/index_descriptor', '$BUILD_DIR/mongo/db/server_options_core', '$BUILD_DIR/mongo/db/service_context', @@ -1166,6 +1165,8 @@ env.Library( '$BUILD_DIR/mongo/client/clientdriver', '$BUILD_DIR/mongo/db/auth/authcore', '$BUILD_DIR/mongo/db/commands', + '$BUILD_DIR/mongo/db/logical_clock', + '$BUILD_DIR/mongo/db/logical_time', '$BUILD_DIR/mongo/db/commands/list_collections_filter', '$BUILD_DIR/mongo/rpc/client_metadata', '$BUILD_DIR/mongo/db/concurrency/lock_manager', diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 0e9b8c0366c..82c285441b6 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -62,11 +62,12 @@ #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/dbhelpers.h" -#include "mongo/db/global_timestamp.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/index_builder.h" #include "mongo/db/keypattern.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" #include "mongo/db/namespace_string.h" #include "mongo/db/op_observer.h" #include "mongo/db/ops/delete.h" @@ -161,7 +162,8 @@ void getNextOpTime(OperationContext* txn, } stdx::lock_guard<stdx::mutex> lk(newOpMutex); - Timestamp ts = getNextGlobalTimestamp(txn->getServiceContext(), count); + + auto ts = LogicalClock::get(txn)->reserveTicks(count).asTimestamp(); newTimestampNotifier.notify_all(); fassert(28560, oplog->getRecordStore()->oplogDiskLocRegister(txn, ts)); @@ -1109,7 +1111,7 @@ Status applyCommand_inlock(OperationContext* txn, void setNewTimestamp(ServiceContext* service, const Timestamp& newTime) { stdx::lock_guard<stdx::mutex> lk(newOpMutex); - setGlobalTimestamp(service, newTime); + LogicalClock::get(service)->advanceClusterTimeFromTrustedSource(LogicalTime(newTime)); newTimestampNotifier.notify_all(); } @@ -1193,9 +1195,10 @@ void SnapshotThread::run() { if (_inShutdown.load()) return; - if (_forcedSnapshotPending.load() || lastTimestamp != getLastSetTimestamp()) { + auto clusterTime = LogicalClock::get(service)->getClusterTime().getTime(); + if (_forcedSnapshotPending.load() || lastTimestamp != clusterTime.asTimestamp()) { _forcedSnapshotPending.store(false); - lastTimestamp = getLastSetTimestamp(); + lastTimestamp = clusterTime.asTimestamp(); break; } diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 623f5251977..099f9462504 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -40,8 +40,9 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/concurrency/d_concurrency.h" -#include "mongo/db/global_timestamp.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" #include "mongo/db/operation_context_noop.h" #include "mongo/db/repl/check_quorum_for_config_change.h" #include "mongo/db/repl/data_replicator_external_state_initial_sync.h" @@ -2677,7 +2678,9 @@ void ReplicationCoordinatorImpl::_performPostMemberStateUpdateAction( } else { _electionId = OID::gen(); } - _topCoord->processWinElection(_electionId, getNextGlobalTimestamp(getServiceContext())); + + auto ts = LogicalClock::get(getServiceContext())->reserveTicks(1).asTimestamp(); + _topCoord->processWinElection(_electionId, ts); invariant(!_isCatchingUp); invariant(!_isWaitingForDrainToComplete); _isCatchingUp = true; @@ -2872,13 +2875,15 @@ ReplicationCoordinatorImpl::_setCurrentRSConfig_inlock(const ReplicaSetConfig& n // Downgrade invariant(newConfig.getProtocolVersion() == 0); _electionId = OID::gen(); - _topCoord->setElectionInfo(_electionId, getNextGlobalTimestamp(getServiceContext())); + auto ts = LogicalClock::get(getServiceContext())->reserveTicks(1).asTimestamp(); + _topCoord->setElectionInfo(_electionId, ts); } else if (oldConfig.getProtocolVersion() < newConfig.getProtocolVersion()) { // Upgrade invariant(newConfig.getProtocolVersion() == 1); invariant(_topCoord->getTerm() != OpTime::kUninitializedTerm); _electionId = OID::fromTerm(_topCoord->getTerm()); - _topCoord->setElectionInfo(_electionId, getNextGlobalTimestamp(getServiceContext())); + auto ts = LogicalClock::get(getServiceContext())->reserveTicks(1).asTimestamp(); + _topCoord->setElectionInfo(_electionId, ts); } } diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp index 61fd52855de..c0bbda407f1 100644 --- a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp +++ b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp @@ -32,6 +32,7 @@ #include "mongo/db/repl/replication_coordinator_test_fixture.h" +#include "mongo/db/logical_clock.h" #include "mongo/db/operation_context_noop.h" #include "mongo/db/repl/is_master_response.h" #include "mongo/db/repl/repl_set_heartbeat_args.h" @@ -41,6 +42,7 @@ #include "mongo/db/repl/replication_coordinator_impl.h" #include "mongo/db/repl/storage_interface_mock.h" #include "mongo/db/repl/topology_coordinator_impl.h" +#include "mongo/db/time_proof_service.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/stdx/functional.h" #include "mongo/stdx/memory.h" @@ -120,6 +122,11 @@ void ReplCoordTest::init() { // PRNG seed for tests. const int64_t seed = 0; + auto timeProofService = stdx::make_unique<TimeProofService>(); + auto logicalClock = + stdx::make_unique<LogicalClock>(service, std::move(timeProofService), false); + LogicalClock::set(service, std::move(logicalClock)); + TopologyCoordinatorImpl::Options settings; auto topo = stdx::make_unique<TopologyCoordinatorImpl>(settings); _topo = topo.get(); diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp index a0302e3addb..8f752b49e05 100644 --- a/src/mongo/db/repl/sync_tail.cpp +++ b/src/mongo/db/repl/sync_tail.cpp @@ -52,7 +52,6 @@ #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbhelpers.h" -#include "mongo/db/global_timestamp.h" #include "mongo/db/namespace_string.h" #include "mongo/db/prefetch.h" #include "mongo/db/query/query_knobs.h" diff --git a/src/mongo/db/s/balancer/migration_manager_test.cpp b/src/mongo/db/s/balancer/migration_manager_test.cpp index 2f2012b1ee9..a037f434ebc 100644 --- a/src/mongo/db/s/balancer/migration_manager_test.cpp +++ b/src/mongo/db/s/balancer/migration_manager_test.cpp @@ -43,6 +43,7 @@ #include "mongo/s/config_server_test_fixture.h" #include "mongo/s/move_chunk_request.h" #include "mongo/stdx/memory.h" +#include "mongo/util/scopeguard.h" namespace mongo { namespace { @@ -311,6 +312,7 @@ TEST_F(MigrationManagerTest, OneCollectionTwoMigrations) { const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; auto future = launchAsync([this, migrationRequests] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -373,6 +375,7 @@ TEST_F(MigrationManagerTest, TwoCollectionsTwoMigrationsEach) { {kShardId3, chunk2coll2}}; auto future = launchAsync([this, migrationRequests] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -427,6 +430,7 @@ TEST_F(MigrationManagerTest, SourceShardNotFound) { const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; auto future = launchAsync([this, chunk1, chunk2, migrationRequests] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -473,6 +477,7 @@ TEST_F(MigrationManagerTest, JumboChunkResponseBackwardsCompatibility) { const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}}; auto future = launchAsync([this, chunk1, migrationRequests] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -511,6 +516,7 @@ TEST_F(MigrationManagerTest, InterruptMigration) { setUpChunk(collName, kKeyPattern.globalMin(), kKeyPattern.globalMax(), kShardId0, version); auto future = launchAsync([&] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -598,6 +604,7 @@ TEST_F(MigrationManagerTest, RestartMigrationManager) { _migrationManager->finishRecovery(operationContext(), 0, kDefaultSecondaryThrottle); auto future = launchAsync([&] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -652,6 +659,7 @@ TEST_F(MigrationManagerTest, MigrationRecovery) { _migrationManager->startRecoveryAndAcquireDistLocks(operationContext()); auto future = launchAsync([this] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); @@ -753,6 +761,7 @@ TEST_F(MigrationManagerTest, RemoteCallErrorConversionToOperationFailed) { setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); auto future = launchAsync([&] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); Client::initThreadIfNotAlready("Test"); auto txn = cc().makeOperationContext(); diff --git a/src/mongo/dbtests/SConscript b/src/mongo/dbtests/SConscript index 27bb7cfea70..37238d35d0b 100644 --- a/src/mongo/dbtests/SConscript +++ b/src/mongo/dbtests/SConscript @@ -123,6 +123,7 @@ dbtest = env.Program( "$BUILD_DIR/mongo/db/repl/repl_coordinator_global", "$BUILD_DIR/mongo/db/repl/replmocks", "$BUILD_DIR/mongo/db/serveronly", + "$BUILD_DIR/mongo/db/logical_clock", "$BUILD_DIR/mongo/db/storage/paths", "$BUILD_DIR/mongo/util/concurrency/rwlock", "$BUILD_DIR/mongo/util/net/network", diff --git a/src/mongo/dbtests/dbtests.cpp b/src/mongo/dbtests/dbtests.cpp index 4ce21b9097c..52f5f2a4888 100644 --- a/src/mongo/dbtests/dbtests.cpp +++ b/src/mongo/dbtests/dbtests.cpp @@ -42,11 +42,13 @@ #include "mongo/db/commands.h" #include "mongo/db/db_raii.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/logical_clock.h" #include "mongo/db/repl/replication_coordinator_global.h" #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" #include "mongo/db/service_context_d.h" +#include "mongo/db/time_proof_service.h" #include "mongo/db/wire_version.h" #include "mongo/dbtests/framework.h" #include "mongo/scripting/engine.h" @@ -131,6 +133,12 @@ int dbtestsMain(int argc, char** argv, char** envp) { repl::ReplSettings replSettings; replSettings.setOplogSizeBytes(10 * 1024 * 1024); ServiceContext* service = getGlobalServiceContext(); + + auto timeProofService = stdx::make_unique<TimeProofService>(); + auto logicalClock = + stdx::make_unique<LogicalClock>(service, std::move(timeProofService), false); + LogicalClock::set(service, std::move(logicalClock)); + repl::setGlobalReplicationCoordinator( new repl::ReplicationCoordinatorMock(service, replSettings)); repl::getGlobalReplicationCoordinator()->setFollowerMode(repl::MemberState::RS_PRIMARY); diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp index 1ca8cf49bf0..5288038b1f8 100644 --- a/src/mongo/dbtests/querytests.cpp +++ b/src/mongo/dbtests/querytests.cpp @@ -39,10 +39,11 @@ #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/dbhelpers.h" -#include "mongo/db/global_timestamp.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/json.h" #include "mongo/db/lasterror.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" #include "mongo/db/namespace_string.h" #include "mongo/db/query/find.h" #include "mongo/db/service_context.h" @@ -670,12 +671,12 @@ public: << 8192), info); - Date_t one = - Date_t::fromMillisSinceEpoch(getNextGlobalTimestamp(_txn.getServiceContext()).asLL()); - Date_t two = - Date_t::fromMillisSinceEpoch(getNextGlobalTimestamp(_txn.getServiceContext()).asLL()); - Date_t three = - Date_t::fromMillisSinceEpoch(getNextGlobalTimestamp(_txn.getServiceContext()).asLL()); + Date_t one = Date_t::fromMillisSinceEpoch( + LogicalClock::get(&_txn)->reserveTicks(1).asTimestamp().asLL()); + Date_t two = Date_t::fromMillisSinceEpoch( + LogicalClock::get(&_txn)->reserveTicks(1).asTimestamp().asLL()); + Date_t three = Date_t::fromMillisSinceEpoch( + LogicalClock::get(&_txn)->reserveTicks(1).asTimestamp().asLL()); insert(ns, BSON("ts" << one)); insert(ns, BSON("ts" << two)); insert(ns, BSON("ts" << three)); diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index 68afcfd378b..1a5d0b28ea9 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -54,6 +54,8 @@ #include "mongo/db/initialize_server_global_state.h" #include "mongo/db/lasterror.h" #include "mongo/db/log_process_details.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/operation_context.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" #include "mongo/db/service_context_noop.h" @@ -266,6 +268,11 @@ static ExitCode runMongosServer() { auto opCtx = cc().makeOperationContext(); + auto timeProofService = stdx::make_unique<TimeProofService>(); + auto logicalClock = stdx::make_unique<LogicalClock>( + opCtx->getServiceContext(), std::move(timeProofService), false); + LogicalClock::set(opCtx->getServiceContext(), std::move(logicalClock)); + { Status status = initializeSharding(opCtx.get()); if (!status.isOK()) { diff --git a/src/mongo/s/sharding_mongod_test_fixture.cpp b/src/mongo/s/sharding_mongod_test_fixture.cpp index 79097d4682f..d4b3d4d9e2a 100644 --- a/src/mongo/s/sharding_mongod_test_fixture.cpp +++ b/src/mongo/s/sharding_mongod_test_fixture.cpp @@ -39,6 +39,7 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/db_raii.h" +#include "mongo/db/logical_clock.h" #include "mongo/db/namespace_string.h" #include "mongo/db/op_observer_impl.h" #include "mongo/db/query/cursor_response.h" @@ -49,6 +50,7 @@ #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/service_context_noop.h" +#include "mongo/db/time_proof_service.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/task_executor_pool.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" @@ -107,6 +109,11 @@ void ShardingMongodTestFixture::setUp() { // Set up this node as part of a replica set. + auto timeProofService = stdx::make_unique<TimeProofService>(); + auto logicalClock = + stdx::make_unique<LogicalClock>(service, std::move(timeProofService), false); + LogicalClock::set(service, std::move(logicalClock)); + repl::ReplSettings replSettings; replSettings.setReplSetString(ConnectionString::forReplicaSet(_setName, _servers).toString()); auto replCoordPtr = makeReplicationCoordinator(replSettings); |