1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
//
// Tests during chunk migration that the recipient does not receive out of range deletes from
// the donor.
//
// Pauses the migration on the recipient shard after the initial data chunk cloning is finished.
// This allows time for the donor shard to perform deletes, half of which are on the migrating
// chunk. The recipient is then set to continue, collecting the delete mods from the donor, and
// finishes the migration. A failpoint is set prior to resuming in the recipient shard to fail
// if it receives an out of chunk range delete from the donor's delete mods log.
//
// The idea is that the recipient shard should not be collecting deletes from the donor shard
// that are not in range and that will unnecessarily prevent the migration from finishing: the
// migration can only end when donor's log of delete mods for the migrating chunk is empty.
//
load('./jstests/libs/chunk_manipulation_util.js');
(function() {
"use strict";
var staticMongod = MongoRunner.runMongod({}); // For startParallelOps.
/**
* Start up new sharded cluster, stop balancer that would interfere in manual chunk management.
*/
var st = new ShardingTest({ shards : 2, mongos : 1 });
st.stopBalancer();
var mongos = st.s0,
admin = mongos.getDB('admin'),
shards = mongos.getCollection('config.shards').find().toArray(),
dbName = "testDB",
ns = dbName + ".foo",
coll = mongos.getCollection(ns),
donor = st.shard0,
recipient = st.shard1,
donorColl = donor.getCollection(ns),
recipientColl = recipient.getCollection(ns);
/**
* Exable sharding, and split collection into two chunks.
*/
// Two chunks
// Donor: [0, 10) [10, 20)
// Recipient:
jsTest.log('Enable sharding of the collection and pre-split into two chunks....');
assert.commandWorked( admin.runCommand( {enableSharding: dbName} ) );
st.ensurePrimaryShard(dbName, shards[0]._id);
assert.commandWorked( admin.runCommand( {shardCollection: ns, key: {a: 1}} ) );
assert.commandWorked( admin.runCommand( {split: ns, middle: {a: 10}} ) );
/**
* Insert data into collection
*/
// 10 documents in each chunk on the donor
jsTest.log('Inserting 20 docs into donor shard, 10 in each chunk....');
for (var i = 0; i < 20; ++i) donorColl.insert( {a: i} );
assert.eq(null, donorColl.getDB().getLastError());
assert.eq(20, donorColl.count());
/**
* Set failpoints. Recipient will crash if an out of chunk range data delete is
* received from donor. Recipient will pause migration after cloning chunk data from donor,
* before checking delete mods log on donor.
*/
jsTest.log('setting failpoint failMigrationReceivedOutOfRangeDelete');
assert.commandWorked(recipient.getDB('admin').runCommand( {configureFailPoint: 'failMigrationReceivedOutOfRangeDelete', mode: 'alwaysOn'} ))
jsTest.log('setting recipient failpoint cloned');
pauseMigrateAtStep(recipient, migrateStepNames.cloned);
/**
* Start a moveChunk in the background. Move chunk [10, 20), which has 10 docs,
* from shard 0 (donor) to shard 1 (recipient). Migration will pause after cloning
* (when it reaches the recipient failpoint).
*/
// Donor: [0, 10)
// Recipient: [10, 20)
jsTest.log('starting migration, pause after cloning...');
var joinMoveChunk = moveChunkParallel(
staticMongod,
st.s0.host,
{a: 10},
null,
coll.getFullName(),
shards[1]._id);
/**
* Wait for recipient to finish cloning.
* THEN delete 10 documents on donor, 5 in the migrating chunk and the 5 in the remaining chunk.
*/
jsTest.log('Delete 5 docs from each chunk, migrating chunk and remaining chunk...');
waitForMigrateStep(recipient, migrateStepNames.cloned);
donorColl.remove( {$and : [ {a: {$gte: 5}}, {a: {$lt: 15}} ]} );
/**
* Finish migration. Unpause recipient migration, wait for it to collect
* the delete diffs from donor and finish.
*/
jsTest.log('Continuing and finishing migration...');
unpauseMigrateAtStep(recipient, migrateStepNames.cloned);
joinMoveChunk();
/**
* Check documents are where they should be: 5 docs in each shard's chunk.
*/
jsTest.log('Checking that documents are on the shards they should be...');
assert.eq(5, donorColl.count());
assert.eq(5, recipientColl.count());
assert.eq(10, coll.count());
jsTest.log('DONE!');
st.stop();
})()
|