diff --git a/jstests/sharding/repro.js b/jstests/sharding/repro.js new file mode 100644 index 00000000000..b2ac347903e --- /dev/null +++ b/jstests/sharding/repro.js @@ -0,0 +1,63 @@ +(function() { +"use strict"; + +load("jstests/libs/uuid_util.js"); +const dbName = "TROLL"; +const collName = "myColl"; +const ns = dbName + "." + collName; + +// Disable the check (performed @ test teardown). +TestData.skipCheckOrphans = true; + +let st = new ShardingTest( + {shards: 2, + rs: { + nodes: 1, + // disable the range deleter; this will maintain the persisted docs. + setParameter: {disableResumableRangeDeleter: true} + } +}); + +/* + * Set up the data required to get the failure with FCV 5.x + */ +assert.commandWorked( + st.s.adminCommand({setFeatureCompatibilityVersion: lastContinuousFCV})); + +// 1. Create a sharded collection with 5 chunks +assert.commandWorked(st.s.adminCommand({enableSharding: dbName})); +assert.commandWorked(st.s.adminCommand({movePrimary: dbName, to: st.shard0.shardName})); +assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1}})); +assert.commandWorked(st.s.adminCommand({split: ns, middle: {x: -20}})); +assert.commandWorked(st.s.adminCommand({split: ns, middle: {x: -10}})); +assert.commandWorked(st.s.adminCommand({split: ns, middle: {x: -0}})); +assert.commandWorked(st.s.adminCommand({split: ns, middle: {x: 10}})); + +// 2. Populate the collection +var db = st.s.getDB(dbName); +var coll = db.getCollection(collName); +let bulk = coll.initializeUnorderedBulkOp(); +for (var i = 0; i < 40; i++) { + bulk.insert({x: i}); +} +assert.commandWorked(bulk.execute()); + +// 3. Move 4 chunks to shard 1 - this will create orphans and range deletion docs on shard 0. +assert.commandWorked(st.s.adminCommand( + {moveChunk: ns, find: {x: -30}, to: st.shard1.shardName})); +assert.commandWorked(st.s.adminCommand( + {moveChunk: ns, find: {x: -20}, to: st.shard1.shardName})); +assert.commandWorked(st.s.adminCommand( + {moveChunk: ns, find: {x: -10}, to: st.shard1.shardName})); +assert.commandWorked(st.s.adminCommand( + {moveChunk: ns, find: {x: 0}, to: st.shard1.shardName})); + +/* + * Go back to FCV 6.0 -> this will invoke setOrphanCountersOnRangeDeletionTasks() + */ +jsTest.log('About to trigger the failing path...'); +assert.commandWorked( + st.s.adminCommand({setFeatureCompatibilityVersion: latestFCV})); +jsTest.log('It did not fail.'); +st.stop(); +})(); diff --git a/src/mongo/client/dbclient_cursor.cpp b/src/mongo/client/dbclient_cursor.cpp index 81de065de0b..91f71ab8bba 100644 --- a/src/mongo/client/dbclient_cursor.cpp +++ b/src/mongo/client/dbclient_cursor.cpp @@ -425,6 +425,7 @@ void DBClientCursor::requestMore() { dataReceived(response); }; if (_client) + logd("TROLL doRequestMore()"); return doRequestMore(); invariant(_scopedHost.size()); diff --git a/src/mongo/db/persistent_task_store.h b/src/mongo/db/persistent_task_store.h index d5ef0e50d49..4873fcacdd0 100644 --- a/src/mongo/db/persistent_task_store.h +++ b/src/mongo/db/persistent_task_store.h @@ -153,6 +153,7 @@ public: DBDirectClient dbClient(opCtx); FindCommandRequest findRequest{_storageNss}; + findRequest.setBatchSize(2); // TODO remove! findRequest.setFilter(filter); auto cursor = dbClient.find(std::move(findRequest)); diff --git a/src/mongo/db/s/range_deletion_util.cpp b/src/mongo/db/s/range_deletion_util.cpp index 82b18854782..8b88fa87c96 100644 --- a/src/mongo/db/s/range_deletion_util.cpp +++ b/src/mongo/db/s/range_deletion_util.cpp @@ -643,11 +643,12 @@ void setOrphanCountersOnRangeDeletionTasks(OperationContext* opCtx) { BSON("$set" << BSON(RangeDeletionTask::kNumOrphanDocsFieldName << numOrphans)), ShardingCatalogClient::kLocalWriteConcern); }; - + int times = 0; store.forEach( opCtx, BSONObj(), - [opCtx, &store, &setNumOrphansOnTask](const RangeDeletionTask& deletionTask) { + [opCtx, &store, &setNumOrphansOnTask, ×](const RangeDeletionTask& deletionTask) { + ++times; AutoGetCollection collection(opCtx, deletionTask.getNss(), MODE_IX); ScopedRangeDeleterLock rangeDeleterLock(opCtx, deletionTask.getCollectionUuid()); if (!collection || collection->uuid() != deletionTask.getCollectionUuid()) { @@ -689,6 +690,7 @@ void setOrphanCountersOnRangeDeletionTasks(OperationContext* opCtx) { setNumOrphansOnTask(deletionTask, numOrphansInRange); return true; }); + logd("TROLL forEach: {} times", times); } void clearOrphanCountersFromRangeDeletionTasks(OperationContext* opCtx) {