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
|
/**
* 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
* - Confirm that the pseudo commands and eval can perform fsyncLock/Unlock
*/
(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.writeOK(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.writeOK(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");
// Ensure eval is not allowed to invoke fsyncLock
assert(!db.eval('db.fsyncLock()').ok, "eval('db.fsyncLock()') should fail.");
// 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());
}());
|