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

SERVER-24024 If there is no "local" database at startup in queryableBackupMode, do not panic.

At startup, the logic that checks for version-specific bugs that may need to be
worked around attempts to open the "local" database to see what version of
mongod was last used to access the data files. In queryableBackupMode, if there
is no local database, this can legally fail, at least for some storage engines.
This patch recovers from that failure, rather than shutting down the server.

This patch also updates the read_only and read_only_sharded test suites, to test
cases where there is no "local" database, as this is the standard
queryableBackupMode use case.
This commit is contained in:
Andy Schwerin 2016-05-20 16:01:35 -04:00
parent cebf4c1711
commit 68ee19bbd7
2 changed files with 137 additions and 129 deletions

View File

@ -1,148 +1,153 @@
"use_strict";
var StandaloneFixture, ShardedFixture, runReadOnlyTest, zip2, cycleN;
function makeDirectoryReadOnly(dir) {
if (_isWindows()) {
run("attrib", "+r", dir, "/s");
} else {
run("chmod", "-R", "a-w", dir);
(function() {
"use_strict";
function makeDirectoryReadOnly(dir) {
if (_isWindows()) {
run("attrib", "+r", dir, "/s");
} else {
run("chmod", "-R", "a-w", dir);
}
}
}
function makeDirectoryWritable(dir) {
if (_isWindows()) {
run("attrib", "-r", dir, "/s");
} else {
run("chmod", "-R", "a+w", dir);
function makeDirectoryWritable(dir) {
if (_isWindows()) {
run("attrib", "-r", dir, "/s");
} else {
run("chmod", "-R", "a+w", dir);
}
}
}
function StandaloneFixture() {
}
StandaloneFixture = function() {};
StandaloneFixture.prototype.runLoadPhase = function runLoadPhase(test) {
this.mongod = MongoRunner.runMongod({});
this.dbpath = this.mongod.dbpath;
test.load(this.mongod.getDB("test")[test.name]);
MongoRunner.stopMongod(this.mongod);
};
StandaloneFixture.prototype.runExecPhase = function runExecPhase(test) {
try {
makeDirectoryReadOnly(this.dbpath);
var options = {
queryableBackupMode: "",
noCleanData: true,
dbpath: this.dbpath
};
this.mongod = MongoRunner.runMongod(options);
test.exec(this.mongod.getDB("test")[test.name]);
StandaloneFixture.prototype.runLoadPhase = function runLoadPhase(test) {
this.mongod = MongoRunner.runMongod({});
this.dbpath = this.mongod.dbpath;
test.load(this.mongod.getDB("test")[test.name]);
assert.commandWorked(this.mongod.getDB("local").dropDatabase());
MongoRunner.stopMongod(this.mongod);
} finally {
makeDirectoryWritable(this.dbpath);
}
};
};
function ShardedFixture() {
this.nShards = 3;
}
StandaloneFixture.prototype.runExecPhase = function runExecPhase(test) {
try {
makeDirectoryReadOnly(this.dbpath);
ShardedFixture.prototype.runLoadPhase = function runLoadPhase(test) {
this.shardingTest = new ShardingTest({nopreallocj: true, mongos: 1, shards: this.nShards});
this.paths = this.shardingTest.getDBPaths();
jsTest.log("sharding test collection...");
// Use a hashed shard key so we actually hit multiple shards.
this.shardingTest.shardColl(test.name, {_id: "hashed"});
test.load(this.shardingTest.getDB("test")[test.name]);
};
ShardedFixture.prototype.runExecPhase = function runExecPhase(test) {
jsTest.log("restarting shards...");
try {
for (var i = 0; i < this.nShards; ++i) {
var opts = {
var options = {
queryableBackupMode: "",
dbpath: this.paths[i]
noCleanData: true,
dbpath: this.dbpath
};
this.shardingTest.restartMongod(i,
opts,
() => {
makeDirectoryReadOnly(this.paths[i]);
});
this.mongod = MongoRunner.runMongod(options);
test.exec(this.mongod.getDB("test")[test.name]);
MongoRunner.stopMongod(this.mongod);
} finally {
makeDirectoryWritable(this.dbpath);
}
};
ShardedFixture = function() {
this.nShards = 3;
};
ShardedFixture.prototype.runLoadPhase = function runLoadPhase(test) {
this.shardingTest = new ShardingTest({nopreallocj: true, mongos: 1, shards: this.nShards});
this.paths = this.shardingTest.getDBPaths();
jsTest.log("sharding test collection...");
// Use a hashed shard key so we actually hit multiple shards.
this.shardingTest.shardColl(test.name, {_id: "hashed"});
test.load(this.shardingTest.getDB("test")[test.name]);
};
ShardedFixture.prototype.runExecPhase = function runExecPhase(test) {
jsTest.log("restarting shards...");
try {
for (var i = 0; i < this.nShards; ++i) {
var opts = {
queryableBackupMode: "",
dbpath: this.paths[i]
};
assert.commandWorked(this.shardingTest["d" + i].getDB("local").dropDatabase());
this.shardingTest.restartMongod(i,
opts,
() => {
makeDirectoryReadOnly(this.paths[i]);
});
}
jsTest.log("restarting mongos...");
this.shardingTest.restartMongos(0);
test.exec(this.shardingTest.getDB("test")[test.name]);
this.paths.forEach((path) => {
makeDirectoryWritable(path);
});
this.shardingTest.stop();
} finally {
this.paths.forEach((path) => {
makeDirectoryWritable(path);
});
}
};
runReadOnlyTest = function(test) {
printjson(test);
assert.eq(typeof(test.exec), "function");
assert.eq(typeof(test.load), "function");
assert.eq(typeof(test.name), "string");
var fixtureType = TestData.fixture || "standalone";
var fixture = null;
if (fixtureType === "standalone") {
fixture = new StandaloneFixture();
} else if (fixtureType === "sharded") {
fixture = new ShardedFixture();
} else {
throw new Error("fixtureType must be one of either 'standalone' or 'sharded'");
}
jsTest.log("restarting mongos...");
jsTest.log("starting load phase for test: " + test.name);
fixture.runLoadPhase(test);
this.shardingTest.restartMongos(0);
jsTest.log("starting execution phase for test: " + test.name);
fixture.runExecPhase(test);
};
test.exec(this.shardingTest.getDB("test")[test.name]);
this.paths.forEach((path) => {
makeDirectoryWritable(path);
});
this.shardingTest.stop();
} finally {
this.paths.forEach((path) => {
makeDirectoryWritable(path);
});
}
};
function runReadOnlyTest(test) {
printjson(test);
assert.eq(typeof(test.exec), "function");
assert.eq(typeof(test.load), "function");
assert.eq(typeof(test.name), "string");
var fixtureType = TestData.fixture || "standalone";
var fixture = null;
if (fixtureType === "standalone") {
fixture = new StandaloneFixture();
} else if (fixtureType === "sharded") {
fixture = new ShardedFixture();
} else {
throw new Error("fixtureType must be one of either 'standalone' or 'sharded'");
}
jsTest.log("starting load phase for test: " + test.name);
fixture.runLoadPhase(test);
jsTest.log("starting execution phase for test: " + test.name);
fixture.runExecPhase(test);
}
function * cycleN(arr, N) {
for (var i = 0; i < N; ++i) {
yield arr[i % arr.length];
}
}
function * zip2(iter1, iter2) {
var n1 = iter1.next();
var n2 = iter2.next();
while (!n1.done || !n2.done) {
var res = [];
if (!n1.done) {
res.push(n1.value);
n1 = iter1.next();
}
if (!n2.done) {
res.push(n2.value);
n2 = iter2.next();
cycleN = function * (arr, N) {
for (var i = 0; i < N; ++i) {
yield arr[i % arr.length];
}
};
yield res;
}
}
zip2 = function * (iter1, iter2) {
var n1 = iter1.next();
var n2 = iter2.next();
while (!n1.done || !n2.done) {
var res = [];
if (!n1.done) {
res.push(n1.value);
n1 = iter1.next();
}
if (!n2.done) {
res.push(n2.value);
n2 = iter2.next();
}
yield res;
}
};
}());

View File

@ -322,6 +322,9 @@ static unsigned long long checkIfReplMissingFromCommandLine(OperationContext* tx
* these versions.
*/
static bool isSubjectToSERVER23299(OperationContext* txn) {
if (storageGlobalParams.readOnly) {
return false;
}
dbHolder().openDb(txn, startupLogCollectionName.db());
AutoGetCollectionForRead autoColl(txn, startupLogCollectionName);
// No startup log or an empty one means either that the user was not running an affected