0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/jstests/noPassthrough/hybrid_index_with_updates.js

135 lines
4.5 KiB
JavaScript

/**
* Tests that write operations are accepted and result in correct indexing behavior for each phase
* of hybrid index builds.
*
* @tags: [requires_document_locking]
*/
(function() {
"use strict";
load("jstests/libs/check_log.js");
let conn = MongoRunner.runMongod();
let testDB = conn.getDB('test');
let turnFailPointOn = function(failPointName, data) {
assert.commandWorked(testDB.adminCommand(
{configureFailPoint: failPointName, mode: "alwaysOn", data: data || {}}));
};
let turnFailPointOff = function(failPointName) {
assert.commandWorked(testDB.adminCommand({configureFailPoint: failPointName, mode: "off"}));
};
let totalDocs = 0;
let crudOpsForPhase = function(coll, phase) {
let bulk = coll.initializeUnorderedBulkOp();
// Create 1000 documents in a specific range for this phase.
for (let i = 0; i < 1000; i++) {
bulk.insert({i: (phase * 1000) + i});
}
totalDocs += 1000;
if (phase <= 0) {
assert.commandWorked(bulk.execute());
return;
}
// Update 50 documents.
// For example, if phase is 2, documents [100, 150) will be updated to [-100, -150).
let start = (phase - 1) * 100;
for (let j = start; j < (100 * phase) - 50; j++) {
bulk.find({i: j}).update({$set: {i: -j}});
}
// Delete 25 documents.
// Similarly, if phase is 2, documents [150, 200) will be removed.
for (let j = start + 50; j < 100 * phase; j++) {
bulk.find({i: j}).remove();
}
totalDocs -= 50;
assert.commandWorked(bulk.execute());
};
crudOpsForPhase(testDB.hybrid, 0);
assert.eq(totalDocs, testDB.hybrid.count());
// Hang the build after the first document.
let stopKey = {'i': 1};
turnFailPointOn("hangBeforeIndexBuildOf", stopKey);
// Start the background build.
let bgBuild = startParallelShell(function() {
assert.commandWorked(db.hybrid.createIndex({i: 1}, {background: true}));
}, conn.port);
checkLog.contains(conn, "Hanging before index build of i=1");
// Phase 1: Collection scan and external sort
// Insert documents while doing the bulk build.
crudOpsForPhase(testDB.hybrid, 1);
assert.eq(totalDocs, testDB.hybrid.count());
// Enable pause after bulk dump into index.
turnFailPointOn("hangAfterIndexBuildDumpsInsertsFromBulk");
// Wait for the bulk insert to complete.
turnFailPointOff("hangBeforeIndexBuildOf");
checkLog.contains(conn, "Hanging after dumping inserts from bulk builder");
// Phase 2: First drain
// Do some updates, inserts and deletes after the bulk builder has finished.
// Hang after yielding
turnFailPointOn("hangDuringIndexBuildDrainYield", {namespace: testDB.hybrid.getFullName()});
// Enable pause after first drain.
turnFailPointOn("hangAfterIndexBuildFirstDrain");
crudOpsForPhase(testDB.hybrid, 2);
assert.eq(totalDocs, testDB.hybrid.count());
// Allow first drain to start.
turnFailPointOff("hangAfterIndexBuildDumpsInsertsFromBulk");
// Ensure the operation yields during the drain, then attempt some operations.
checkLog.contains(conn, "Hanging index build during drain yield");
assert.commandWorked(testDB.hybrid.insert({i: "during yield"}));
assert.commandWorked(testDB.hybrid.remove({i: "during yield"}));
turnFailPointOff("hangDuringIndexBuildDrainYield");
// Wait for first drain to finish.
checkLog.contains(conn, "Hanging after index build first drain");
// Phase 3: Second drain
// Enable pause after second drain.
turnFailPointOn("hangAfterIndexBuildSecondDrain");
// Add inserts that must be consumed in the second drain.
crudOpsForPhase(testDB.hybrid, 3);
assert.eq(totalDocs, testDB.hybrid.count());
// Allow second drain to start.
turnFailPointOff("hangAfterIndexBuildFirstDrain");
// Wait for second drain to finish.
checkLog.contains(conn, "Hanging after index build second drain");
// Phase 4: Final drain and commit.
// Add inserts that must be consumed in the final drain.
crudOpsForPhase(testDB.hybrid, 4);
assert.eq(totalDocs, testDB.hybrid.count());
// Allow final drain to start.
turnFailPointOff("hangAfterIndexBuildSecondDrain");
// Wait for build to complete.
bgBuild();
assert.eq(totalDocs, testDB.hybrid.count());
assert.commandWorked(testDB.hybrid.validate({full: true}));
MongoRunner.stopMongod(conn);
})();