summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2017-01-12 13:15:08 -0500
committerJudah Schvimer <judah@mongodb.com>2017-04-06 09:54:34 -0400
commitb4e4f6c70b4324b8e5ffd8f292922c201ed7c92d (patch)
tree958ad08bbb2e05f295145d0d6853200c9de61794 /src
parent5e04506f9ccf9388dba552cb514957ceca1399bd (diff)
downloadmongo-b4e4f6c70b4324b8e5ffd8f292922c201ed7c92d.tar.gz
SERVER-27543 Create new metadata for oplog queries
(cherry picked from commit 8daf13374403272ace73340f25fce573fa36a55b)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/rpc/SConscript9
-rw-r--r--src/mongo/rpc/metadata/oplog_query_metadata.cpp117
-rw-r--r--src/mongo/rpc/metadata/oplog_query_metadata.h119
-rw-r--r--src/mongo/rpc/metadata/oplog_query_metadata_test.cpp86
4 files changed, 331 insertions, 0 deletions
diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript
index afcfe2563e6..516e3a5f305 100644
--- a/src/mongo/rpc/SConscript
+++ b/src/mongo/rpc/SConscript
@@ -150,6 +150,7 @@ env.Library(
'metadata/server_selection_metadata.cpp',
'metadata/sharding_metadata.cpp',
'metadata/repl_set_metadata.cpp',
+ 'metadata/oplog_query_metadata.cpp',
'metadata/tracking_metadata.cpp',
],
LIBDEPS=[
@@ -204,6 +205,14 @@ env.CppUnitTest(
)
env.CppUnitTest(
+ target='oplog_query_metadata_test',
+ source=[
+ 'metadata/oplog_query_metadata_test.cpp',
+ ],
+ LIBDEPS=['metadata']
+)
+
+env.CppUnitTest(
target='config_server_metadata_test',
source=[
'metadata/config_server_metadata_test.cpp',
diff --git a/src/mongo/rpc/metadata/oplog_query_metadata.cpp b/src/mongo/rpc/metadata/oplog_query_metadata.cpp
new file mode 100644
index 00000000000..6ac3f91ea00
--- /dev/null
+++ b/src/mongo/rpc/metadata/oplog_query_metadata.cpp
@@ -0,0 +1,117 @@
+/**
+ * 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/rpc/metadata/oplog_query_metadata.h"
+
+#include "mongo/bson/util/bson_check.h"
+#include "mongo/bson/util/bson_extract.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/repl/bson_extract_optime.h"
+#include "mongo/rpc/metadata.h"
+
+namespace mongo {
+namespace rpc {
+
+using repl::OpTime;
+
+const char kOplogQueryMetadataFieldName[] = "$oplogQueryData";
+
+namespace {
+
+const char kLastOpCommittedFieldName[] = "lastOpCommitted";
+const char kLastOpAppliedFieldName[] = "lastOpApplied";
+const char kPrimaryIndexFieldName[] = "primaryIndex";
+const char kSyncSourceIndexFieldName[] = "syncSourceIndex";
+const char kRBIDFieldName[] = "rbid";
+
+} // unnamed namespace
+
+const int OplogQueryMetadata::kNoPrimary;
+
+OplogQueryMetadata::OplogQueryMetadata(OpTime lastOpCommitted,
+ OpTime lastOpApplied,
+ int rbid,
+ int currentPrimaryIndex,
+ int currentSyncSourceIndex)
+ : _lastOpCommitted(std::move(lastOpCommitted)),
+ _lastOpApplied(std::move(lastOpApplied)),
+ _rbid(rbid),
+ _currentPrimaryIndex(currentPrimaryIndex),
+ _currentSyncSourceIndex(currentSyncSourceIndex) {}
+
+StatusWith<OplogQueryMetadata> OplogQueryMetadata::readFromMetadata(const BSONObj& metadataObj) {
+ BSONElement oqMetadataElement;
+
+ Status status = bsonExtractTypedField(
+ metadataObj, rpc::kOplogQueryMetadataFieldName, Object, &oqMetadataElement);
+ if (!status.isOK())
+ return status;
+ BSONObj oqMetadataObj = oqMetadataElement.Obj();
+
+ long long primaryIndex;
+ status = bsonExtractIntegerField(oqMetadataObj, kPrimaryIndexFieldName, &primaryIndex);
+ if (!status.isOK())
+ return status;
+
+ long long syncSourceIndex;
+ status = bsonExtractIntegerField(oqMetadataObj, kSyncSourceIndexFieldName, &syncSourceIndex);
+ if (!status.isOK())
+ return status;
+
+ long long rbid;
+ status = bsonExtractIntegerField(oqMetadataObj, kRBIDFieldName, &rbid);
+ if (!status.isOK())
+ return status;
+
+ repl::OpTime lastOpCommitted;
+ status = bsonExtractOpTimeField(oqMetadataObj, kLastOpCommittedFieldName, &lastOpCommitted);
+ if (!status.isOK())
+ return status;
+
+ repl::OpTime lastOpApplied;
+ status = bsonExtractOpTimeField(oqMetadataObj, kLastOpAppliedFieldName, &lastOpApplied);
+ if (!status.isOK())
+ return status;
+
+ return OplogQueryMetadata(lastOpCommitted, lastOpApplied, rbid, primaryIndex, syncSourceIndex);
+}
+
+Status OplogQueryMetadata::writeToMetadata(BSONObjBuilder* builder) const {
+ BSONObjBuilder oqMetadataBuilder(builder->subobjStart(kOplogQueryMetadataFieldName));
+ _lastOpCommitted.append(&oqMetadataBuilder, kLastOpCommittedFieldName);
+ _lastOpApplied.append(&oqMetadataBuilder, kLastOpAppliedFieldName);
+ oqMetadataBuilder.append(kRBIDFieldName, _rbid);
+ oqMetadataBuilder.append(kPrimaryIndexFieldName, _currentPrimaryIndex);
+ oqMetadataBuilder.append(kSyncSourceIndexFieldName, _currentSyncSourceIndex);
+ oqMetadataBuilder.doneFast();
+
+ return Status::OK();
+}
+
+} // namespace rpc
+} // namespace mongo
diff --git a/src/mongo/rpc/metadata/oplog_query_metadata.h b/src/mongo/rpc/metadata/oplog_query_metadata.h
new file mode 100644
index 00000000000..b95970a7d38
--- /dev/null
+++ b/src/mongo/rpc/metadata/oplog_query_metadata.h
@@ -0,0 +1,119 @@
+/**
+ * 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/oid.h"
+#include "mongo/db/repl/optime.h"
+
+namespace mongo {
+
+class BSONObj;
+class BSONObjBuilder;
+
+namespace rpc {
+
+extern const char kOplogQueryMetadataFieldName[];
+
+/**
+ * Represents the metadata information for $oplogQueryData.
+ */
+class OplogQueryMetadata {
+public:
+ /**
+ * Default primary index. Also used to indicate in metadata that there is no
+ * primary.
+ */
+ static const int kNoPrimary = -1;
+
+ OplogQueryMetadata(repl::OpTime lastOpCommitted,
+ repl::OpTime lastOpApplied,
+ int rbid,
+ int currentPrimaryIndex,
+ int currentSyncSourceIndex);
+
+ /**
+ * format:
+ * {
+ * lastOpCommitted: {ts: Timestamp(0, 0), term: 0},
+ * lastOpApplied: {ts: Timestamp(0, 0), term: 0},
+ * rbid: 0
+ * primaryIndex: 0,
+ * syncSourceIndex: 0
+ * }
+ */
+ static StatusWith<OplogQueryMetadata> readFromMetadata(const BSONObj& doc);
+ Status writeToMetadata(BSONObjBuilder* builder) const;
+
+ /**
+ * Returns the OpTime of the most recently committed op of which the sender was aware.
+ */
+ repl::OpTime getLastOpCommitted() const {
+ return _lastOpCommitted;
+ }
+
+ /**
+ * Returns the OpTime of the most recent operation to be applied by the sender.
+ */
+ repl::OpTime getLastOpApplied() const {
+ return _lastOpApplied;
+ }
+
+ /**
+ * Returns the index of the current primary from the perspective of the sender.
+ * Returns kNoPrimary if there is no primary.
+ */
+ int getPrimaryIndex() const {
+ return _currentPrimaryIndex;
+ }
+
+ /**
+ * Returns the index of the sync source of the sender.
+ * Returns -1 if it has no sync source.
+ */
+ int getSyncSourceIndex() const {
+ return _currentSyncSourceIndex;
+ }
+
+ /**
+ * Returns the current rbid of the sender.
+ */
+ int getRBID() const {
+ return _rbid;
+ }
+
+private:
+ repl::OpTime _lastOpCommitted;
+ repl::OpTime _lastOpApplied;
+ int _rbid = -1;
+ int _currentPrimaryIndex = kNoPrimary;
+ int _currentSyncSourceIndex = -1;
+};
+
+} // namespace rpc
+} // namespace mongo
diff --git a/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp b/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp
new file mode 100644
index 00000000000..cc08bf832fb
--- /dev/null
+++ b/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp
@@ -0,0 +1,86 @@
+/**
+ * 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/jsobj.h"
+#include "mongo/rpc/metadata/oplog_query_metadata.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+namespace rpc {
+namespace {
+
+using repl::OpTime;
+
+TEST(ReplResponseMetadataTest, OplogQueryMetadataRoundtrip) {
+ OpTime opTime1(Timestamp(1234, 100), 5);
+ OpTime opTime2(Timestamp(7777, 101), 6);
+ OplogQueryMetadata metadata(opTime1, opTime2, 6, 12, -1);
+
+ ASSERT_EQ(opTime1, metadata.getLastOpCommitted());
+ ASSERT_EQ(opTime2, metadata.getLastOpApplied());
+
+ BSONObjBuilder builder;
+ metadata.writeToMetadata(&builder);
+
+ BSONObj expectedObj(BSON(kOplogQueryMetadataFieldName << BSON(
+ "lastOpCommitted"
+ << BSON("ts" << opTime1.getTimestamp() << "t" << opTime1.getTerm())
+ << "lastOpApplied"
+ << BSON("ts" << opTime2.getTimestamp() << "t" << opTime2.getTerm())
+ << "rbid"
+ << 6
+ << "primaryIndex"
+ << 12
+ << "syncSourceIndex"
+ << -1)));
+
+ BSONObj serializedObj = builder.obj();
+ ASSERT_BSONOBJ_EQ(expectedObj, serializedObj);
+
+ auto cloneStatus = OplogQueryMetadata::readFromMetadata(serializedObj);
+ ASSERT_OK(cloneStatus.getStatus());
+
+ const auto& clonedMetadata = cloneStatus.getValue();
+ ASSERT_EQ(opTime1, clonedMetadata.getLastOpCommitted());
+ ASSERT_EQ(opTime2, clonedMetadata.getLastOpApplied());
+ ASSERT_EQ(metadata.getRBID(), clonedMetadata.getRBID());
+ ASSERT_EQ(metadata.getPrimaryIndex(), clonedMetadata.getPrimaryIndex());
+ ASSERT_EQ(metadata.getSyncSourceIndex(), clonedMetadata.getSyncSourceIndex());
+
+ BSONObjBuilder clonedBuilder;
+ clonedMetadata.writeToMetadata(&clonedBuilder);
+
+ BSONObj clonedSerializedObj = clonedBuilder.obj();
+ ASSERT_BSONOBJ_EQ(expectedObj, clonedSerializedObj);
+}
+
+} // unnamed namespace
+} // namespace rpc
+} // namespace mongo