148 lines
4.6 KiB
JavaScript
148 lines
4.6 KiB
JavaScript
//
|
|
// Utilities for testing cleanupOrphaned command.
|
|
//
|
|
|
|
//
|
|
// Run cleanupOrphaned on a shard, and assert cleanupOrphaned runs the
|
|
// expected number of times before stopping.
|
|
//
|
|
function cleanupOrphaned(shardConnection, ns, expectedIterations) {
|
|
var admin = shardConnection.getDB('admin'),
|
|
result = admin.runCommand({cleanupOrphaned: ns}),
|
|
iterations = 1;
|
|
|
|
if (!result.ok) { printjson(result); }
|
|
assert(result.ok);
|
|
while (result.stoppedAtKey) {
|
|
result = admin.runCommand({
|
|
cleanupOrphaned: ns,
|
|
startingFromKey: result.stoppedAtKey
|
|
});
|
|
|
|
assert(result.ok);
|
|
++iterations;
|
|
}
|
|
|
|
assert.eq(iterations, expectedIterations, 'Expected to run ' +
|
|
'cleanupOrphaned' + expectedIterations + ' times, but it only ran ' +
|
|
iterations + ' times before stoppedAtKey was null.')
|
|
}
|
|
|
|
// Shards data from key range, then inserts orphan documents, runs cleanupOrphans
|
|
// and makes sure that orphans are removed.
|
|
// Pass an options object like:
|
|
// {
|
|
// shardKey: { a: 1, b: 1 },
|
|
// keyGen: function() { return [{ a: 'foo', b: 1 }, { a: 'bar', b: 2 }]; }
|
|
// }
|
|
function testCleanupOrphaned(options) {
|
|
var st = new ShardingTest({shards: 2, mongos: 2});
|
|
|
|
var mongos = st.s0,
|
|
admin = mongos.getDB('admin'),
|
|
shards = mongos.getCollection('config.shards').find().toArray(),
|
|
coll = mongos.getCollection('foo.bar'),
|
|
shard0Coll = st.shard0.getCollection(coll.getFullName()),
|
|
keys = options.keyGen(),
|
|
beginning = keys[0],
|
|
oneQuarter = keys[Math.round(keys.length / 4)],
|
|
middle = keys[Math.round(keys.length / 2)],
|
|
threeQuarters = keys[Math.round(3 * keys.length / 4)];
|
|
|
|
assert.commandWorked(admin.runCommand({
|
|
enableSharding: coll.getDB().getName()
|
|
}));
|
|
|
|
printjson( admin.runCommand({ movePrimary : coll.getDB() + "", to : shards[0]._id }) );
|
|
|
|
assert.commandWorked(admin.runCommand({
|
|
shardCollection: coll.getFullName(),
|
|
key: options.shardKey
|
|
}));
|
|
|
|
st.printShardingStatus();
|
|
|
|
jsTest.log('Inserting some regular docs...');
|
|
|
|
assert.commandWorked(admin.runCommand({
|
|
split: coll.getFullName(),
|
|
middle: middle
|
|
}));
|
|
|
|
assert.commandWorked(admin.runCommand({
|
|
moveChunk: coll.getFullName(),
|
|
find: middle,
|
|
to: shards[1]._id,
|
|
_waitForDelete: true
|
|
}));
|
|
|
|
for (var i = 0; i < keys.length; i++) coll.insert(keys[i]);
|
|
assert.eq(null, coll.getDB().getLastError());
|
|
|
|
// Half of the data is on each shard:
|
|
// shard 0: [beginning, middle)
|
|
// shard 1: [middle, end)
|
|
//
|
|
assert.eq(keys.length / 2, shard0Coll.count());
|
|
assert.eq(keys.length, coll.find().itcount());
|
|
|
|
jsTest.log('Inserting some orphaned docs...');
|
|
|
|
shard0Coll.insert(threeQuarters);
|
|
|
|
// I'll represent the orphan doc like {threeQuarters}, in this diagram:
|
|
//
|
|
// shard 0: [beginning, middle) {threeQuarters}
|
|
// shard 1: [middle, end)
|
|
assert.eq(null, shard0Coll.getDB().getLastError());
|
|
assert.eq(1 + keys.length / 2, shard0Coll.count());
|
|
|
|
jsTest.log('Cleaning up orphaned data...');
|
|
|
|
cleanupOrphaned(st.shard0, coll.getFullName(), 2);
|
|
assert.eq(keys.length / 2, shard0Coll.count());
|
|
assert.eq(keys.length, coll.find().itcount());
|
|
|
|
jsTest.log('Moving half the data out again (making a hole)...');
|
|
|
|
assert.commandWorked(admin.runCommand({
|
|
split: coll.getFullName(),
|
|
middle: oneQuarter
|
|
}));
|
|
|
|
assert.commandWorked(admin.runCommand({
|
|
moveChunk: coll.getFullName(),
|
|
find: beginning,
|
|
to: shards[1]._id,
|
|
_waitForDelete: true
|
|
}));
|
|
|
|
// 1/4 of the data is on the first shard.
|
|
// shard 0: [threeQuarters, middle)
|
|
// shard 1: [beginning, threeQuarters) [middle, end)
|
|
assert.eq(Math.round(keys.length / 4), shard0Coll.count());
|
|
assert.eq(keys.length, coll.find().itcount());
|
|
|
|
jsTest.log('Inserting some more orphaned docs...');
|
|
|
|
shard0Coll.insert(beginning);
|
|
shard0Coll.insert(middle);
|
|
assert.eq(null, shard0Coll.getDB().getLastError());
|
|
|
|
// shard 0: {beginning} [threeQuarters, middle) {middle}
|
|
// shard 1: [beginning, threeQuarters) [middle, end)
|
|
assert.eq(2 + Math.round(keys.length / 4), shard0Coll.count());
|
|
assert.eq(100, coll.find().itcount());
|
|
|
|
jsTest.log('Cleaning up more orphaned data...');
|
|
|
|
// Now cleanupOrphaned must iterate over 3 regions, not 2.
|
|
cleanupOrphaned(st.shard0, coll.getFullName(), 3);
|
|
assert.eq(Math.round(keys.length / 4), shard0Coll.count());
|
|
assert.eq(keys.length, coll.find().itcount());
|
|
|
|
jsTest.log('DONE!');
|
|
|
|
st.stop();
|
|
}
|