summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/repl/repl_coordinator.h5
-rw-r--r--src/mongo/db/repl/repl_coordinator_external_state_mock.cpp7
-rw-r--r--src/mongo/db/repl/repl_coordinator_external_state_mock.h6
-rw-r--r--src/mongo/db/repl/repl_coordinator_hybrid.cpp7
-rw-r--r--src/mongo/db/repl/repl_coordinator_hybrid.h2
-rw-r--r--src/mongo/db/repl/repl_coordinator_impl.cpp29
-rw-r--r--src/mongo/db/repl/repl_coordinator_impl.h2
-rw-r--r--src/mongo/db/repl/repl_coordinator_impl_test.cpp75
-rw-r--r--src/mongo/db/repl/repl_coordinator_legacy.cpp9
-rw-r--r--src/mongo/db/repl/repl_coordinator_legacy.h2
-rw-r--r--src/mongo/db/repl/repl_coordinator_mock.cpp5
-rw-r--r--src/mongo/db/repl/repl_coordinator_mock.h2
-rw-r--r--src/mongo/db/repl/repl_coordinator_test_fixture.h5
-rw-r--r--src/mongo/db/write_concern.cpp11
-rw-r--r--src/mongo/db/write_concern.h3
15 files changed, 145 insertions, 25 deletions
diff --git a/src/mongo/db/repl/repl_coordinator.h b/src/mongo/db/repl/repl_coordinator.h
index 77e57f4f66d..b4d91704039 100644
--- a/src/mongo/db/repl/repl_coordinator.h
+++ b/src/mongo/db/repl/repl_coordinator.h
@@ -442,10 +442,9 @@ namespace repl {
virtual bool buildsIndexes() = 0;
/**
- * Returns a vector containing BSONObjs describing each member that has applied operation
- * at OpTime 'op'.
+ * Returns a vector of members that have applied the operation with OpTime 'op'.
*/
- virtual std::vector<BSONObj> getHostsWrittenTo(const OpTime& op) = 0;
+ virtual std::vector<HostAndPort> getHostsWrittenTo(const OpTime& op) = 0;
/**
* Returns a BSONObj containing a representation of the current default write concern.
diff --git a/src/mongo/db/repl/repl_coordinator_external_state_mock.cpp b/src/mongo/db/repl/repl_coordinator_external_state_mock.cpp
index 7a1d6486d7f..370960e7b65 100644
--- a/src/mongo/db/repl/repl_coordinator_external_state_mock.cpp
+++ b/src/mongo/db/repl/repl_coordinator_external_state_mock.cpp
@@ -68,7 +68,12 @@ namespace repl {
HostAndPort ReplicationCoordinatorExternalStateMock::getClientHostAndPort(
const OperationContext* txn) {
- return HostAndPort();
+ return _clientHostAndPort;
+ }
+
+ void ReplicationCoordinatorExternalStateMock::setClientHostAndPort(
+ const HostAndPort& clientHostAndPort) {
+ _clientHostAndPort = clientHostAndPort;
}
StatusWith<BSONObj> ReplicationCoordinatorExternalStateMock::loadLocalConfigDocument(
diff --git a/src/mongo/db/repl/repl_coordinator_external_state_mock.h b/src/mongo/db/repl/repl_coordinator_external_state_mock.h
index 950a870efc3..5519745d917 100644
--- a/src/mongo/db/repl/repl_coordinator_external_state_mock.h
+++ b/src/mongo/db/repl/repl_coordinator_external_state_mock.h
@@ -67,10 +67,16 @@ namespace repl {
*/
void setLocalConfigDocument(const StatusWith<BSONObj>& localConfigDocument);
+ /**
+ * Sets the return value for subsequent calls to getClientHostAndPort().
+ */
+ void setClientHostAndPort(const HostAndPort& clientHostAndPort);
+
private:
StatusWith<BSONObj> _localRsConfigDocument;
std::vector<HostAndPort> _selfHosts;
bool _connectionsClosed;
+ HostAndPort _clientHostAndPort;
};
} // namespace repl
diff --git a/src/mongo/db/repl/repl_coordinator_hybrid.cpp b/src/mongo/db/repl/repl_coordinator_hybrid.cpp
index 2c5cddbf9dc..f8c9f1241d1 100644
--- a/src/mongo/db/repl/repl_coordinator_hybrid.cpp
+++ b/src/mongo/db/repl/repl_coordinator_hybrid.cpp
@@ -376,10 +376,9 @@ namespace repl {
return legacyResponse;
}
- vector<BSONObj> HybridReplicationCoordinator::getHostsWrittenTo(const OpTime& op) {
- vector<BSONObj> legacyResponse = _legacy.getHostsWrittenTo(op);
- vector<BSONObj> implResponse = _impl.getHostsWrittenTo(op);
- return legacyResponse;
+ vector<HostAndPort> HybridReplicationCoordinator::getHostsWrittenTo(const OpTime& op) {
+ vector<HostAndPort> implResponse = _impl.getHostsWrittenTo(op);
+ return implResponse;
}
Status HybridReplicationCoordinator::checkIfWriteConcernCanBeSatisfied(
diff --git a/src/mongo/db/repl/repl_coordinator_hybrid.h b/src/mongo/db/repl/repl_coordinator_hybrid.h
index cede8b8c9fb..6fddbc99ba8 100644
--- a/src/mongo/db/repl/repl_coordinator_hybrid.h
+++ b/src/mongo/db/repl/repl_coordinator_hybrid.h
@@ -153,7 +153,7 @@ namespace repl {
virtual bool buildsIndexes();
- virtual std::vector<BSONObj> getHostsWrittenTo(const OpTime& op);
+ virtual std::vector<HostAndPort> getHostsWrittenTo(const OpTime& op);
virtual BSONObj getGetLastErrorDefault();
diff --git a/src/mongo/db/repl/repl_coordinator_impl.cpp b/src/mongo/db/repl/repl_coordinator_impl.cpp
index 8d12a1d5c2c..bc0ff5fedd5 100644
--- a/src/mongo/db/repl/repl_coordinator_impl.cpp
+++ b/src/mongo/db/repl/repl_coordinator_impl.cpp
@@ -1215,9 +1215,32 @@ namespace {
return self.shouldBuildIndexes();
}
- std::vector<BSONObj> ReplicationCoordinatorImpl::getHostsWrittenTo(const OpTime& op) {
- // TODO
- return std::vector<BSONObj>();
+ std::vector<HostAndPort> ReplicationCoordinatorImpl::getHostsWrittenTo(const OpTime& op) {
+ std::vector<HostAndPort> hosts;
+ boost::lock_guard<boost::mutex> lk(_mutex);
+ for (SlaveInfoMap::const_iterator it = _slaveInfoMap.begin();
+ it != _slaveInfoMap.end(); ++it) {
+ const SlaveInfo& slaveInfo = it->second;
+ if (slaveInfo.opTime < op) {
+ continue;
+ }
+ if (_getReplicationMode_inlock() == modeReplSet) {
+ const MemberConfig* memberConfig = _rsConfig.findMemberByID(slaveInfo.memberID);
+ if (!memberConfig) {
+ // Node might have been removed in a reconfig
+ continue;
+ }
+ hosts.push_back(memberConfig->getHostAndPort());
+ }
+ else {
+ if (it->first == _getMyRID_inlock()) {
+ // Master-slave doesn't know the HostAndPort for itself at this point.
+ continue;
+ }
+ hosts.push_back(slaveInfo.hostAndPort);
+ }
+ }
+ return hosts;
}
Status ReplicationCoordinatorImpl::checkIfWriteConcernCanBeSatisfied(
diff --git a/src/mongo/db/repl/repl_coordinator_impl.h b/src/mongo/db/repl/repl_coordinator_impl.h
index 7ecb7022f62..50a25d13f84 100644
--- a/src/mongo/db/repl/repl_coordinator_impl.h
+++ b/src/mongo/db/repl/repl_coordinator_impl.h
@@ -187,7 +187,7 @@ namespace repl {
virtual bool buildsIndexes();
- virtual std::vector<BSONObj> getHostsWrittenTo(const OpTime& op);
+ virtual std::vector<HostAndPort> getHostsWrittenTo(const OpTime& op);
virtual BSONObj getGetLastErrorDefault();
diff --git a/src/mongo/db/repl/repl_coordinator_impl_test.cpp b/src/mongo/db/repl/repl_coordinator_impl_test.cpp
index 63a0661213c..2c63a066766 100644
--- a/src/mongo/db/repl/repl_coordinator_impl_test.cpp
+++ b/src/mongo/db/repl/repl_coordinator_impl_test.cpp
@@ -1054,7 +1054,80 @@ namespace {
ASSERT_OK(getReplCoord()->setMaintenanceMode(&txn, false));
}
- // TODO(spencer): Unit test replSetFreeze
+ TEST_F(ReplCoordTest, GetHostsWrittenToReplSet) {
+ HostAndPort myHost("node1:12345");
+ HostAndPort client1Host("node2:12345");
+ HostAndPort client2Host("node3:12345") ;
+ assertStartSuccess(
+ BSON("_id" << "mySet" <<
+ "version" << 2 <<
+ "members" << BSON_ARRAY(BSON("_id" << 0 << "host" << myHost.toString()) <<
+ BSON("_id" << 1 << "host" << client1Host.toString()) <<
+ BSON("_id" << 2 << "host" << client2Host.toString()))),
+ HostAndPort("node1", 12345));
+ OperationContextNoop txn;
+
+ OID myRID = getReplCoord()->getMyRID();
+ OID client1 = OID::gen();
+ OID client2 = OID::gen();
+ OpTime time1(1, 1);
+ OpTime time2(1, 2);
+
+ HandshakeArgs handshake1;
+ ASSERT_OK(handshake1.initialize(BSON("handshake" << client1 << "member" << 1)));
+ ASSERT_OK(getReplCoord()->processHandshake(&txn, handshake1));
+ HandshakeArgs handshake2;
+ ASSERT_OK(handshake2.initialize(BSON("handshake" << client2 << "member" << 2)));
+ ASSERT_OK(getReplCoord()->processHandshake(&txn, handshake2));
+
+ ASSERT_OK(getReplCoord()->setLastOptime(&txn, myRID, time2));
+ ASSERT_OK(getReplCoord()->setLastOptime(&txn, client1, time1));
+
+ std::vector<HostAndPort> caughtUpHosts = getReplCoord()->getHostsWrittenTo(time2);
+ ASSERT_EQUALS(1U, caughtUpHosts.size());
+ ASSERT_EQUALS(myHost, caughtUpHosts[0]);
+
+ ASSERT_OK(getReplCoord()->setLastOptime(&txn, client2, time2));
+ caughtUpHosts = getReplCoord()->getHostsWrittenTo(time2);
+ ASSERT_EQUALS(2U, caughtUpHosts.size());
+ if (myHost == caughtUpHosts[0]) {
+ ASSERT_EQUALS(client2Host, caughtUpHosts[1]);
+ }
+ else {
+ ASSERT_EQUALS(client2Host, caughtUpHosts[0]);
+ ASSERT_EQUALS(myHost, caughtUpHosts[1]);
+ }
+ }
+
+ TEST_F(ReplCoordTest, GetHostsWrittenToMasterSlave) {
+ ReplSettings settings;
+ settings.master = true;
+ init(settings);
+ HostAndPort clientHost("node2:12345");
+ OperationContextNoop txn;
+
+ OID myRID = getReplCoord()->getMyRID();
+ OID client = OID::gen();
+ OpTime time1(1, 1);
+ OpTime time2(1, 2);
+
+ getExternalState()->setClientHostAndPort(clientHost);
+ HandshakeArgs handshake;
+ ASSERT_OK(handshake.initialize(BSON("handshake" << client)));
+ ASSERT_OK(getReplCoord()->processHandshake(&txn, handshake));
+
+ ASSERT_OK(getReplCoord()->setLastOptime(&txn, myRID, time2));
+ ASSERT_OK(getReplCoord()->setLastOptime(&txn, client, time1));
+
+ std::vector<HostAndPort> caughtUpHosts = getReplCoord()->getHostsWrittenTo(time2);
+ ASSERT_EQUALS(0U, caughtUpHosts.size()); // self doesn't get included in master-slave
+
+ ASSERT_OK(getReplCoord()->setLastOptime(&txn, client, time2));
+ caughtUpHosts = getReplCoord()->getHostsWrittenTo(time2);
+ ASSERT_EQUALS(1U, caughtUpHosts.size());
+ ASSERT_EQUALS(clientHost, caughtUpHosts[0]);
+ }
+
// TODO(schwerin): Unit test election id updating
} // namespace
diff --git a/src/mongo/db/repl/repl_coordinator_legacy.cpp b/src/mongo/db/repl/repl_coordinator_legacy.cpp
index b4557f608b5..060f78d8d5f 100644
--- a/src/mongo/db/repl/repl_coordinator_legacy.cpp
+++ b/src/mongo/db/repl/repl_coordinator_legacy.cpp
@@ -953,8 +953,13 @@ namespace {
return theReplSet->buildIndexes();
}
- vector<BSONObj> LegacyReplicationCoordinator::getHostsWrittenTo(const OpTime& op) {
- return repl::getHostsWrittenTo(op);
+ vector<HostAndPort> LegacyReplicationCoordinator::getHostsWrittenTo(const OpTime& op) {
+ vector<BSONObj> configs = repl::getHostsWrittenTo(op);
+ vector<HostAndPort> hosts;
+ for (size_t i = 0; i < configs.size(); ++i) {
+ hosts.push_back(HostAndPort(configs[i]["host"].String()));
+ }
+ return hosts;
}
Status LegacyReplicationCoordinator::checkIfWriteConcernCanBeSatisfied(
diff --git a/src/mongo/db/repl/repl_coordinator_legacy.h b/src/mongo/db/repl/repl_coordinator_legacy.h
index 415a8cfe175..581e7fd7432 100644
--- a/src/mongo/db/repl/repl_coordinator_legacy.h
+++ b/src/mongo/db/repl/repl_coordinator_legacy.h
@@ -149,7 +149,7 @@ namespace repl {
virtual bool buildsIndexes();
- virtual std::vector<BSONObj> getHostsWrittenTo(const OpTime& op);
+ virtual std::vector<HostAndPort> getHostsWrittenTo(const OpTime& op);
virtual BSONObj getGetLastErrorDefault();
diff --git a/src/mongo/db/repl/repl_coordinator_mock.cpp b/src/mongo/db/repl/repl_coordinator_mock.cpp
index 6c4e5828595..bafad53ca68 100644
--- a/src/mongo/db/repl/repl_coordinator_mock.cpp
+++ b/src/mongo/db/repl/repl_coordinator_mock.cpp
@@ -230,9 +230,8 @@ namespace repl {
return false;
}
- std::vector<BSONObj> ReplicationCoordinatorMock::getHostsWrittenTo(const OpTime& op) {
- // TODO
- return std::vector<BSONObj>();
+ std::vector<HostAndPort> ReplicationCoordinatorMock::getHostsWrittenTo(const OpTime& op) {
+ return std::vector<HostAndPort>();
}
Status ReplicationCoordinatorMock::checkIfWriteConcernCanBeSatisfied(
diff --git a/src/mongo/db/repl/repl_coordinator_mock.h b/src/mongo/db/repl/repl_coordinator_mock.h
index 53f045c4443..aa3bfec4bd9 100644
--- a/src/mongo/db/repl/repl_coordinator_mock.h
+++ b/src/mongo/db/repl/repl_coordinator_mock.h
@@ -150,7 +150,7 @@ namespace repl {
virtual bool buildsIndexes();
- virtual std::vector<BSONObj> getHostsWrittenTo(const OpTime& op);
+ virtual std::vector<HostAndPort> getHostsWrittenTo(const OpTime& op);
virtual BSONObj getGetLastErrorDefault();
diff --git a/src/mongo/db/repl/repl_coordinator_test_fixture.h b/src/mongo/db/repl/repl_coordinator_test_fixture.h
index d636b5a61eb..5529572c7a6 100644
--- a/src/mongo/db/repl/repl_coordinator_test_fixture.h
+++ b/src/mongo/db/repl/repl_coordinator_test_fixture.h
@@ -82,6 +82,11 @@ namespace repl {
TopologyCoordinatorImpl& getTopoCoord() { return *_topo;}
/**
+ * Gets the external state used by the replication coordinator under test.
+ */
+ ReplicationCoordinatorExternalStateMock* getExternalState() { return _externalState; }
+
+ /**
* Initializes the objects under test; this behavior is optional, in case you need to call
* any methods on the network or coordinator objects before calling start.
*/
diff --git a/src/mongo/db/write_concern.cpp b/src/mongo/db/write_concern.cpp
index 3aaefead488..90fe69b947b 100644
--- a/src/mongo/db/write_concern.cpp
+++ b/src/mongo/db/write_concern.cpp
@@ -105,10 +105,15 @@ namespace mongo {
if ( wTimedOut )
result->appendBool( "wtimeout", true );
- if ( writtenTo.size() )
- result->append( "writtenTo", writtenTo );
- else
+ if (writtenTo.size()) {
+ BSONArrayBuilder hosts(result->subarrayStart("writtenTo"));
+ for (size_t i = 0; i < writtenTo.size(); ++i) {
+ hosts.append(writtenTo[i].toString());
+ }
+ }
+ else {
result->appendNull( "writtenTo" );
+ }
if ( err.empty() )
result->appendNull( "err" );
diff --git a/src/mongo/db/write_concern.h b/src/mongo/db/write_concern.h
index 6e4a1c30087..98d7893a2e1 100644
--- a/src/mongo/db/write_concern.h
+++ b/src/mongo/db/write_concern.h
@@ -29,6 +29,7 @@
#pragma once
#include "mongo/db/write_concern_options.h"
+#include "mongo/util/net/hostandport.h"
namespace mongo {
@@ -59,7 +60,7 @@ namespace mongo {
bool wTimedOut;
int wTime;
- std::vector<BSONObj> writtenTo;
+ std::vector<HostAndPort> writtenTo;
std::string err; // this is the old err field, should deprecate
};