mirror of https://github.com/mongodb/mongo
120 lines
4.4 KiB
JavaScript
120 lines
4.4 KiB
JavaScript
/**
|
|
* Test fsyncLock functionality
|
|
* - Skip for all storage engines which don't support fsync
|
|
* - Run the fsyncLock command, confirm we lock correctly with currentOp
|
|
* - Confirm that we cannot insert during fsyncLock
|
|
* - Confirm that writes can progress after fsyncUnlock
|
|
* - Confirm that the command can be run repeatedly without breaking things
|
|
*
|
|
* @tags: [
|
|
* requires_fastcount,
|
|
* requires_fsync,
|
|
* uses_parallel_shell,
|
|
* ]
|
|
*/
|
|
(function() {
|
|
"use strict";
|
|
|
|
// Start with a clean DB.
|
|
var fsyncLockDB = db.getSisterDB('fsyncLockTestDB');
|
|
fsyncLockDB.dropDatabase();
|
|
|
|
// Tests the db.fsyncLock/fsyncUnlock features.
|
|
var storageEngine = db.serverStatus().storageEngine.name;
|
|
|
|
// As of SERVER-18899 fsyncLock/fsyncUnlock will error when called on a storage engine
|
|
// that does not support the begin/end backup commands.
|
|
var supportsFsync = db.fsyncLock();
|
|
|
|
if (!supportsFsync.ok) {
|
|
assert.commandFailedWithCode(supportsFsync, ErrorCodes.CommandNotSupported);
|
|
jsTestLog("Skipping test for " + storageEngine + " as it does not support fsync");
|
|
return;
|
|
}
|
|
db.fsyncUnlock();
|
|
|
|
var resFail = fsyncLockDB.runCommand({fsync: 1, lock: 1});
|
|
|
|
// Start with a clean DB
|
|
var fsyncLockDB = db.getSisterDB('fsyncLockTestDB');
|
|
fsyncLockDB.dropDatabase();
|
|
|
|
// Test that a single, regular write works as expected.
|
|
assert.commandWorked(fsyncLockDB.coll.insert({x: 1}));
|
|
|
|
// Test that fsyncLock doesn't work unless invoked against the admin DB.
|
|
var resFail = fsyncLockDB.runCommand({fsync: 1, lock: 1});
|
|
assert(!resFail.ok, "fsyncLock command succeeded against DB other than admin.");
|
|
|
|
// Uses admin automatically and locks the server for writes.
|
|
var fsyncLockRes = db.fsyncLock();
|
|
assert(fsyncLockRes.ok, "fsyncLock command failed against admin DB");
|
|
assert(db.currentOp().fsyncLock, "Value in db.currentOp incorrect for fsyncLocked server");
|
|
|
|
// Make sure writes are blocked. Spawn a write operation in a separate shell and make sure it
|
|
// is blocked. There is really no way to do that currently, so just check that the write didn't
|
|
// go through.
|
|
var writeOpHandle = startParallelShell("db.getSisterDB('fsyncLockTestDB').coll.insert({x:1});");
|
|
sleep(3000);
|
|
|
|
// Make sure reads can still run even though there is a pending write and also that the write
|
|
// didn't get through.
|
|
assert.eq(1, fsyncLockDB.coll.find({}).itcount());
|
|
|
|
// Unlock and make sure the insert succeeded.
|
|
var fsyncUnlockRes = db.fsyncUnlock();
|
|
assert(fsyncUnlockRes.ok, "fsyncUnlock command failed");
|
|
assert(db.currentOp().fsyncLock == null, "fsyncUnlock is not null in db.currentOp");
|
|
|
|
// Make sure the db is unlocked and the initial write made it through.
|
|
writeOpHandle();
|
|
assert.commandWorked(fsyncLockDB.coll.insert({x: 2}));
|
|
|
|
assert.eq(3, fsyncLockDB.coll.count({}));
|
|
|
|
// Issue the fsyncLock and fsyncUnlock a second time, to ensure that we can
|
|
// run this command repeatedly with no problems.
|
|
var fsyncLockRes = db.fsyncLock();
|
|
assert(fsyncLockRes.ok, "Second execution of fsyncLock command failed");
|
|
|
|
var fsyncUnlockRes = db.fsyncUnlock();
|
|
assert(fsyncUnlockRes.ok, "Second execution of fsyncUnlock command failed");
|
|
|
|
// Make sure that insert attempts made during multiple fsyncLock requests will not execute until
|
|
// all locks have been released.
|
|
fsyncLockRes = db.fsyncLock();
|
|
assert.commandWorked(fsyncLockRes);
|
|
assert(fsyncLockRes.lockCount == 1, tojson(fsyncLockRes));
|
|
let currentOp = db.currentOp();
|
|
assert.commandWorked(currentOp);
|
|
assert(currentOp.fsyncLock, "Value in db.currentOp incorrect for fsyncLocked server");
|
|
|
|
let shellHandle1 =
|
|
startParallelShell("db.getSisterDB('fsyncLockTestDB').multipleLock.insert({x:1});");
|
|
|
|
fsyncLockRes = db.fsyncLock();
|
|
assert.commandWorked(fsyncLockRes);
|
|
assert(fsyncLockRes.lockCount == 2, tojson(fsyncLockRes));
|
|
currentOp = db.currentOp();
|
|
assert.commandWorked(currentOp);
|
|
assert(currentOp.fsyncLock, "Value in db.currentOp incorrect for fsyncLocked server");
|
|
|
|
let shellHandle2 =
|
|
startParallelShell("db.getSisterDB('fsyncLockTestDB').multipleLock.insert({x:1});");
|
|
sleep(3000);
|
|
assert.eq(0, fsyncLockDB.multipleLock.find({}).itcount());
|
|
|
|
fsyncUnlockRes = db.fsyncUnlock();
|
|
assert.commandWorked(fsyncUnlockRes);
|
|
assert(fsyncUnlockRes.lockCount == 1, tojson(fsyncLockRes));
|
|
sleep(3000);
|
|
assert.eq(0, fsyncLockDB.multipleLock.find({}).itcount());
|
|
|
|
fsyncUnlockRes = db.fsyncUnlock();
|
|
assert.commandWorked(fsyncUnlockRes);
|
|
assert(fsyncUnlockRes.lockCount == 0, tojson(fsyncLockRes));
|
|
shellHandle1();
|
|
shellHandle2();
|
|
assert.eq(2, fsyncLockDB.multipleLock.find({}).itcount());
|
|
}());
|