summaryrefslogtreecommitdiff
path: root/jstests/sharding/migration_with_source_deletes.js
blob: afc00e513e252d19be93edfce409c16a83354606 (plain)
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();

})()