summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2016-05-27 10:11:21 -0400
committerJudah Schvimer <judah@mongodb.com>2016-05-27 10:11:21 -0400
commit9b3fc54ceb6d1066e423f7c562c22de2f5c6480e (patch)
tree26153960ba47738da06b62bde700fabb2061539d
parentd5a2826989b0e5ae268ba9cc4226611d7c83c207 (diff)
downloadmongo-9b3fc54ceb6d1066e423f7c562c22de2f5c6480e.tar.gz
SERVER-23698 Removed ability to run replSetInitiate if not started as a replica set node
-rw-r--r--jstests/replsets/initiate_without_replset_name_at_startup.js180
-rw-r--r--src/mongo/db/repl/oplog.cpp60
-rw-r--r--src/mongo/db/repl/oplog.h18
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state.h7
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.cpp26
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.h4
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_mock.cpp3
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_mock.h4
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp75
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_test.cpp138
-rw-r--r--src/mongo/db/repl/replset_commands.cpp8
11 files changed, 63 insertions, 460 deletions
diff --git a/jstests/replsets/initiate_without_replset_name_at_startup.js b/jstests/replsets/initiate_without_replset_name_at_startup.js
deleted file mode 100644
index a21467768e0..00000000000
--- a/jstests/replsets/initiate_without_replset_name_at_startup.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * If a node is started with --configsvr but without --replSet, and it has neither an oplog nor a
- * local replica set config document, the operator should be able to run replSetInitiate to create
- * a single-node replica set configuration and to prime the oplog. Then, on restart if the operator
- * adds --replSet to the startup configuration directives, the node can immediately transition into
- * PRIMARY rather than waiting in STARTUP for the operator to run replSetInitiate. This should
- * only be allowed for single-node replica set configurations.
- *
- * This test cannot be run on ephemeral storage engines, since their replica set config document
- * will not persist across a restart and they will not transition to PRIMARY as described above.
- * @tags: [requires_persistence]
- */
-(function() {
- "use strict";
-
- var baseName = 'testInitiateWithoutReplSetNameAtStartup';
- var port = allocatePorts(1)[0];
- var dbpath = MongoRunner.dataPath + baseName + '/';
-
- var mongod = MongoRunner.runMongod({dbpath: dbpath, port: port});
-
- var config = {
- _id: baseName,
- version: 1,
- members: [{_id: 0, host: mongod.name}, ],
- };
-
- var result = assert.commandFailedWithCode(
- mongod.getDB('admin').runCommand({replSetInitiate: config}),
- ErrorCodes.NoReplicationEnabled,
- 'replSetInitiate should fail when both --configsvr and --replSet are missing.');
- assert(result.errmsg.match(/This node was not started with the replSet option/),
- 'unexpected error message when both --configsvr and --replSet are missing. ' +
- 'configuration: ' + tojson(result));
-
- // The rest of this test can only be run if the storageEngine supports committed reads.
- var supportsCommittedReads =
- mongod.getDB('admin').serverStatus().storageEngine.supportsCommittedReads;
-
- MongoRunner.stopMongod(port);
-
- if (!supportsCommittedReads) {
- jsTestLog('Skipping rest of test because storage engine does not support committed reads');
- return;
- }
-
- mongod = MongoRunner.runMongod({configsvr: '', dbpath: dbpath, port: port, restart: true});
-
- assert.commandWorked(mongod.getDB('admin').runCommand({replSetInitiate: config}),
- 'replSetInitiate should not fail when given a valid configuration');
-
- // Check saved config
- var systemReplsetCollection = mongod.getDB('local').system.replset;
- assert.eq(
- 1,
- systemReplsetCollection.count(),
- 'replSetInitiate did not save configuration in ' + systemReplsetCollection.getFullName());
- var savedConfig = systemReplsetCollection.findOne();
- assert.eq(config._id,
- savedConfig._id,
- 'config passed to replSetInitiate (left side) does not match config saved in ' +
- systemReplsetCollection.getFullName() + ' (right side)');
-
- result = assert.commandFailedWithCode(
- mongod.getDB('admin').runCommand({
- replSetInitiate: {
- _id: baseName + '-2',
- version: 1,
- members: [{_id: 0, host: mongod.name}, ],
- }
- }),
- ErrorCodes.AlreadyInitialized,
- 'expected AlreadyInitialized error code when configuration already exists in ' +
- systemReplsetCollection.getFullName());
- assert(
- result.errmsg.match(/already initialized/),
- 'unexpected error message when replica set configuration already exists ' + tojson(result));
- systemReplsetCollection = mongod.getDB('local').system.replset;
- savedConfig = systemReplsetCollection.findOne();
- assert.eq(config._id,
- savedConfig._id,
- 'config passed to replSetInitiate (left side) does not match config saved in ' +
- systemReplsetCollection.getFullName() + ' (right side)');
-
- var oplogCollection = mongod.getDB('local').oplog.rs;
- assert(oplogCollection.exists(),
- 'oplog collection ' + oplogCollection.getFullName() +
- ' not created after successful replSetInitiate. Collections in local database: ' +
- mongod.getDB('local').getCollectionNames().join(', '));
- assert(oplogCollection.isCapped(),
- 'oplog collection ' + oplogCollection.getFullName() + ' must be capped');
- assert.eq(1,
- oplogCollection.count(),
- 'oplog collection ' + oplogCollection.getFullName() +
- ' is not initialized with first entry.');
- var oplogEntry = oplogCollection.findOne();
- assert.eq('n', oplogEntry.op, 'unexpected first oplog entry type: ' + tojson(oplogEntry));
-
- MongoRunner.stopMongod(port);
-
- // Restart server and attempt to save a different config.
- mongod = MongoRunner.runMongod({configsvr: '', dbpath: dbpath, port: port, restart: true});
- result = assert.commandFailedWithCode(
- mongod.getDB('admin').runCommand({
- replSetInitiate: {
- _id: baseName + '-2',
- version: 1,
- members: [{_id: 0, host: mongod.name}, ],
- }
- }),
- ErrorCodes.AlreadyInitialized,
- 'expected AlreadyInitialized error code when configuration already exists in ' +
- systemReplsetCollection.getFullName() + ' after restarting');
- assert(result.errmsg.match(/already initialized/),
- 'unexpected error message when replica set configuration already exists ' +
- '(after restarting without --replSet): ' + tojson(result));
- systemReplsetCollection = mongod.getDB('local').system.replset;
- savedConfig = systemReplsetCollection.findOne();
- assert.eq(config._id,
- savedConfig._id,
- 'config passed to replSetInitiate (left side) does not match config saved in ' +
- systemReplsetCollection.getFullName() + ' (right side)');
-
- MongoRunner.stopMongod(port);
-
- // Restart server with --replSet and check own replica member state.
- mongod = MongoRunner.runMongod(
- {configsvr: '', dbpath: dbpath, port: port, replSet: config._id, restart: true});
-
- // Wait for member state to become PRIMARY.
- assert.soon(
- function() {
- result = mongod.getDB('admin').runCommand({replSetGetStatus: 1});
- if (result.ok !== 1) {
- // Command might fail if we are still loading the config for replset.
- return false;
- }
- assert.eq(
- 1, result.members.length, 'replica set status should contain exactly 1 member');
- var member = result.members[0];
- print('Current replica member state = ' + member.state + ' (' + member.stateStr + ')');
- return member.state == ReplSetTest.State.PRIMARY;
- },
- 'Replica set member state did not reach PRIMARY after starting up with --replSet option',
- 5000,
- 1000);
-
- // Write/read a single document to ensure basic functionality.
- var t = mongod.getDB('config').getCollection(baseName);
- var doc = {
- _id: 0
- };
- assert.soon(function() {
- result = t.save(doc);
- assert(result instanceof WriteResult);
- if (result.hasWriteError()) {
- print('Failed with write error saving document after transitioning to primary: ' +
- tojson(result) + '. Retrying...');
- return false;
- }
- if (result.hasWriteConcernError()) {
- print('Failed with write concern error saving document after transitioning to ' +
- 'primary: ' + tojson(result) + '. Retrying...');
- return false;
- }
- print('Successfully saved document after transitioning to primary: ' + tojson(result));
- return true;
- }, 'failed to save document after transitioning to primary', 5000, 1000);
-
- assert.eq(1, t.count(), 'incorrect collection size after successful write');
- assert.eq(doc, t.findOne());
-
- oplogCollection = mongod.getDB('local').oplog.rs;
- oplogEntry = oplogCollection.find().sort({$natural: -1}).limit(1).next();
- assert.eq('i', oplogEntry.op, 'unexpected optype for insert oplog entry');
- assert.eq(t.getFullName(), oplogEntry.ns, 'unexpected namespace for insert oplog entry');
- assert.eq(doc, oplogEntry.o, 'unexpected embedded object for insert oplog entry');
-
- MongoRunner.stopMongod(port);
-}());
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index b59d8b2a75e..0d66d00aad6 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -363,7 +363,6 @@ void _logOpsInner(OperationContext* txn,
size_t nWriters,
Collection* oplogCollection,
ReplicationCoordinator::Mode replicationMode,
- bool updateReplOpTime,
OpTime finalOpTime) {
ReplicationCoordinator* replCoord = getGlobalReplicationCoordinator();
@@ -378,36 +377,32 @@ void _logOpsInner(OperationContext* txn,
checkOplogInsert(oplogCollection->insertDocumentsForOplog(txn, writers, nWriters));
// Set replCoord last optime only after we're sure the WUOW didn't abort and roll back.
- if (updateReplOpTime) {
- txn->recoveryUnit()->onCommit(
- [replCoord, finalOpTime] { replCoord->setMyLastAppliedOpTimeForward(finalOpTime); });
- }
+ txn->recoveryUnit()->onCommit(
+ [replCoord, finalOpTime] { replCoord->setMyLastAppliedOpTimeForward(finalOpTime); });
ReplClientInfo::forClient(txn->getClient()).setLastOp(finalOpTime);
}
-void _logOp(OperationContext* txn,
- const char* opstr,
- const char* ns,
- const BSONObj& obj,
- const BSONObj* o2,
- bool fromMigrate,
- const std::string& oplogName,
- ReplicationCoordinator::Mode replMode,
- bool updateOpTime) {
+void logOp(OperationContext* txn,
+ const char* opstr,
+ const char* ns,
+ const BSONObj& obj,
+ const BSONObj* o2,
+ bool fromMigrate) {
+ ReplicationCoordinator::Mode replMode = ReplicationCoordinator::get(txn)->getReplicationMode();
NamespaceString nss(ns);
if (oplogDisabled(txn, replMode, nss))
return;
ReplicationCoordinator* replCoord = getGlobalReplicationCoordinator();
- Collection* oplog = getLocalOplogCollection(txn, oplogName);
+ Collection* oplog = getLocalOplogCollection(txn, _oplogCollectionName);
Lock::DBLock lk(txn->lockState(), "local", MODE_IX);
- Lock::CollectionLock lock(txn->lockState(), oplogName, MODE_IX);
+ Lock::CollectionLock lock(txn->lockState(), _oplogCollectionName, MODE_IX);
OplogSlot slot;
getNextOpTime(txn, oplog, replCoord, replMode, 1, &slot);
auto writer = _logOpWriter(txn, opstr, nss, obj, o2, fromMigrate, slot.opTime, slot.hash);
const DocWriter* basePtr = &writer;
- _logOpsInner(txn, nss, &basePtr, 1, oplog, replMode, updateOpTime, slot.opTime);
+ _logOpsInner(txn, nss, &basePtr, 1, oplog, replMode, slot.opTime);
}
void logOps(OperationContext* txn,
@@ -440,20 +435,10 @@ void logOps(OperationContext* txn,
for (size_t i = 0; i < count; i++) {
basePtrs[i] = &writers[i];
}
- _logOpsInner(txn, nss, basePtrs.get(), count, oplog, replMode, true, slots[count - 1].opTime);
+ _logOpsInner(txn, nss, basePtrs.get(), count, oplog, replMode, slots[count - 1].opTime);
}
-void logOp(OperationContext* txn,
- const char* opstr,
- const char* ns,
- const BSONObj& obj,
- const BSONObj* o2,
- bool fromMigrate) {
- ReplicationCoordinator::Mode replMode = ReplicationCoordinator::get(txn)->getReplicationMode();
- _logOp(txn, opstr, ns, obj, o2, fromMigrate, _oplogCollectionName, replMode, true);
-}
-
OpTime writeOpsToOplog(OperationContext* txn, const std::vector<BSONObj>& ops) {
OpTime lastOptime;
MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
@@ -532,14 +517,15 @@ long long getNewOplogSizeBytes(OperationContext* txn, const ReplSettings& replSe
}
} // namespace
-void createOplog(OperationContext* txn, const std::string& oplogCollectionName, bool replEnabled) {
+void createOplog(OperationContext* txn) {
ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
const ReplSettings& replSettings = ReplicationCoordinator::get(txn)->getSettings();
+ bool replEnabled = replSettings.usingReplSets();
- OldClientContext ctx(txn, oplogCollectionName);
- Collection* collection = ctx.db()->getCollection(oplogCollectionName);
+ OldClientContext ctx(txn, _oplogCollectionName);
+ Collection* collection = ctx.db()->getCollection(_oplogCollectionName);
if (collection) {
if (replSettings.getOplogSizeBytes() != 0) {
@@ -558,7 +544,7 @@ void createOplog(OperationContext* txn, const std::string& oplogCollectionName,
}
if (!replEnabled)
- initTimestampFromOplog(txn, oplogCollectionName);
+ initTimestampFromOplog(txn, _oplogCollectionName);
return;
}
@@ -575,12 +561,12 @@ void createOplog(OperationContext* txn, const std::string& oplogCollectionName,
MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
WriteUnitOfWork uow(txn);
- invariant(ctx.db()->createCollection(txn, oplogCollectionName, options));
+ invariant(ctx.db()->createCollection(txn, _oplogCollectionName, options));
if (!replEnabled)
getGlobalServiceContext()->getOpObserver()->onOpMessage(txn, BSONObj());
uow.commit();
}
- MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "createCollection", oplogCollectionName);
+ MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "createCollection", _oplogCollectionName);
/* sync here so we don't get any surprising lag later when we try to sync */
StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
@@ -588,12 +574,6 @@ void createOplog(OperationContext* txn, const std::string& oplogCollectionName,
log() << "******" << endl;
}
-void createOplog(OperationContext* txn) {
- const auto replEnabled = ReplicationCoordinator::get(txn)->getReplicationMode() ==
- ReplicationCoordinator::modeReplSet;
- createOplog(txn, _oplogCollectionName, replEnabled);
-}
-
// -------------------------------------
namespace {
diff --git a/src/mongo/db/repl/oplog.h b/src/mongo/db/repl/oplog.h
index b8182448997..d009083c709 100644
--- a/src/mongo/db/repl/oplog.h
+++ b/src/mongo/db/repl/oplog.h
@@ -58,12 +58,6 @@ class ReplSettings;
*/
void truncateOplogTo(OperationContext* txn, Timestamp truncateTimestamp);
-/**
- * Create a new capped collection for the oplog if it doesn't yet exist.
- * If the collection already exists, set the 'last' OpTime if master/slave (side effect!)
- */
-void createOplog(OperationContext* txn, const std::string& oplogCollectionName, bool replEnabled);
-
/*
* Create a new capped collection for the oplog using createOplog() if it doesn't yet exist.
* Collection name will be "_oplogCollectionName" initialized in setOplogCollectionName().
@@ -102,19 +96,7 @@ void logOps(OperationContext* txn,
/* For 'u' records, 'obj' captures the mutation made to the object but not
* the object itself. 'o2' captures the the criteria for the object that will be modified.
- *
- * Sets replCoord last optime if 'updateReplOpTime' is true.
*/
-void _logOp(OperationContext* txn,
- const char* opstr,
- const char* ns,
- const BSONObj& obj,
- const BSONObj* o2,
- bool fromMigrate,
- const std::string& oplogCollectionName,
- ReplicationCoordinator::Mode replicationMode,
- bool updateReplOpTime);
-
void logOp(OperationContext* txn,
const char* opstr,
const char* ns,
diff --git a/src/mongo/db/repl/replication_coordinator_external_state.h b/src/mongo/db/repl/replication_coordinator_external_state.h
index 4a58018474a..3fc7913e3b4 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state.h
@@ -104,12 +104,9 @@ public:
virtual void shutdown() = 0;
/**
- * Creates the oplog, writes the first entry and stores the replica set config document. Sets
- * replCoord last optime if 'updateReplOpTime' is true.
+ * Creates the oplog, writes the first entry and stores the replica set config document.
*/
- virtual Status initializeReplSetStorage(OperationContext* txn,
- const BSONObj& config,
- bool updateReplOpTime) = 0;
+ virtual Status initializeReplSetStorage(OperationContext* txn, const BSONObj& config) = 0;
/**
* Writes a message about our transition to primary to the oplog.
diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
index d7e413b590e..e705fd17c9d 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
@@ -180,10 +180,9 @@ void ReplicationCoordinatorExternalStateImpl::shutdown() {
}
Status ReplicationCoordinatorExternalStateImpl::initializeReplSetStorage(OperationContext* txn,
- const BSONObj& config,
- bool updateReplOpTime) {
+ const BSONObj& config) {
try {
- createOplog(txn, rsOplogName, true);
+ createOplog(txn);
MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
ScopedTransaction scopedXact(txn, MODE_X);
@@ -193,26 +192,7 @@ Status ReplicationCoordinatorExternalStateImpl::initializeReplSetStorage(Operati
Helpers::putSingleton(txn, configCollectionName, config);
const auto msgObj = BSON("msg"
<< "initiating set");
- if (updateReplOpTime) {
- getGlobalServiceContext()->getOpObserver()->onOpMessage(txn, msgObj);
- } else {
- // 'updateReplOpTime' is false when called from the replSetInitiate command when the
- // server is running with replication disabled. We bypass onOpMessage to invoke
- // _logOp directly so that we can override the replication mode and keep _logO from
- // updating the replication coordinator's op time (illegal operation when
- // replication is not enabled).
- repl::oplogCheckCloseDatabase(txn, nullptr);
- repl::_logOp(txn,
- "n",
- "",
- msgObj,
- nullptr,
- false,
- rsOplogName,
- ReplicationCoordinator::modeReplSet,
- updateReplOpTime);
- repl::oplogCheckCloseDatabase(txn, nullptr);
- }
+ getGlobalServiceContext()->getOpObserver()->onOpMessage(txn, msgObj);
wuow.commit();
}
MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "initiate oplog entry", "local.oplog.rs");
diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.h b/src/mongo/db/repl/replication_coordinator_external_state_impl.h
index a74976dbc5e..4ddac22d4a1 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.h
@@ -58,9 +58,7 @@ public:
virtual void startMasterSlave(OperationContext* txn);
virtual void shutdown();
- virtual Status initializeReplSetStorage(OperationContext* txn,
- const BSONObj& config,
- bool updateReplOpTime);
+ virtual Status initializeReplSetStorage(OperationContext* txn, const BSONObj& config);
virtual void logTransitionToPrimaryToOplog(OperationContext* txn);
virtual void forwardSlaveProgress();
virtual OID ensureMe(OperationContext* txn);
diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
index 2d7736def87..36b4ec96d01 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
@@ -65,8 +65,7 @@ void ReplicationCoordinatorExternalStateMock::startSteadyStateReplication() {}
void ReplicationCoordinatorExternalStateMock::startMasterSlave(OperationContext*) {}
Status ReplicationCoordinatorExternalStateMock::initializeReplSetStorage(OperationContext* txn,
- const BSONObj& config,
- bool updateReplOpTime) {
+ const BSONObj& config) {
return storeLocalConfigDocument(txn, config);
}
diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.h b/src/mongo/db/repl/replication_coordinator_external_state_mock.h
index 049f39745c8..898edb0d125 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_mock.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.h
@@ -58,9 +58,7 @@ public:
virtual void startSteadyStateReplication() override;
virtual void startMasterSlave(OperationContext*);
virtual void shutdown();
- virtual Status initializeReplSetStorage(OperationContext* txn,
- const BSONObj& config,
- bool updateReplOpTime);
+ virtual Status initializeReplSetStorage(OperationContext* txn, const BSONObj& config);
virtual void logTransitionToPrimaryToOplog(OperationContext* txn);
virtual void forwardSlaveProgress();
virtual OID ensureMe(OperationContext*);
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 3b5319b8cc7..172f10b8a08 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -2314,25 +2314,21 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* txn,
BSONObjBuilder* resultObj) {
log() << "replSetInitiate admin command received from client";
- // Skip config state changes if server is not running with replication enabled.
const auto replEnabled = _settings.usingReplSets();
stdx::unique_lock<stdx::mutex> lk(_mutex);
- if (replEnabled) {
- while (_rsConfigState == kConfigPreStart || _rsConfigState == kConfigStartingUp) {
- _rsConfigStateChange.wait(lk);
- }
+ if (!replEnabled) {
+ return Status(ErrorCodes::NoReplicationEnabled, "server is not running with --replSet");
+ }
+ while (_rsConfigState == kConfigPreStart || _rsConfigState == kConfigStartingUp) {
+ _rsConfigStateChange.wait(lk);
+ }
- if (_rsConfigState != kConfigUninitialized) {
- resultObj->append("info",
- "try querying local.system.replset to see current configuration");
- return Status(ErrorCodes::AlreadyInitialized, "already initialized");
- }
- invariant(!_rsConfig.isInitialized());
- _setConfigState_inlock(kConfigInitiating);
- } else if (_externalState->loadLocalConfigDocument(txn).isOK()) {
+ if (_rsConfigState != kConfigUninitialized) {
resultObj->append("info", "try querying local.system.replset to see current configuration");
return Status(ErrorCodes::AlreadyInitialized, "already initialized");
}
+ invariant(!_rsConfig.isInitialized());
+ _setConfigState_inlock(kConfigInitiating);
ScopeGuard configStateGuard = MakeGuard(
lockAndCall,
@@ -2341,17 +2337,13 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* txn,
&ReplicationCoordinatorImpl::_setConfigState_inlock, this, kConfigUninitialized));
lk.unlock();
- if (!replEnabled) {
- configStateGuard.Dismiss();
- }
-
ReplicaSetConfig newConfig;
Status status = newConfig.initializeForInitiate(configObj, true);
if (!status.isOK()) {
error() << "replSet initiate got " << status << " while parsing " << configObj;
return Status(ErrorCodes::InvalidReplicaSetConfig, status.reason());
}
- if (replEnabled && newConfig.getReplSetName() != _settings.ourSetName()) {
+ if (newConfig.getReplSetName() != _settings.ourSetName()) {
str::stream errmsg;
errmsg << "Attempting to initiate a replica set with name " << newConfig.getReplSetName()
<< ", but command line reports " << _settings.ourSetName() << "; rejecting";
@@ -2366,51 +2358,38 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* txn,
return Status(ErrorCodes::InvalidReplicaSetConfig, myIndex.getStatus().reason());
}
- if (!replEnabled && newConfig.getNumMembers() != 1) {
- str::stream errmsg;
- errmsg << "When replication is not enabled (no --replSet option) you can only specify one "
- << "member in the config. " << newConfig.getNumMembers() << " members found in"
- << "configuration: " << newConfig.toBSON();
- error() << std::string(errmsg);
- return Status(ErrorCodes::InvalidReplicaSetConfig, errmsg);
- }
-
log() << "replSetInitiate config object with " << newConfig.getNumMembers()
<< " members parses ok";
- if (replEnabled) {
- status = checkQuorumForInitiate(&_replExecutor, newConfig, myIndex.getValue());
+ status = checkQuorumForInitiate(&_replExecutor, newConfig, myIndex.getValue());
- if (!status.isOK()) {
- error() << "replSetInitiate failed; " << status;
- return status;
- }
+ if (!status.isOK()) {
+ error() << "replSetInitiate failed; " << status;
+ return status;
}
- status = _externalState->initializeReplSetStorage(txn, newConfig.toBSON(), replEnabled);
+ status = _externalState->initializeReplSetStorage(txn, newConfig.toBSON());
if (!status.isOK()) {
error() << "replSetInitiate failed to store config document or create the oplog; "
<< status;
return status;
}
- if (replEnabled) {
- // Since the JournalListener has not yet been set up, we must manually set our
- // durableOpTime.
- setMyLastDurableOpTime(getMyLastAppliedOpTime());
-
- {
- LockGuard topoLock(_topoMutex);
- _finishReplSetInitiate(newConfig, myIndex.getValue());
- }
+ // Since the JournalListener has not yet been set up, we must manually set our
+ // durableOpTime.
+ setMyLastDurableOpTime(getMyLastAppliedOpTime());
- // A configuration passed to replSetInitiate() with the current node as an arbiter
- // will fail validation with a "replSet initiate got ... while validating" reason.
- invariant(!newConfig.getMemberAt(myIndex.getValue()).isArbiter());
- _externalState->startThreads(_settings);
- _startDataReplication(txn);
+ {
+ LockGuard topoLock(_topoMutex);
+ _finishReplSetInitiate(newConfig, myIndex.getValue());
}
+ // A configuration passed to replSetInitiate() with the current node as an arbiter
+ // will fail validation with a "replSet initiate got ... while validating" reason.
+ invariant(!newConfig.getMemberAt(myIndex.getValue()).isArbiter());
+ _externalState->startThreads(_settings);
+ _startDataReplication(txn);
+
configStateGuard.Dismiss();
return Status::OK();
}
diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
index d86e17f72a9..41bbb2a2d4b 100644
--- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
@@ -385,7 +385,7 @@ TEST_F(ReplCoordTest,
TEST_F(ReplCoordTest, NodeReturnsInvalidReplicaSetConfigWhenInitiatingWithAnEmptyConfig) {
OperationContextNoop txn;
- init("");
+ init("mySet");
start(HostAndPort("node1", 12345));
ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
@@ -398,7 +398,7 @@ TEST_F(ReplCoordTest, NodeReturnsInvalidReplicaSetConfigWhenInitiatingWithAnEmpt
TEST_F(ReplCoordTest, NodeReturnsInvalidReplicaSetConfigWhenInitiatingWithoutAn_idField) {
OperationContextNoop txn;
- init("");
+ init("mySet");
start(HostAndPort("node1", 12345));
ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
@@ -416,7 +416,7 @@ TEST_F(ReplCoordTest, NodeReturnsInvalidReplicaSetConfigWhenInitiatingWithoutAn_
TEST_F(ReplCoordTest,
NodeReturnsInvalidReplicaSetConfigWhenInitiatingWithAConfigVersionNotEqualToOne) {
OperationContextNoop txn;
- init("");
+ init("mySet");
start(HostAndPort("node1", 12345));
ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
@@ -434,140 +434,15 @@ TEST_F(ReplCoordTest,
ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
}
-TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlagWithMoreThanOneMember) {
- OperationContextNoop txn;
- init("");
- start(HostAndPort("node1", 12345));
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-
- BSONObjBuilder result1;
- auto status =
- getReplCoord()->processReplSetInitiate(&txn,
- BSON("_id"
- << "mySet"
- << "version" << 1 << "members"
- << BSON_ARRAY(BSON("_id" << 0 << "host"
- << "node1:12345")
- << BSON("_id" << 1 << "host"
- << "node2:12345"))),
- &result1);
- ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status);
- ASSERT_STRING_CONTAINS(status.reason(), "you can only specify one member in the config");
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-}
-
-TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlagWithSelfMissing) {
- OperationContextNoop txn;
- init("");
- start(HostAndPort("node1", 12345));
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-
- BSONObjBuilder result1;
- auto status =
- getReplCoord()->processReplSetInitiate(&txn,
- BSON("_id"
- << "mySet"
- << "version" << 1 << "members"
- << BSON_ARRAY(BSON("_id" << 0 << "host"
- << "node5:12345"))),
- &result1);
- ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status);
- ASSERT_STRING_CONTAINS(status.reason(), "No host described in new configuration");
- ASSERT_STRING_CONTAINS(status.reason(), "maps to this node");
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-}
-
-TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlagWithArbiterMember) {
+TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlag) {
OperationContextNoop txn;
init("");
start(HostAndPort("node1", 12345));
ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
BSONObjBuilder result1;
- auto status = getReplCoord()->processReplSetInitiate(
- &txn,
- BSON("_id"
- << "mySet"
- << "version" << 1 << "members" << BSON_ARRAY(BSON("_id" << 0 << "host"
- << "node1:12345"
- << "arbiterOnly" << true))),
- &result1);
- ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status);
- ASSERT_STRING_CONTAINS(status.reason(), "must contain at least one non-arbiter member");
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-}
-
-TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlagWithPriorityZero) {
- OperationContextNoop txn;
- init("");
- start(HostAndPort("node1", 12345));
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-
- BSONObjBuilder result1;
- auto status =
- getReplCoord()->processReplSetInitiate(&txn,
- BSON("_id"
- << "mySet"
- << "version" << 1 << "members"
- << BSON_ARRAY(BSON("_id" << 0 << "host"
- << "node1:12345"
- << "priority" << 0))),
- &result1);
- ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status);
- ASSERT_STRING_CONTAINS(status.reason(), "must contain at least one non-arbiter member");
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-}
-
-TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlagWithNoVotes) {
- OperationContextNoop txn;
- init("");
- start(HostAndPort("node1", 12345));
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-
- BSONObjBuilder result1;
- auto status =
- getReplCoord()->processReplSetInitiate(&txn,
- BSON("_id"
- << "mySet"
- << "version" << 1 << "members"
- << BSON_ARRAY(BSON("_id" << 0 << "host"
- << "node1:12345"
- << "votes" << 0))),
- &result1);
- ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status);
- ASSERT_STRING_CONTAINS(status.reason(), "priority must be 0 when non-voting (votes:0)");
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-}
-
-TEST_F(ReplCoordTest, InitiateFailsWithoutReplSetFlagWithHiddenMember) {
- OperationContextNoop txn;
- init("");
- start(HostAndPort("node1", 12345));
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-
- BSONObjBuilder result1;
- auto status =
- getReplCoord()->processReplSetInitiate(&txn,
- BSON("_id"
- << "mySet"
- << "version" << 1 << "members"
- << BSON_ARRAY(BSON("_id" << 0 << "host"
- << "node1:12345"
- << "hidden" << true))),
- &result1);
- ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status);
- ASSERT_STRING_CONTAINS(status.reason(), "priority must be 0 when hidden=true");
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-}
-
-TEST_F(ReplCoordTest, InitiatePassesWithoutReplSetFlagWithValidConfiguration) {
- OperationContextNoop txn;
- init("");
- start(HostAndPort("node1", 12345));
- ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
-
- BSONObjBuilder result1;
- ASSERT_OK(
+ ASSERT_EQUALS(
+ ErrorCodes::NoReplicationEnabled,
getReplCoord()->processReplSetInitiate(&txn,
BSON("_id"
<< "mySet"
@@ -575,6 +450,7 @@ TEST_F(ReplCoordTest, InitiatePassesWithoutReplSetFlagWithValidConfiguration) {
<< BSON_ARRAY(BSON("_id" << 0 << "host"
<< "node1:12345"))),
&result1));
+ ASSERT_EQUALS(MemberState::RS_STARTUP, getReplCoord()->getMemberState().s);
}
TEST_F(ReplCoordTest, NodeReturnsOutOfDiskSpaceWhenInitiateCannotWriteConfigToDisk) {
diff --git a/src/mongo/db/repl/replset_commands.cpp b/src/mongo/db/repl/replset_commands.cpp
index e12f0405751..70aaa8b7b6d 100644
--- a/src/mongo/db/repl/replset_commands.cpp
+++ b/src/mongo/db/repl/replset_commands.cpp
@@ -354,15 +354,9 @@ public:
std::string replSetString =
ReplicationCoordinator::get(txn)->getSettings().getReplSetString();
if (replSetString.empty()) {
- if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
- return appendCommandStatus(result,
- ReplicationCoordinator::get(txn)
- ->processReplSetInitiate(txn, configObj, &result));
- }
return appendCommandStatus(result,
Status(ErrorCodes::NoReplicationEnabled,
- "This node was not started with the replSet "
- "option"));
+ "This node was not started with the replSet option"));
}
if (configObj.isEmpty()) {