summaryrefslogtreecommitdiff
path: root/jstests/libs/override_methods/check_orphans_are_deleted.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/libs/override_methods/check_orphans_are_deleted.js')
-rw-r--r--jstests/libs/override_methods/check_orphans_are_deleted.js119
1 files changed, 119 insertions, 0 deletions
diff --git a/jstests/libs/override_methods/check_orphans_are_deleted.js b/jstests/libs/override_methods/check_orphans_are_deleted.js
new file mode 100644
index 00000000000..f2d329df80b
--- /dev/null
+++ b/jstests/libs/override_methods/check_orphans_are_deleted.js
@@ -0,0 +1,119 @@
+/**
+ * Asserts that all shards in the sharded cluster doesn't own any orphan documents.
+ * Requires all shards and config server to have primary that is reachable.
+ *
+ * Note: Doesn't catch documents in the shard that doesn't have the full shard key.
+ * Assumes that all shards have the index that matches the shard key.
+ */
+ShardingTest.prototype.checkOrphansAreDeleted = function() {
+ if (jsTest.options().skipCheckOrphans) {
+ print("Skipping orphan check across the cluster");
+ return;
+ }
+
+ print('Running check orphans against cluster with mongos: ' + this.s.host);
+
+ let runCheck = function(mongosConn, shardConn, shardId) {
+ let configDB = shardConn.getDB('config');
+
+ let migrationCoordinatorDocs = [];
+ assert.soon(
+ () => {
+ try {
+ migrationCoordinatorDocs = configDB.migrationCoordinators.find().toArray();
+ return migrationCoordinatorDocs.length == 0;
+ } catch (exp) {
+ // Primary purpose is to stabilize shell repl set monitor to recognize the
+ // current primary.
+ print('caught exception while checking migration coordinators, ' +
+ 'will retry again unless timed out: ' + tojson(exp));
+ }
+ },
+ () => {
+ return 'timed out waiting for migrationCoordinators to be empty @ ' + shardId +
+ ', last known contents: ' + tojson(migrationCoordinatorDocs);
+ },
+ 5 * 60 * 1000,
+ 1000);
+
+ let rangeDeletions = [];
+ assert.soon(
+ () => {
+ rangeDeletions = configDB.rangeDeletions.find().toArray();
+ return rangeDeletions.length == 0;
+ },
+ () => {
+ return 'timed out waiting for rangeDeletions to be empty @ ' + shardId +
+ ', last known contents: ' + tojson(rangeDeletions);
+ });
+
+ mongosConn.getDB('config').collections.find({dropped: false}).forEach(collDoc => {
+ let tempNsArray = collDoc._id.split('.');
+ let dbName = tempNsArray.shift();
+ let collName = tempNsArray.join('.');
+
+ let coll = shardConn.getDB(dbName)[collName];
+ mongosConn.getDB('config')
+ .chunks.find({ns: collDoc._id, shard: {$ne: shardId}})
+ .forEach(chunkDoc => {
+ // Use $min/$max so this will also work with hashed and compound shard keys.
+ let orphans = coll.find({})
+ .hint(collDoc.key)
+ .min(chunkDoc.min)
+ .max(chunkDoc.max)
+ .toArray();
+ assert.eq(0,
+ orphans.length,
+ 'found orphans @ ' + shardId + ' within chunk: ' + tojson(chunkDoc) +
+ ', orphans: ' + tojson(orphans));
+ });
+ });
+ };
+
+ let getConn = function(connStr) {
+ try {
+ return new Mongo(connStr);
+ } catch (exp) {
+ jsTest.log('Unable to connect to ' + connStr + ' while trying to check for orphans');
+ return null;
+ }
+ };
+
+ // Use a new connection so we don't have to worry about existing users logged in to the
+ // connection.
+ let mongosConn = new Mongo(this.s.host);
+ mongosConn.fullOptions = Object.merge(this.s.fullOptions, {});
+
+ const keyFile = this.keyFile;
+ if (keyFile || mongosConn.fullOptions.clusterAuthMode == 'x509') {
+ authutil.asCluster(mongosConn, keyFile, () => {
+ assert.commandWorked(mongosConn.adminCommand({balancerStop: 1}));
+
+ // Use config.shards so we will not miss shards added outside of ShardingTest.
+ mongosConn.getDB('config').shards.find().forEach(shardDoc => {
+ let shardConn = getConn(shardDoc.host);
+
+ // Inherit connection options from mongos connection.
+ shardConn.fullOptions = Object.merge(this.s.fullOptions, {});
+
+ if (shardConn != null) {
+ authutil.asCluster(shardConn, keyFile, () => {
+ runCheck(mongosConn, shardConn, shardDoc._id);
+ });
+ }
+ });
+ });
+ } else {
+ assert.commandWorked(mongosConn.adminCommand({balancerStop: 1}));
+
+ // Use config.shards so we will not miss shards added outside of ShardingTest.
+ mongosConn.getDB('config').shards.find().forEach(shardDoc => {
+ let shardConn = getConn(shardDoc.host);
+
+ if (shardConn != null) {
+ shardConn.host = shardDoc.host;
+ runCheck(mongosConn, shardConn, shardDoc._id);
+ }
+ });
+ }
+};