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:
parent
cebf4c1711
commit
68ee19bbd7
@ -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;
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user