summaryrefslogtreecommitdiff
path: root/jstests/sharding/libs
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/sharding/libs')
-rw-r--r--jstests/sharding/libs/defragmentation_util.js26
-rw-r--r--jstests/sharding/libs/last_lts_mongod_commands.js4
-rw-r--r--jstests/sharding/libs/last_lts_mongos_commands.js5
-rw-r--r--jstests/sharding/libs/mongos_api_params_util.js7
-rw-r--r--jstests/sharding/libs/resharding_test_fixture.js100
-rw-r--r--jstests/sharding/libs/with_partial_shard_key_util.js28
6 files changed, 128 insertions, 42 deletions
diff --git a/jstests/sharding/libs/defragmentation_util.js b/jstests/sharding/libs/defragmentation_util.js
index 52ac1333ef7..943f2eb462d 100644
--- a/jstests/sharding/libs/defragmentation_util.js
+++ b/jstests/sharding/libs/defragmentation_util.js
@@ -21,7 +21,9 @@ var defragmentationUtil = (function() {
}
createAndDistributeChunks(mongos, ns, numChunks, chunkSpacing);
- createRandomZones(mongos, ns, numZones, chunkSpacing);
+ // Created zones will line up exactly with existing chunks so as not to trigger zone
+ // violations in the balancer.
+ createRandomZones(mongos, ns, numZones);
fillChunksToRandomSize(mongos, ns, docSizeBytes, maxChunkFillMB);
const beginningNumberChunks = findChunksUtil.countChunksForNs(mongos.getDB('config'), ns);
@@ -49,19 +51,18 @@ var defragmentationUtil = (function() {
}
};
- let createRandomZones = function(mongos, ns, numZones, chunkSpacing) {
- for (let i = -Math.floor(numZones / 2); i < Math.ceil(numZones / 2); i++) {
+ let createRandomZones = function(mongos, ns, numZones) {
+ let existingChunks = findChunksUtil.findChunksByNs(mongos.getDB('config'), ns);
+ existingChunks = Array.shuffle(existingChunks.toArray());
+ for (let i = 0; i < numZones; i++) {
let zoneName = "Zone" + i;
- let shardForZone =
- findChunksUtil
- .findOneChunkByNs(mongos.getDB('config'), ns, {min: {key: i * chunkSpacing}})
- .shard;
+ let shardForZone = existingChunks[i].shard;
assert.commandWorked(
mongos.adminCommand({addShardToZone: shardForZone, zone: zoneName}));
assert.commandWorked(mongos.adminCommand({
updateZoneKeyRange: ns,
- min: {key: i * chunkSpacing},
- max: {key: i * chunkSpacing + chunkSpacing},
+ min: existingChunks[i].min,
+ max: existingChunks[i].max,
zone: zoneName
}));
}
@@ -202,6 +203,13 @@ var defragmentationUtil = (function() {
assert.soon(function() {
let balancerStatus =
assert.commandWorked(mongos.adminCommand({balancerCollectionStatus: ns}));
+
+ if (balancerStatus.balancerCompliant) {
+ // As we can't rely on `balancerCompliant` due to orphan counter non atomic update,
+ // we need to ensure the collection is balanced by some extra checks
+ sh.awaitCollectionBalance(mongos.getCollection(ns));
+ }
+
return balancerStatus.balancerCompliant ||
balancerStatus.firstComplianceViolation !== 'defragmentingChunks';
});
diff --git a/jstests/sharding/libs/last_lts_mongod_commands.js b/jstests/sharding/libs/last_lts_mongod_commands.js
index c25af3a8275..f8c0802af04 100644
--- a/jstests/sharding/libs/last_lts_mongod_commands.js
+++ b/jstests/sharding/libs/last_lts_mongod_commands.js
@@ -20,8 +20,12 @@ const commandsAddedToMongodSinceLastLTS = [
"clusterGetMore",
"clusterInsert",
"clusterUpdate",
+ "createSearchIndexes",
+ "dropSearchIndex",
"getClusterParameter",
+ "listSearchIndexes",
"rotateCertificates",
"setClusterParameter",
"setUserWriteBlockMode",
+ "updateSearchIndex",
];
diff --git a/jstests/sharding/libs/last_lts_mongos_commands.js b/jstests/sharding/libs/last_lts_mongos_commands.js
index f7a72743e6b..c2d8308e5f4 100644
--- a/jstests/sharding/libs/last_lts_mongos_commands.js
+++ b/jstests/sharding/libs/last_lts_mongos_commands.js
@@ -18,12 +18,16 @@ const commandsAddedToMongosSinceLastLTS = [
"commitReshardCollection",
"compactStructuredEncryptionData",
"configureCollectionBalancing",
+ "createSearchIndexes",
+ "dropSearchIndex",
"getClusterParameter",
+ "listSearchIndexes",
"moveRange",
"reshardCollection",
"rotateCertificates",
"setAllowMigrations",
"setClusterParameter",
+ "setProfilingFilterGlobally", // TODO SERVER-73305
"setUserWriteBlockMode",
"testDeprecation",
"testDeprecationInVersion2",
@@ -31,4 +35,5 @@ const commandsAddedToMongosSinceLastLTS = [
"testRemoval",
"testVersions1And2",
"testVersion2",
+ "updateSearchIndex",
];
diff --git a/jstests/sharding/libs/mongos_api_params_util.js b/jstests/sharding/libs/mongos_api_params_util.js
index e1ca18df3e6..8289582d9ee 100644
--- a/jstests/sharding/libs/mongos_api_params_util.js
+++ b/jstests/sharding/libs/mongos_api_params_util.js
@@ -75,7 +75,7 @@ let MongosAPIParametersUtil = (function() {
function awaitRemoveShard(shardName) {
assert.commandWorked(st.startBalancer());
- st.waitForBalancer(true, 60000);
+ st.awaitBalancerRound();
assert.soon(() => {
const res = st.s.adminCommand({removeShard: shardName});
jsTestLog(`removeShard result: ${tojson(res)}`);
@@ -1215,9 +1215,8 @@ let MongosAPIParametersUtil = (function() {
}
},
{
- commandName: "setFreeMonitoring",
- skip: "explicitly fails for mongos, primary mongod only",
- conditional: true
+ commandName: "setProfilingFilterGlobally",
+ skip: "executes locally on mongos (not sent to any remote node)",
},
{
commandName: "setParameter",
diff --git a/jstests/sharding/libs/resharding_test_fixture.js b/jstests/sharding/libs/resharding_test_fixture.js
index 13d39674f0f..cd658ae9508 100644
--- a/jstests/sharding/libs/resharding_test_fixture.js
+++ b/jstests/sharding/libs/resharding_test_fixture.js
@@ -85,11 +85,11 @@ var ReshardingTest = class {
/** @private */
this._newShardKey = undefined;
/** @private */
- this._pauseCoordinatorBeforeBlockingWrites = undefined;
+ this._pauseCoordinatorBeforeBlockingWritesFailpoints = [];
/** @private */
- this._pauseCoordinatorBeforeDecisionPersistedFailpoint = undefined;
+ this._pauseCoordinatorBeforeDecisionPersistedFailpoints = [];
/** @private */
- this._pauseCoordinatorBeforeCompletionFailpoint = undefined;
+ this._pauseCoordinatorBeforeCompletionFailpoints = [];
/** @private */
this._reshardingThread = undefined;
/** @private */
@@ -283,6 +283,11 @@ var ReshardingTest = class {
return sourceCollection;
}
+ get tempNs() {
+ assert.neq(undefined, this._tempNs, "createShardedCollection must be called first");
+ return this._tempNs;
+ }
+
/**
* Reshards an existing collection using the specified new shard key and new chunk ranges.
*
@@ -316,13 +321,19 @@ var ReshardingTest = class {
this._newShardKey = Object.assign({}, newShardKeyPattern);
- const configPrimary = this._st.configRS.getPrimary();
- this._pauseCoordinatorBeforeBlockingWrites =
- configureFailPoint(configPrimary, "reshardingPauseCoordinatorBeforeBlockingWrites");
- this._pauseCoordinatorBeforeDecisionPersistedFailpoint =
- configureFailPoint(configPrimary, "reshardingPauseCoordinatorBeforeDecisionPersisted");
- this._pauseCoordinatorBeforeCompletionFailpoint = configureFailPoint(
- configPrimary, "reshardingPauseCoordinatorBeforeCompletion", {}, {times: 1});
+ this._pauseCoordinatorBeforeBlockingWritesFailpoints = [];
+ this._pauseCoordinatorBeforeDecisionPersistedFailpoints = [];
+ this._pauseCoordinatorBeforeCompletionFailpoints = [];
+ this._st.forEachConfigServer((configServer) => {
+ this._pauseCoordinatorBeforeBlockingWritesFailpoints.push(
+ configureFailPoint(configServer, "reshardingPauseCoordinatorBeforeBlockingWrites"));
+ this._pauseCoordinatorBeforeDecisionPersistedFailpoints.push(configureFailPoint(
+ configServer, "reshardingPauseCoordinatorBeforeDecisionPersisted"));
+ this._pauseCoordinatorBeforeCompletionFailpoints.push(
+ configureFailPoint(configServer,
+ "reshardingPauseCoordinatorBeforeCompletion",
+ {"sourceNamespace": this._ns}));
+ });
this._commandDoneSignal = new CountDownLatch(1);
@@ -452,9 +463,9 @@ var ReshardingTest = class {
try {
fn();
} catch (duringReshardingError) {
- for (const fp of [this._pauseCoordinatorBeforeBlockingWrites,
- this._pauseCoordinatorBeforeDecisionPersistedFailpoint,
- this._pauseCoordinatorBeforeCompletionFailpoint]) {
+ for (const fp of [...this._pauseCoordinatorBeforeBlockingWritesFailpoints,
+ ...this._pauseCoordinatorBeforeDecisionPersistedFailpoints,
+ ...this._pauseCoordinatorBeforeCompletionFailpoints]) {
try {
fp.off();
} catch (disableFailpointError) {
@@ -503,7 +514,9 @@ var ReshardingTest = class {
* proceeding to the next stage. This helper returns after either:
*
* 1) The node's waitForFailPoint returns successfully or
- * 2) The `reshardCollection` command has returned a response.
+ * 2) The `reshardCollection` command has returned a response or
+ * 3) The ReshardingCoordinator is blocked on the reshardingPauseCoordinatorBeforeCompletion
+ * failpoint and won't ever satisfy the supplied failpoint.
*
* The function returns true when we returned because the server reached the failpoint. The
* function returns false when the `reshardCollection` command is no longer running.
@@ -512,9 +525,20 @@ var ReshardingTest = class {
* @private
*/
_waitForFailPoint(fp) {
+ const completionFailpoint = this._pauseCoordinatorBeforeCompletionFailpoints.find(
+ completionFailpoint => completionFailpoint.conn.host === fp.conn.host);
+
assert.soon(
() => {
- return this._commandDoneSignal.getCount() === 0 || fp.waitWithTimeout(1000);
+ if (this._commandDoneSignal.getCount() === 0 || fp.waitWithTimeout(1000)) {
+ return true;
+ }
+
+ if (completionFailpoint !== fp && completionFailpoint.waitWithTimeout(1000)) {
+ completionFailpoint.off();
+ }
+
+ return false;
},
"Timed out waiting for failpoint to be hit. Failpoint: " + fp.failPointName,
undefined,
@@ -529,6 +553,19 @@ var ReshardingTest = class {
postCheckConsistencyFn = () => {},
postDecisionPersistedFn = () => {},
afterReshardingFn = () => {}) {
+ // The CSRS primary may have changed as a result of running the duringReshardingFn()
+ // callback function. The failpoints will only be triggered on the new CSRS primary so we
+ // detect which node that is here.
+ const configPrimary = this._st.configRS.getPrimary();
+ const primaryIdx = this._pauseCoordinatorBeforeBlockingWritesFailpoints.findIndex(
+ fp => fp.conn.host === configPrimary.host);
+ // The CSRS secondaries may be going through replication rollback which closes their
+ // connections to the test client. We wait for any replication rollbacks to complete and for
+ // the test client to have reconnected so the failpoints can be turned off on all of the
+ // nodes later on.
+ this._st.configRS.awaitSecondaryNodes();
+ this._st.configRS.awaitReplication();
+
let performCorrectnessChecks = true;
if (expectedErrorCode === ErrorCodes.OK) {
this._callFunctionSafely(() => {
@@ -539,17 +576,18 @@ var ReshardingTest = class {
// reshardingPauseCoordinatorBeforeDecisionPersisted failpoint to wait for all of
// the recipient shards to have applied through all of the oplog entries from all of
// the donor shards.
- if (!this._waitForFailPoint(this._pauseCoordinatorBeforeBlockingWrites)) {
+ if (!this._waitForFailPoint(
+ this._pauseCoordinatorBeforeBlockingWritesFailpoints[primaryIdx])) {
performCorrectnessChecks = false;
}
- this._pauseCoordinatorBeforeBlockingWrites.off();
+ this._pauseCoordinatorBeforeBlockingWritesFailpoints.forEach(fp => fp.off());
// A resharding command that returned a failure will not hit the "Decision
// Persisted" failpoint. If the command has returned, don't require that the
// failpoint was entered. This ensures that following up by joining the
// `_reshardingThread` will succeed.
if (!this._waitForFailPoint(
- this._pauseCoordinatorBeforeDecisionPersistedFailpoint)) {
+ this._pauseCoordinatorBeforeDecisionPersistedFailpoints[primaryIdx])) {
performCorrectnessChecks = false;
}
@@ -562,22 +600,21 @@ var ReshardingTest = class {
postCheckConsistencyFn();
}
- this._pauseCoordinatorBeforeDecisionPersistedFailpoint.off();
+ this._pauseCoordinatorBeforeDecisionPersistedFailpoints.forEach(fp => fp.off());
postDecisionPersistedFn();
- this._pauseCoordinatorBeforeCompletionFailpoint.off();
+ this._pauseCoordinatorBeforeCompletionFailpoints.forEach(fp => fp.off());
});
} else {
this._callFunctionSafely(() => {
- this.retryOnceOnNetworkError( //
- () => this._pauseCoordinatorBeforeBlockingWrites.off());
-
+ this._pauseCoordinatorBeforeBlockingWritesFailpoints.forEach(
+ fp => this.retryOnceOnNetworkError(fp.off));
postCheckConsistencyFn();
- this.retryOnceOnNetworkError(
- () => this._pauseCoordinatorBeforeDecisionPersistedFailpoint.off());
+ this._pauseCoordinatorBeforeDecisionPersistedFailpoints.forEach(
+ fp => this.retryOnceOnNetworkError(fp.off));
postDecisionPersistedFn();
- this.retryOnceOnNetworkError(
- () => this._pauseCoordinatorBeforeCompletionFailpoint.off());
+ this._pauseCoordinatorBeforeCompletionFailpoints.forEach(
+ fp => this.retryOnceOnNetworkError(fp.off));
});
}
@@ -600,7 +637,11 @@ var ReshardingTest = class {
/** @private */
_checkConsistency() {
- const nsCursor = this._st.s.getCollection(this._ns).find().sort({_id: 1});
+ // The "available" read concern level won't block this find cmd behind the critical section.
+ // Tests for resharding are not expected to have unowned documents in the collection being
+ // resharded.
+ const nsCursor =
+ this._st.s.getCollection(this._ns).find().readConcern("available").sort({_id: 1});
const tempNsCursor = this._st.s.getCollection(this._tempNs).find().sort({_id: 1});
const diff = ((diff) => {
@@ -618,7 +659,8 @@ var ReshardingTest = class {
docsExtraAfterResharding: [],
docsMissingAfterResharding: [],
},
- "existing sharded collection and temporary resharding collection had different" +
+ "existing sharded collection " + this._ns +
+ " and temporary resharding collection " + this._tempNs + " had different" +
" contents");
}
diff --git a/jstests/sharding/libs/with_partial_shard_key_util.js b/jstests/sharding/libs/with_partial_shard_key_util.js
new file mode 100644
index 00000000000..bcfeae08926
--- /dev/null
+++ b/jstests/sharding/libs/with_partial_shard_key_util.js
@@ -0,0 +1,28 @@
+/**
+ * Utilities for the find_and_modify_with_partial_shard_key.js and delete_with_partial_shard_key.js
+ * tests.
+ */
+"use strict";
+
+/**
+ * Runs an explain on the `cmdObj` and checks that the explain targets the shard given be
+ * `expectedShardName`.
+ */
+function assertExplainTargetsCorrectShard(db, cmdObj, expectedShardName) {
+ var res = db.runCommand({explain: cmdObj});
+ assert.eq(res.queryPlanner.winningPlan.shards.length, 1);
+ assert.eq(res.queryPlanner.winningPlan.shards[0].shardName, expectedShardName);
+}
+
+/**
+ * Performs a split given by the `splitDoc`, and then moves the chunk containg `moveShard0Doc` to
+ * shard0 and the chunk containing `moveShard1Doc` to shard1.
+ */
+function splitAndMoveChunks(st, splitDoc, moveShard0Doc, moveShard1Doc) {
+ assert.commandWorked(st.s0.adminCommand({split: "test.sharded_coll", middle: splitDoc}));
+
+ assert.commandWorked(st.s0.adminCommand(
+ {moveChunk: "test.sharded_coll", find: moveShard0Doc, to: st.shard0.shardName}));
+ assert.commandWorked(st.s0.adminCommand(
+ {moveChunk: "test.sharded_coll", find: moveShard1Doc, to: st.shard1.shardName}));
+}