Skip to content

Commit 33adeaf

Browse files
ajdavisEvergreen Agent
authored andcommitted
SERVER-47125 Don't trust OplogQueryMetadata.primaryIndex
1 parent 906e1a7 commit 33adeaf

File tree

7 files changed

+26
-16
lines changed

7 files changed

+26
-16
lines changed

src/mongo/db/repl/README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -346,12 +346,11 @@ It then creates a `ReplSetHeartbeatResponse` object. This includes:
346346
2. The receiving node's election time
347347
3. The receiving node's last applied OpTime
348348
4. The receiving node's last durable OpTime
349-
5. The node the receiving node thinks is primary
350-
6. The term of the receiving node
351-
7. The state of the receiving node
352-
8. The receiving node's sync source
353-
9. The receiving node's `ReplicaSetConfig` version
354-
10. Whether the receiving node is primary
349+
5. The term of the receiving node
350+
6. The state of the receiving node
351+
7. The receiving node's sync source
352+
8. The receiving node's `ReplicaSetConfig` version
353+
9. Whether the receiving node is primary
355354

356355
When the sending node receives the response to the heartbeat, it first processes its
357356
`ReplSetMetadata` like before.

src/mongo/db/repl/data_replicator_external_state_impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void DataReplicatorExternalStateImpl::processMetadata(const rpc::ReplSetMetadata
8686

8787
_replicationCoordinator->processReplSetMetadata(replMetadata);
8888

89-
if (oqMetadata.getPrimaryIndex() != rpc::OplogQueryMetadata::kNoPrimary) {
89+
if (oqMetadata.hasPrimaryIndex()) {
9090
_replicationCoordinator->cancelAndRescheduleElectionTimeout();
9191
}
9292
}

src/mongo/db/repl/oplog_fetcher.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ Status OplogFetcher::_onSuccessfulBatch(const Documents& documents) {
859859
errMsg << " (config version: " << replSetMetadata.getConfigVersion();
860860
errMsg << "; last applied optime: " << oqMetadata.getLastOpApplied().toString();
861861
errMsg << "; sync source index: " << oqMetadata.getSyncSourceIndex();
862-
errMsg << "; primary index: " << oqMetadata.getPrimaryIndex();
862+
errMsg << "; has primary index: " << oqMetadata.hasPrimaryIndex();
863863
errMsg << ") is no longer valid";
864864
errMsg << "last fetched optime: " << lastFetched.toString();
865865
return Status(ErrorCodes::InvalidSyncSource, errMsg);

src/mongo/db/repl/oplog_fetcher_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -853,8 +853,8 @@ TEST_F(OplogFetcherTest, ValidMetadataWithInResponseShouldBeForwardedToProcessMe
853853
ASSERT_TRUE(dataReplicatorExternalState->metadataWasProcessed);
854854
ASSERT_EQUALS(replSetMetadata.getIsPrimary(),
855855
dataReplicatorExternalState->replMetadataProcessed.getIsPrimary());
856-
ASSERT_EQUALS(oqMetadata.getPrimaryIndex(),
857-
dataReplicatorExternalState->oqMetadataProcessed.getPrimaryIndex());
856+
ASSERT_EQUALS(oqMetadata.hasPrimaryIndex(),
857+
dataReplicatorExternalState->oqMetadataProcessed.hasPrimaryIndex());
858858
}
859859

860860
TEST_F(OplogFetcherTest, MetadataAndBatchAreNotProcessedWhenSyncSourceRollsBack) {

src/mongo/db/repl/replication_coordinator_impl_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6388,7 +6388,7 @@ TEST_F(ReplCoordTest, PrepareOplogQueryMetadata) {
63886388
ASSERT_EQ(oqMetadata.getValue().getLastOpApplied(), optime2);
63896389
ASSERT_EQ(oqMetadata.getValue().getRBID(), 100);
63906390
ASSERT_EQ(oqMetadata.getValue().getSyncSourceIndex(), -1);
6391-
ASSERT_EQ(oqMetadata.getValue().getPrimaryIndex(), -1);
6391+
ASSERT_EQ(oqMetadata.getValue().hasPrimaryIndex(), false);
63926392

63936393
auto replMetadata = rpc::ReplSetMetadata::readFromMetadata(metadata);
63946394
ASSERT_OK(replMetadata.getStatus());

src/mongo/rpc/metadata/oplog_query_metadata.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,13 @@ class OplogQueryMetadata {
8888
}
8989

9090
/**
91-
* Returns the index of the current primary from the perspective of the sender.
92-
* Returns kNoPrimary if there is no primary.
91+
* True if the sender thinks there is a primary.
92+
*
93+
* Note: the $oplogQueryData's primaryIndex isn't safe to use, we don't know which config
94+
* version it's from. All we can safely say is whether the sender thinks there's a primary.
9395
*/
94-
int getPrimaryIndex() const {
95-
return _currentPrimaryIndex;
96+
bool hasPrimaryIndex() const {
97+
return _currentPrimaryIndex != kNoPrimary;
9698
}
9799

98100
/**

src/mongo/rpc/metadata/oplog_query_metadata_test.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ TEST(ReplResponseMetadataTest, OplogQueryMetadataRoundtrip) {
4848
ASSERT_EQ(opTime1, metadata.getLastOpCommitted().opTime);
4949
ASSERT_EQ(committedWall, metadata.getLastOpCommitted().wallTime);
5050
ASSERT_EQ(opTime2, metadata.getLastOpApplied());
51+
ASSERT_TRUE(metadata.hasPrimaryIndex());
5152

5253
BSONObjBuilder builder;
5354
metadata.writeToMetadata(&builder).transitional_ignore();
@@ -75,8 +76,8 @@ TEST(ReplResponseMetadataTest, OplogQueryMetadataRoundtrip) {
7576
ASSERT_EQ(opTime2, clonedMetadata.getLastOpApplied());
7677
ASSERT_EQ(committedWall, clonedMetadata.getLastOpCommitted().wallTime);
7778
ASSERT_EQ(metadata.getRBID(), clonedMetadata.getRBID());
78-
ASSERT_EQ(metadata.getPrimaryIndex(), clonedMetadata.getPrimaryIndex());
7979
ASSERT_EQ(metadata.getSyncSourceIndex(), clonedMetadata.getSyncSourceIndex());
80+
ASSERT_TRUE(clonedMetadata.hasPrimaryIndex());
8081

8182
BSONObjBuilder clonedBuilder;
8283
clonedMetadata.writeToMetadata(&clonedBuilder).transitional_ignore();
@@ -85,6 +86,14 @@ TEST(ReplResponseMetadataTest, OplogQueryMetadataRoundtrip) {
8586
ASSERT_BSONOBJ_EQ(expectedObj, clonedSerializedObj);
8687
}
8788

89+
TEST(ReplResponseMetadataTest, OplogQueryMetadataHasPrimaryIndex) {
90+
for (auto [currentPrimaryIndex, hasPrimaryIndex] :
91+
std::vector<std::pair<int, bool>>{{-1, false}, {0, true}, {1, true}}) {
92+
OplogQueryMetadata oqm({OpTime(), Date_t()}, OpTime(), 1, currentPrimaryIndex, -1);
93+
ASSERT_EQUALS(hasPrimaryIndex, oqm.hasPrimaryIndex());
94+
}
95+
}
96+
8897
} // unnamed namespace
8998
} // namespace rpc
9099
} // namespace mongo

0 commit comments

Comments
 (0)