diff options
author | Misha Tyulenev <misha@mongodb.com> | 2017-02-02 15:25:38 -0500 |
---|---|---|
committer | Misha Tyulenev <misha@mongodb.com> | 2017-02-02 15:26:04 -0500 |
commit | c742c4ebe789fafa3fccd4b25332a7df0782b252 (patch) | |
tree | f037d52849c405db6ba0303b906d50d5f4fbb297 | |
parent | f4adad667540f1fa60797207644575edec69849c (diff) | |
download | mongo-c742c4ebe789fafa3fccd4b25332a7df0782b252.tar.gz |
SERVER-27743: Implement LogicalTime
-rw-r--r-- | src/mongo/db/SConscript | 31 | ||||
-rw-r--r-- | src/mongo/db/logical_time.cpp | 52 | ||||
-rw-r--r-- | src/mongo/db/logical_time.h | 88 | ||||
-rw-r--r-- | src/mongo/db/logical_time_test.cpp | 101 | ||||
-rw-r--r-- | src/mongo/db/signed_logical_time.cpp | 41 | ||||
-rw-r--r-- | src/mongo/db/signed_logical_time.h | 63 | ||||
-rw-r--r-- | src/mongo/db/time_proof_service.h | 61 |
7 files changed, 437 insertions, 0 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index a5c8da3ddac..4cf0a47af5b 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -938,6 +938,37 @@ env.Library( ) env.Library( + target='logical_time', + source=[ + 'logical_time.cpp', + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/base', + ], +) + +env.Library( + target='signed_logical_time', + source=[ + 'signed_logical_time.cpp', + ], + LIBDEPS=[ + 'logical_time', + ], +) + +env.CppUnitTest( + target='logical_time_test', + source=[ + 'logical_time_test.cpp', + ], + LIBDEPS=[ + 'logical_time', + 'signed_logical_time', + ], +) + +env.Library( target= 'op_observer_noop', source= [ 'op_observer_noop.cpp', diff --git a/src/mongo/db/logical_time.cpp b/src/mongo/db/logical_time.cpp new file mode 100644 index 00000000000..9d36a17a234 --- /dev/null +++ b/src/mongo/db/logical_time.cpp @@ -0,0 +1,52 @@ +/** + * 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/db/logical_time.h" + +#include "mongo/platform/basic.h" +#include "mongo/util/mongoutils/str.h" + +namespace mongo { + +LogicalTime::LogicalTime(Timestamp ts) : _time(ts.asULL()) {} + +void LogicalTime::addTicks(uint64_t ticks) { + _time += ticks; +} + +LogicalTime LogicalTime::addTicks(uint64_t ticks) const { + return LogicalTime(Timestamp(_time + ticks)); +} + +std::string LogicalTime::toString() const { + StringBuilder buf; + buf << asTimestamp().toString(); + return buf.str(); +} + +} // namespace mongo diff --git a/src/mongo/db/logical_time.h b/src/mongo/db/logical_time.h new file mode 100644 index 00000000000..6d3fb74a99b --- /dev/null +++ b/src/mongo/db/logical_time.h @@ -0,0 +1,88 @@ +/** + * 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. + */ + +#pragma once + +#include "mongo/bson/timestamp.h" + +namespace mongo { + +/** + * The LogicalTime class holds the cluster time of the cluster. It provides conversions to + * a Timestamp to allow integration with opLog. + */ +class LogicalTime { +public: + explicit LogicalTime(Timestamp); + + Timestamp asTimestamp() const { + return Timestamp(_time); + } + + /** + * Increases the _time by ticks. + */ + void addTicks(uint64_t ticks); + + + /** + * Const version, returns the LogicalTime with increased _time by ticks. + */ + LogicalTime addTicks(uint64_t ticks) const; + + std::string toString() const; + +private: + uint64_t _time{0}; +}; + +inline bool operator==(const LogicalTime& l, const LogicalTime& r) { + return l.asTimestamp() == r.asTimestamp(); +} + +inline bool operator!=(const LogicalTime& l, const LogicalTime& r) { + return !(l == r); +} + +inline bool operator<(const LogicalTime& l, const LogicalTime& r) { + return l.asTimestamp() < r.asTimestamp(); +} + +inline bool operator<=(const LogicalTime& l, const LogicalTime& r) { + return (l < r || l == r); +} + +inline bool operator>(const LogicalTime& l, const LogicalTime& r) { + return (r < l); +} + +inline bool operator>=(const LogicalTime& l, const LogicalTime& r) { + return (l > r || l == r); +} + +} // namespace mongo diff --git a/src/mongo/db/logical_time_test.cpp b/src/mongo/db/logical_time_test.cpp new file mode 100644 index 00000000000..dbff22f8ce3 --- /dev/null +++ b/src/mongo/db/logical_time_test.cpp @@ -0,0 +1,101 @@ +/** + * 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/db/logical_time.h" +#include "mongo/bson/timestamp.h" +#include "mongo/db/signed_logical_time.h" +#include "mongo/db/time_proof_service.h" +#include "mongo/platform/basic.h" +#include "mongo/unittest/unittest.h" + +namespace mongo { +namespace { + +TEST(LogicalTime, comparisons) { + Timestamp tX(1); + Timestamp tY(2); + + ASSERT_TRUE(tX < tY); + + ASSERT_TRUE(LogicalTime(tX) < LogicalTime(tY)); + ASSERT_TRUE(LogicalTime(tX) <= LogicalTime(tY)); + ASSERT_TRUE(LogicalTime(tY) > LogicalTime(tX)); + ASSERT_TRUE(LogicalTime(tY) >= LogicalTime(tX)); + ASSERT_TRUE(LogicalTime(tX) != LogicalTime(tY)); + ASSERT_TRUE(LogicalTime(tX) == LogicalTime(tX)); + + ASSERT_FALSE(LogicalTime(tX) > LogicalTime(tY)); + ASSERT_FALSE(LogicalTime(tX) >= LogicalTime(tY)); + ASSERT_FALSE(LogicalTime(tY) < LogicalTime(tX)); + ASSERT_FALSE(LogicalTime(tY) <= LogicalTime(tX)); + ASSERT_FALSE(LogicalTime(tX) == LogicalTime(tY)); + ASSERT_FALSE(LogicalTime(tX) != LogicalTime(tX)); +} + +TEST(LogicalTime, roundtrip) { + Timestamp tX(1); + auto tY = LogicalTime(tX).asTimestamp(); + + ASSERT_TRUE(tX == tY); +} + +TEST(LogicalTime, addTicks) { + Timestamp tX(1); + Timestamp tY(2); + + auto lT = LogicalTime(tX); + lT.addTicks(1); + + ASSERT_TRUE(tY == lT.asTimestamp()); +} + +TEST(LogicalTime, addTicksConst) { + Timestamp tX(1); + Timestamp tY(2); + + const auto lT = LogicalTime(tX); + auto lQ = lT.addTicks(1); + + ASSERT_TRUE(tX == lT.asTimestamp()); + ASSERT_TRUE(tY == lQ.asTimestamp()); +} + +TEST(SignedLogicalTime, roundtrip) { + Timestamp tX(1); + TimeProofService tps; + auto time = LogicalTime(tX); + auto proof = tps.getProof(time); + + SignedLogicalTime signedTime(time, proof); + ASSERT_TRUE(time == signedTime.getTime()); + ASSERT_TRUE(proof == signedTime.getProof()); +} + +} // unnamed namespace +} // namespace mongo diff --git a/src/mongo/db/signed_logical_time.cpp b/src/mongo/db/signed_logical_time.cpp new file mode 100644 index 00000000000..bcfb89f027a --- /dev/null +++ b/src/mongo/db/signed_logical_time.cpp @@ -0,0 +1,41 @@ +/** + * 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/db/signed_logical_time.h" + +#include "mongo/util/mongoutils/str.h" + +namespace mongo { + +std::string SignedLogicalTime::toString() const { + StringBuilder buf; + buf << _time.toString() << "|" << _proof; + return buf.str(); +} + +} // namespace mongo diff --git a/src/mongo/db/signed_logical_time.h b/src/mongo/db/signed_logical_time.h new file mode 100644 index 00000000000..12c8d373d49 --- /dev/null +++ b/src/mongo/db/signed_logical_time.h @@ -0,0 +1,63 @@ +/** + * 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. + */ + +#pragma once + +#include "mongo/db/logical_time.h" +#include "mongo/db/time_proof_service.h" +#include <string> + +namespace mongo { + +/** + * The SignedLogicalTime class is a pair of value i.e. time and a signature i.e. _proof + * The class is immutable and is used to hold the cryptogrphically protected LogicalTime. + */ +class SignedLogicalTime { +public: + using TimeProof = TimeProofService::TimeProof; + + explicit SignedLogicalTime(LogicalTime time, TimeProof proof) + : _time(std::move(time)), _proof(std::move(proof)) {} + + LogicalTime getTime() const { + return _time; + } + + const TimeProof& getProof() const { + return _proof; + } + + std::string toString() const; + +private: + LogicalTime _time; + TimeProof _proof; +}; + +} // namespace mongo diff --git a/src/mongo/db/time_proof_service.h b/src/mongo/db/time_proof_service.h new file mode 100644 index 00000000000..bc43e1ceee3 --- /dev/null +++ b/src/mongo/db/time_proof_service.h @@ -0,0 +1,61 @@ +/** + * 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. + */ + +#pragma once + +#include "mongo/base/status.h" +#include "mongo/db/logical_time.h" + +namespace mongo { + +/** + * Mock of the TimeProofService class. The class when fully implemented will be self-contained. It + * will provide key management and rotation, caching and other optimizations as needed. + */ +class TimeProofService { +public: + // This type must be synchronized with the library that generates SHA1 or other proof. + using TimeProof = std::string; + + /** + * Returns the proof matching the time argument. + */ + TimeProof getProof(LogicalTime time) { + TimeProof proof = "12345678901234567890"; + return proof; + } + + /** + * Verifies that the proof is matching the time argument. + */ + Status checkProof(LogicalTime time, const TimeProof& proof) { + return Status::OK(); + } +}; + +} // namespace mongo |