summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2016-09-28 13:18:11 -0400
committerBenety Goh <benety@mongodb.com>2016-09-28 17:50:04 -0400
commit7f6eb7f2361addf3f75308bf1603caa8cdc71b68 (patch)
tree94d49edc8e602bd9d9d28ef3de166d4de3e2dc38
parentea43e31157ea0402d4176de506399da81b3c7b29 (diff)
downloadmongo-7f6eb7f2361addf3f75308bf1603caa8cdc71b68.tar.gz
SERVER-26169 added startup parameter for linearizable read support defaulting to disabled
-rw-r--r--jstests/replsets/linearizable_read_concern.js32
-rw-r--r--src/mongo/base/error_codes.err1
-rw-r--r--src/mongo/db/commands/dbcommands.cpp16
-rw-r--r--src/mongo/db/repl/replication_coordinator.h5
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state.h5
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.cpp6
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.h1
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_mock.cpp4
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_mock.h1
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp3
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.h2
-rw-r--r--src/mongo/db/repl/replication_coordinator_mock.cpp4
-rw-r--r--src/mongo/db/repl/replication_coordinator_mock.h2
13 files changed, 81 insertions, 1 deletions
diff --git a/jstests/replsets/linearizable_read_concern.js b/jstests/replsets/linearizable_read_concern.js
index 4cbef17b568..f7f7d3b9228 100644
--- a/jstests/replsets/linearizable_read_concern.js
+++ b/jstests/replsets/linearizable_read_concern.js
@@ -31,9 +31,39 @@ load('jstests/libs/write_concern_util.js');
ErrorCodes.InterruptedDueToReplStateChange);
};
+ // Linearizable read concern is an opt-in feature. Replica sets started with the startup
+ // parameter --setParameter enableLinearizableReadConcern=true should error on receiving a
+ // linearizable read command.
+ {
+ jsTestLog('Testing that linearizable read is disabled by default');
+ let replTest = new ReplSetTest({nodes: 1});
+ replTest.startSet();
+ replTest.initiate();
+ let primary = replTest.getPrimary();
+
+ // Linearizable read concern is a startup-only server parameter.
+ assert.commandFailed(
+ primary.adminCommand({setParameter: 1, enableLinearizableReadConcern: true}));
+ assert.commandFailed(
+ primary.adminCommand({setParameter: 1, enableLinearizableReadConcern: false}));
+
+ let coll = primary.getDB('test').foo;
+ assert.writeOK(coll.insert({x: 1}));
+ assert.commandFailedWithCode(
+ coll.runCommand(
+ {'find': coll.getName(), readConcern: {level: "linearizable"}, maxTimeMS: 60000}),
+ ErrorCodes.LinearizableReadConcernNotEnabled);
+ replTest.stopSet();
+ }
+
var num_nodes = 3;
var name = 'linearizable_read_concern';
- var replTest = new ReplSetTest({name: name, nodes: num_nodes, useBridge: true});
+ var replTest = new ReplSetTest({
+ name: name,
+ nodes: num_nodes,
+ nodeOptions: {setParameter: 'enableLinearizableReadConcern=true'},
+ useBridge: true,
+ });
var config = replTest.getReplSetConfig();
// Increased election timeout to avoid having the primary step down while we are
diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err
index cb524d53263..c6a0e7d014b 100644
--- a/src/mongo/base/error_codes.err
+++ b/src/mongo/base/error_codes.err
@@ -194,6 +194,7 @@ error_code("FailPointEnabled", 192)
error_code("NoShardingEnabled", 193)
error_code("BalancerInterrupted", 194)
error_code("ViewPipelineMaxSizeExceeded", 195)
+error_code("LinearizableReadConcernNotEnabled", 196)
# Non-sequential error codes (for compatibility only)
error_code("SocketException", 9001)
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 432c630166d..a25288efa8e 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -1403,6 +1403,22 @@ bool Command::run(OperationContext* txn,
return result;
}
+ if (readConcernArgsStatus.getValue().getLevel() ==
+ repl::ReadConcernLevel::kLinearizableReadConcern) {
+ auto replCoord = repl::ReplicationCoordinator::get(txn);
+ if (!replCoord->isLinearizableReadConcernEnabled()) {
+ Status status(ErrorCodes::LinearizableReadConcernNotEnabled,
+ "Linearizable read concern requested, but server was not started with "
+ "--setParameter enableLinearizableReadConcern=true");
+ inPlaceReplyBob.resetToEmpty();
+ auto result = appendCommandStatus(inPlaceReplyBob, status);
+ inPlaceReplyBob.doneFast();
+ replyBuilder->setMetadata(rpc::makeEmptyMetadata());
+ return result;
+ }
+ }
+
+
Status rcStatus = waitForReadConcern(txn, readConcernArgsStatus.getValue());
if (!rcStatus.isOK()) {
if (rcStatus == ErrorCodes::ExceededTimeLimit) {
diff --git a/src/mongo/db/repl/replication_coordinator.h b/src/mongo/db/repl/replication_coordinator.h
index 019add3e0cf..e2a6ff4e76b 100644
--- a/src/mongo/db/repl/replication_coordinator.h
+++ b/src/mongo/db/repl/replication_coordinator.h
@@ -794,6 +794,11 @@ public:
virtual Status stepUpIfEligible() = 0;
+ /**
+ * Returns true if linearizable read concern is supported.
+ */
+ virtual bool isLinearizableReadConcernEnabled() const = 0;
+
protected:
ReplicationCoordinator();
};
diff --git a/src/mongo/db/repl/replication_coordinator_external_state.h b/src/mongo/db/repl/replication_coordinator_external_state.h
index 73e99635c36..fbb8d365dbb 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state.h
@@ -355,6 +355,11 @@ public:
* Stops periodic noop writes to oplog.
*/
virtual void stopNoopWriter() = 0;
+
+ /**
+ * Returns true if linearizable read concern is supported.
+ */
+ virtual bool isLinearizableReadConcernEnabled() const = 0;
};
} // namespace repl
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 21708c3ebff..b3d4b4ffbb4 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
@@ -118,6 +118,8 @@ const char kBlockingQueueOplogBufferName[] = "inMemoryBlockingQueue";
// repl::SnapshotThread introduces.
MONGO_EXPORT_STARTUP_SERVER_PARAMETER(enableReplSnapshotThread, bool, false);
+MONGO_EXPORT_STARTUP_SERVER_PARAMETER(enableLinearizableReadConcern, bool, false);
+
MONGO_EXPORT_STARTUP_SERVER_PARAMETER(use3dot2InitialSync, bool, false);
// Set this to specify whether to use a collection to buffer the oplog on the destination server
@@ -899,6 +901,10 @@ std::size_t ReplicationCoordinatorExternalStateImpl::getOplogFetcherMaxFetcherRe
return oplogFetcherMaxFetcherRestarts;
}
+bool ReplicationCoordinatorExternalStateImpl::isLinearizableReadConcernEnabled() const {
+ return enableLinearizableReadConcern;
+}
+
JournalListener::Token ReplicationCoordinatorExternalStateImpl::getToken() {
return repl::getGlobalReplicationCoordinator()->getMyLastAppliedOpTime();
}
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 372a1661e37..9c173a97823 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.h
@@ -113,6 +113,7 @@ public:
OperationContext* txn) const override;
virtual bool shouldUseDataReplicatorInitialSync() const override;
virtual std::size_t getOplogFetcherMaxFetcherRestarts() const override;
+ virtual bool isLinearizableReadConcernEnabled() const override;
// Methods from JournalListener.
virtual JournalListener::Token getToken();
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 700d1608880..087e8d84ab0 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
@@ -294,6 +294,10 @@ std::size_t ReplicationCoordinatorExternalStateMock::getOplogFetcherMaxFetcherRe
return 0;
}
+bool ReplicationCoordinatorExternalStateMock::isLinearizableReadConcernEnabled() const {
+ return false;
+}
+
void ReplicationCoordinatorExternalStateMock::setIsReadCommittedEnabled(bool val) {
_isReadCommittedSupported = val;
}
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 35ff01d5585..fcc6eea1d4b 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_mock.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.h
@@ -107,6 +107,7 @@ public:
OperationContext* txn) const override;
virtual bool shouldUseDataReplicatorInitialSync() const override;
virtual std::size_t getOplogFetcherMaxFetcherRestarts() const override;
+ virtual bool isLinearizableReadConcernEnabled() const override;
/**
* Adds "host" to the list of hosts that this mock will match when responding to "isSelf"
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 81c8cef4821..481c4f86c7a 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -3878,6 +3878,9 @@ void ReplicationCoordinatorImpl::setIndexPrefetchConfig(
_indexPrefetchConfig = cfg;
}
+bool ReplicationCoordinatorImpl::isLinearizableReadConcernEnabled() const {
+ return _externalState->isLinearizableReadConcernEnabled();
+}
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h
index df76c251c0b..d66dd431279 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_impl.h
@@ -339,6 +339,8 @@ public:
virtual Status stepUpIfEligible() override;
+ virtual bool isLinearizableReadConcernEnabled() const override;
+
// ================== Test support API ===================
/**
diff --git a/src/mongo/db/repl/replication_coordinator_mock.cpp b/src/mongo/db/repl/replication_coordinator_mock.cpp
index 03878cc300c..3b1aa2e8960 100644
--- a/src/mongo/db/repl/replication_coordinator_mock.cpp
+++ b/src/mongo/db/repl/replication_coordinator_mock.cpp
@@ -467,5 +467,9 @@ Status ReplicationCoordinatorMock::stepUpIfEligible() {
return Status::OK();
}
+bool ReplicationCoordinatorMock::isLinearizableReadConcernEnabled() const {
+ return false;
+}
+
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/replication_coordinator_mock.h b/src/mongo/db/repl/replication_coordinator_mock.h
index 4daf24d894e..96dd2486e98 100644
--- a/src/mongo/db/repl/replication_coordinator_mock.h
+++ b/src/mongo/db/repl/replication_coordinator_mock.h
@@ -262,6 +262,8 @@ public:
virtual Status stepUpIfEligible() override;
+ virtual bool isLinearizableReadConcernEnabled() const override;
+
/**
* Sets the return value for calls to getConfig.
*/