summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildscripts/resmokeconfig/suites/read_only_sharded.yml2
-rw-r--r--jstests/readonly/validate.js41
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.cpp5
-rw-r--r--src/mongo/db/commands/validate.cpp13
4 files changed, 59 insertions, 2 deletions
diff --git a/buildscripts/resmokeconfig/suites/read_only_sharded.yml b/buildscripts/resmokeconfig/suites/read_only_sharded.yml
index 26e3c978b3e..eb9e3be0379 100644
--- a/buildscripts/resmokeconfig/suites/read_only_sharded.yml
+++ b/buildscripts/resmokeconfig/suites/read_only_sharded.yml
@@ -6,6 +6,8 @@ selector:
exclude_files:
# The test below use applyOps, SERVER-1439.
- jstests/readonly/temp_collection.js
+ exclude_with_any_tags:
+ - assumes_against_mongod_not_mongos
executor:
config:
diff --git a/jstests/readonly/validate.js b/jstests/readonly/validate.js
new file mode 100644
index 00000000000..5819f065953
--- /dev/null
+++ b/jstests/readonly/validate.js
@@ -0,0 +1,41 @@
+// Tests that running validate in read-only mode doesn't try to fix metadata
+// @tags: [assumes_against_mongod_not_mongos]
+
+load("jstests/readonly/lib/read_only_test.js");
+
+// We skip doing the data consistency checks while terminating the cluster because we leave data in
+// an inconsitent state on purpose.
+TestData.skipCollectionAndIndexValidation = true;
+
+runReadOnlyTest(function() {
+ 'use strict';
+ return {
+ name: 'validate',
+ load: function(writableCollection) {
+ const db = writableCollection.getDB();
+ assert.commandWorked(
+ db.adminCommand({configureFailPoint: "skipUpdateIndexMultikey", mode: "alwaysOn"}));
+ assert.commandWorked(writableCollection.createIndex({a: 1, b: 1}, {name: 'idx'}));
+ assert.commandWorked(writableCollection.insert({_id: 0, a: [0, 1]}));
+ assert.commandWorked(
+ db.adminCommand({configureFailPoint: "skipUpdateIndexMultikey", mode: "off"}));
+ },
+ exec: function(readableCollection) {
+ // Make sure we don't try to adjust multikey indices in read-only mode
+ const res = readableCollection.validate({full: true});
+ assert.eq(1, res.ok, "Expected success of validate on read-only mode");
+ assert.eq(false, res.valid);
+ assert.eq(1, res.errors.length);
+
+ const idx = res.indexDetails.idx;
+ assert.eq(false, idx.valid);
+ assert.eq(1, idx.errors.length);
+
+ // Test that validate { repair: true } fails in read-only mode.
+ assert.commandFailedWithCode(
+ readableCollection.validate({full: true, repair: true}),
+ ErrorCodes.InvalidOptions,
+ "Expected validate to fail because repairing a read-only database is not possible");
+ }
+ };
+}());
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
index 0093b66fb40..94e09994b0c 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
@@ -57,6 +57,7 @@
#include "mongo/util/scopeguard.h"
namespace mongo {
+MONGO_FAIL_POINT_DEFINE(skipUpdateIndexMultikey);
using std::string;
@@ -206,6 +207,10 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx,
}
}
+ if (MONGO_unlikely(skipUpdateIndexMultikey.shouldFail())) {
+ return;
+ }
+
MultikeyPaths paths = indexTracksMultikeyPathsInCatalog ? multikeyPaths : MultikeyPaths{};
// On a primary, we can simply assign this write the same timestamp as the index creation,
diff --git a/src/mongo/db/commands/validate.cpp b/src/mongo/db/commands/validate.cpp
index fb494ab74eb..c6724076b9f 100644
--- a/src/mongo/db/commands/validate.cpp
+++ b/src/mongo/db/commands/validate.cpp
@@ -148,15 +148,20 @@ public:
}
const bool repair = cmdObj["repair"].trueValue();
+ if (storageGlobalParams.readOnly && repair) {
+ uasserted(ErrorCodes::InvalidOptions,
+ str::stream() << "Running the validate command with { repair: true } in"
+ << " read-only mode is not supported.");
+ }
if (background && repair) {
uasserted(ErrorCodes::InvalidOptions,
- str::stream() << "Running the validate command with both {background: true }"
+ str::stream() << "Running the validate command with both { background: true }"
<< " and { repair: true } is not supported.");
}
if (enforceFastCount && repair) {
uasserted(ErrorCodes::InvalidOptions,
str::stream()
- << "Running the validate command with both {enforceFastCount: true }"
+ << "Running the validate command with both { enforceFastCount: true }"
<< " and { repair: true } is not supported.");
}
repl::ReplicationCoordinator* replCoord = repl::ReplicationCoordinator::get(opCtx);
@@ -221,6 +226,10 @@ public:
}();
auto repairMode = [&] {
+ if (storageGlobalParams.readOnly) {
+ // On read-only mode we can't make any adjustments.
+ return CollectionValidation::RepairMode::kNone;
+ }
switch (mode) {
case CollectionValidation::ValidateMode::kForeground:
case CollectionValidation::ValidateMode::kForegroundFull: